ctf: append error causes when returning errors
[babeltrace.git] / src / plugins / ctf / common / metadata / visitor-generate-ir.c
1 /*
2 * SPDX-License-Identifier: MIT
3 *
4 * Copyright 2010 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
5 * Copyright 2015-2018 Philippe Proulx <philippe.proulx@efficios.com>
6 *
7 * Common Trace Format metadata visitor (generates CTF IR objects).
8 */
9
10 #define BT_COMP_LOG_SELF_COMP (ctx->log_cfg.self_comp)
11 #define BT_COMP_LOG_SELF_COMP_CLASS (ctx->log_cfg.self_comp_class)
12 #define BT_LOG_OUTPUT_LEVEL (ctx->log_cfg.log_level)
13 #define BT_LOG_TAG "PLUGIN/CTF/META/IR-VISITOR"
14 #include "logging/comp-logging.h"
15
16 #include <stdio.h>
17 #include <unistd.h>
18 #include <string.h>
19 #include <stdbool.h>
20 #include <stdlib.h>
21 #include <ctype.h>
22 #include "common/assert.h"
23 #include <glib.h>
24 #include <inttypes.h>
25 #include <errno.h>
26 #include "common/common.h"
27 #include "common/uuid.h"
28 #include "compat/endian.h"
29 #include <babeltrace2/babeltrace.h>
30
31 #include "logging.h"
32 #include "scanner.h"
33 #include "ast.h"
34 #include "decoder.h"
35 #include "ctf-meta.h"
36 #include "ctf-meta-visitors.h"
37
38 /* Bit value (left shift) */
39 #define _BV(_val) (1 << (_val))
40
41 /* Bit is set in a set of bits */
42 #define _IS_SET(_set, _mask) (*(_set) & (_mask))
43
44 /* Set bit in a set of bits */
45 #define _SET(_set, _mask) (*(_set) |= (_mask))
46
47 /* Try to push scope, or go to the `error` label */
48 #define _TRY_PUSH_SCOPE_OR_GOTO_ERROR() \
49 do { \
50 ret = ctx_push_scope(ctx); \
51 if (ret) { \
52 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot push scope."); \
53 goto error; \
54 } \
55 } while (0)
56
57 /* Bits for verifying existing attributes in various declarations */
58 enum {
59 _CLOCK_NAME_SET = _BV(0),
60 _CLOCK_UUID_SET = _BV(1),
61 _CLOCK_FREQ_SET = _BV(2),
62 _CLOCK_PRECISION_SET = _BV(3),
63 _CLOCK_OFFSET_S_SET = _BV(4),
64 _CLOCK_OFFSET_SET = _BV(5),
65 _CLOCK_ABSOLUTE_SET = _BV(6),
66 _CLOCK_DESCRIPTION_SET = _BV(7),
67 };
68
69 enum {
70 _INTEGER_ALIGN_SET = _BV(0),
71 _INTEGER_SIZE_SET = _BV(1),
72 _INTEGER_BASE_SET = _BV(2),
73 _INTEGER_ENCODING_SET = _BV(3),
74 _INTEGER_BYTE_ORDER_SET = _BV(4),
75 _INTEGER_SIGNED_SET = _BV(5),
76 _INTEGER_MAP_SET = _BV(6),
77 };
78
79 enum {
80 _FLOAT_ALIGN_SET = _BV(0),
81 _FLOAT_MANT_DIG_SET = _BV(1),
82 _FLOAT_EXP_DIG_SET = _BV(2),
83 _FLOAT_BYTE_ORDER_SET = _BV(3),
84 };
85
86 enum {
87 _STRING_ENCODING_SET = _BV(0),
88 };
89
90 enum {
91 _TRACE_MINOR_SET = _BV(0),
92 _TRACE_MAJOR_SET = _BV(1),
93 _TRACE_BYTE_ORDER_SET = _BV(2),
94 _TRACE_UUID_SET = _BV(3),
95 _TRACE_PACKET_HEADER_SET = _BV(4),
96 };
97
98 enum {
99 _STREAM_ID_SET = _BV(0),
100 _STREAM_PACKET_CONTEXT_SET = _BV(1),
101 _STREAM_EVENT_HEADER_SET = _BV(2),
102 _STREAM_EVENT_CONTEXT_SET = _BV(3),
103 };
104
105 enum {
106 _EVENT_NAME_SET = _BV(0),
107 _EVENT_ID_SET = _BV(1),
108 _EVENT_MODEL_EMF_URI_SET = _BV(2),
109 _EVENT_STREAM_ID_SET = _BV(3),
110 _EVENT_LOG_LEVEL_SET = _BV(4),
111 _EVENT_CONTEXT_SET = _BV(5),
112 _EVENT_FIELDS_SET = _BV(6),
113 };
114
115 enum loglevel {
116 LOG_LEVEL_EMERG = 0,
117 LOG_LEVEL_ALERT = 1,
118 LOG_LEVEL_CRIT = 2,
119 LOG_LEVEL_ERR = 3,
120 LOG_LEVEL_WARNING = 4,
121 LOG_LEVEL_NOTICE = 5,
122 LOG_LEVEL_INFO = 6,
123 LOG_LEVEL_DEBUG_SYSTEM = 7,
124 LOG_LEVEL_DEBUG_PROGRAM = 8,
125 LOG_LEVEL_DEBUG_PROCESS = 9,
126 LOG_LEVEL_DEBUG_MODULE = 10,
127 LOG_LEVEL_DEBUG_UNIT = 11,
128 LOG_LEVEL_DEBUG_FUNCTION = 12,
129 LOG_LEVEL_DEBUG_LINE = 13,
130 LOG_LEVEL_DEBUG = 14,
131 _NR_LOGLEVELS = 15,
132 };
133
134 /* Prefixes of class aliases */
135 #define _PREFIX_ALIAS 'a'
136 #define _PREFIX_ENUM 'e'
137 #define _PREFIX_STRUCT 's'
138 #define _PREFIX_VARIANT 'v'
139
140 /* First entry in a BT list */
141 #define _BT_LIST_FIRST_ENTRY(_ptr, _class, _member) \
142 bt_list_entry((_ptr)->next, _class, _member)
143
144 #define _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(_node, _attr, _entity) \
145 _BT_COMP_LOGE_APPEND_CAUSE_LINENO((_node)->lineno, \
146 "Duplicate attribute in %s: attr-name=\"%s\"", \
147 _entity, _attr)
148
149 #define _BT_COMP_LOGE_NODE(_node, _msg, args...) \
150 _BT_COMP_LOGE_LINENO((_node)->lineno, _msg, ## args)
151
152 #define _BT_COMP_LOGE_APPEND_CAUSE_NODE(_node, _msg, args...) \
153 _BT_COMP_LOGE_APPEND_CAUSE_LINENO((_node)->lineno, _msg, ## args)
154
155 #define _BT_COMP_LOGW_NODE(_node, _msg, args...) \
156 _BT_COMP_LOGW_LINENO((_node)->lineno, _msg, ## args)
157
158 #define _BT_COMP_LOGT_NODE(_node, _msg, args...) \
159 _BT_COMP_LOGT_LINENO((_node)->lineno, _msg, ## args)
160
161 /*
162 * Declaration scope of a visitor context. This represents a TSDL
163 * lexical scope, so that aliases and named structures, variants,
164 * and enumerations may be registered and looked up hierarchically.
165 */
166 struct ctx_decl_scope {
167 /*
168 * Alias name to field class.
169 *
170 * GQuark -> struct ctf_field_class * (owned by this)
171 */
172 GHashTable *decl_map;
173
174 /* Parent scope; NULL if this is the root declaration scope */
175 struct ctx_decl_scope *parent_scope;
176 };
177
178 /*
179 * Visitor context (private).
180 */
181 struct ctx {
182 struct meta_log_config log_cfg;
183
184 /* Trace IR trace class being filled (owned by this) */
185 bt_trace_class *trace_class;
186
187 /* CTF meta trace being filled (owned by this) */
188 struct ctf_trace_class *ctf_tc;
189
190 /* Current declaration scope (top of the stack) (owned by this) */
191 struct ctx_decl_scope *current_scope;
192
193 /* True if trace declaration is visited */
194 bool is_trace_visited;
195
196 /* True if this is an LTTng trace */
197 bool is_lttng;
198
199 /* Config passed by the user */
200 struct ctf_metadata_decoder_config decoder_config;
201 };
202
203 /*
204 * Visitor (public).
205 */
206 struct ctf_visitor_generate_ir;
207
208 /**
209 * Creates a new declaration scope.
210 *
211 * @param par_scope Parent scope (NULL if creating a root scope)
212 * @returns New declaration scope, or NULL on error
213 */
214 static
215 struct ctx_decl_scope *ctx_decl_scope_create(struct ctx *ctx,
216 struct ctx_decl_scope *par_scope)
217 {
218 struct ctx_decl_scope *scope;
219
220 scope = g_new(struct ctx_decl_scope, 1);
221 if (!scope) {
222 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Failed to allocate one declaration scope.");
223 goto end;
224 }
225
226 scope->decl_map = g_hash_table_new_full(g_direct_hash, g_direct_equal,
227 NULL, (GDestroyNotify) ctf_field_class_destroy);
228 scope->parent_scope = par_scope;
229
230 end:
231 return scope;
232 }
233
234 /**
235 * Destroys a declaration scope.
236 *
237 * This function does not destroy the parent scope.
238 *
239 * @param scope Scope to destroy
240 */
241 static
242 void ctx_decl_scope_destroy(struct ctx_decl_scope *scope)
243 {
244 if (!scope) {
245 goto end;
246 }
247
248 g_hash_table_destroy(scope->decl_map);
249 g_free(scope);
250
251 end:
252 return;
253 }
254
255 /**
256 * Returns the GQuark of a prefixed alias.
257 *
258 * @param prefix Prefix character
259 * @param name Name
260 * @returns Associated GQuark, or 0 on error
261 */
262 static
263 GQuark get_prefixed_named_quark(struct ctx *ctx, char prefix, const char *name)
264 {
265 GQuark qname = 0;
266
267 BT_ASSERT(name);
268
269 /* Prefix character + original string + '\0' */
270 char *prname = g_new(char, strlen(name) + 2);
271 if (!prname) {
272 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Failed to allocate a string.");
273 goto end;
274 }
275
276 sprintf(prname, "%c%s", prefix, name);
277 qname = g_quark_from_string(prname);
278 g_free(prname);
279
280 end:
281 return qname;
282 }
283
284 /**
285 * Looks up a prefixed class alias within a declaration scope.
286 *
287 * @param scope Declaration scope
288 * @param prefix Prefix character
289 * @param name Alias name
290 * @param levels Number of levels to dig into (-1 means infinite)
291 * @param copy True to return a copy
292 * @returns Declaration (owned by caller if \p copy is true),
293 * or NULL if not found
294 */
295 static
296 struct ctf_field_class *ctx_decl_scope_lookup_prefix_alias(
297 struct ctx *ctx, struct ctx_decl_scope *scope, char prefix,
298 const char *name, int levels, bool copy)
299 {
300 GQuark qname = 0;
301 int cur_levels = 0;
302 struct ctf_field_class *decl = NULL;
303 struct ctx_decl_scope *cur_scope = scope;
304
305 BT_ASSERT(scope);
306 BT_ASSERT(name);
307 qname = get_prefixed_named_quark(ctx, prefix, name);
308 if (!qname) {
309 goto end;
310 }
311
312 if (levels < 0) {
313 levels = INT_MAX;
314 }
315
316 while (cur_scope && cur_levels < levels) {
317 decl = g_hash_table_lookup(cur_scope->decl_map,
318 (gconstpointer) GUINT_TO_POINTER(qname));
319 if (decl) {
320 /* Caller's reference */
321 if (copy) {
322 decl = ctf_field_class_copy(decl);
323 BT_ASSERT(decl);
324 }
325
326 goto end;
327 }
328
329 cur_scope = cur_scope->parent_scope;
330 cur_levels++;
331 }
332
333 end:
334 return decl;
335 }
336
337 /**
338 * Looks up a class alias within a declaration scope.
339 *
340 * @param scope Declaration scope
341 * @param name Alias name
342 * @param levels Number of levels to dig into (-1 means infinite)
343 * @param copy True to return a copy
344 * @returns Declaration (owned by caller if \p copy is true),
345 * or NULL if not found
346 */
347 static
348 struct ctf_field_class *ctx_decl_scope_lookup_alias(struct ctx *ctx,
349 struct ctx_decl_scope *scope, const char *name, int levels,
350 bool copy)
351 {
352 return ctx_decl_scope_lookup_prefix_alias(ctx, scope, _PREFIX_ALIAS,
353 name, levels, copy);
354 }
355
356 /**
357 * Looks up an enumeration within a declaration scope.
358 *
359 * @param scope Declaration scope
360 * @param name Enumeration name
361 * @param levels Number of levels to dig into (-1 means infinite)
362 * @param copy True to return a copy
363 * @returns Declaration (owned by caller if \p copy is true),
364 * or NULL if not found
365 */
366 static
367 struct ctf_field_class_enum *ctx_decl_scope_lookup_enum(struct ctx *ctx,
368 struct ctx_decl_scope *scope, const char *name, int levels,
369 bool copy)
370 {
371 return (void *) ctx_decl_scope_lookup_prefix_alias(ctx, scope,
372 _PREFIX_ENUM, name, levels, copy);
373 }
374
375 /**
376 * Looks up a structure within a declaration scope.
377 *
378 * @param scope Declaration scope
379 * @param name Structure name
380 * @param levels Number of levels to dig into (-1 means infinite)
381 * @param copy True to return a copy
382 * @returns Declaration (owned by caller if \p copy is true),
383 * or NULL if not found
384 */
385 static
386 struct ctf_field_class_struct *ctx_decl_scope_lookup_struct(struct ctx *ctx,
387 struct ctx_decl_scope *scope, const char *name, int levels,
388 bool copy)
389 {
390 return (void *) ctx_decl_scope_lookup_prefix_alias(ctx, scope,
391 _PREFIX_STRUCT, name, levels, copy);
392 }
393
394 /**
395 * Looks up a variant within a declaration scope.
396 *
397 * @param scope Declaration scope
398 * @param name Variant name
399 * @param levels Number of levels to dig into (-1 means infinite)
400 * @param copy True to return a copy
401 * @returns Declaration (owned by caller if \p copy is true),
402 * or NULL if not found
403 */
404 static
405 struct ctf_field_class_variant *ctx_decl_scope_lookup_variant(struct ctx *ctx,
406 struct ctx_decl_scope *scope, const char *name, int levels,
407 bool copy)
408 {
409 return (void *) ctx_decl_scope_lookup_prefix_alias(ctx, scope,
410 _PREFIX_VARIANT, name, levels, copy);
411 }
412
413 /**
414 * Registers a prefixed class alias within a declaration scope.
415 *
416 * @param scope Declaration scope
417 * @param prefix Prefix character
418 * @param name Alias name (non-NULL)
419 * @param decl Field class to register (copied)
420 * @returns 0 if registration went okay, negative value otherwise
421 */
422 static
423 int ctx_decl_scope_register_prefix_alias(struct ctx *ctx,
424 struct ctx_decl_scope *scope, char prefix, const char *name,
425 struct ctf_field_class *decl)
426 {
427 int ret = 0;
428 GQuark qname = 0;
429
430 BT_ASSERT(scope);
431 BT_ASSERT(name);
432 BT_ASSERT(decl);
433 qname = get_prefixed_named_quark(ctx, prefix, name);
434 if (!qname) {
435 ret = -ENOMEM;
436 goto end;
437 }
438
439 /* Make sure alias does not exist in local scope */
440 if (ctx_decl_scope_lookup_prefix_alias(ctx, scope, prefix, name, 1,
441 false)) {
442 ret = -EEXIST;
443 goto end;
444 }
445
446 decl = ctf_field_class_copy(decl);
447 BT_ASSERT(decl);
448 g_hash_table_insert(scope->decl_map, GUINT_TO_POINTER(qname), decl);
449
450 end:
451 return ret;
452 }
453
454 /**
455 * Registers a class alias within a declaration scope.
456 *
457 * @param scope Declaration scope
458 * @param name Alias name (non-NULL)
459 * @param decl Field class to register (copied)
460 * @returns 0 if registration went okay, negative value otherwise
461 */
462 static
463 int ctx_decl_scope_register_alias(struct ctx *ctx, struct ctx_decl_scope *scope,
464 const char *name, struct ctf_field_class *decl)
465 {
466 return ctx_decl_scope_register_prefix_alias(ctx, scope, _PREFIX_ALIAS,
467 name, (void *) decl);
468 }
469
470 /**
471 * Registers an enumeration declaration within a declaration scope.
472 *
473 * @param scope Declaration scope
474 * @param name Enumeration name (non-NULL)
475 * @param decl Enumeration field class to register (copied)
476 * @returns 0 if registration went okay, negative value otherwise
477 */
478 static
479 int ctx_decl_scope_register_enum(struct ctx *ctx, struct ctx_decl_scope *scope,
480 const char *name, struct ctf_field_class_enum *decl)
481 {
482 return ctx_decl_scope_register_prefix_alias(ctx, scope, _PREFIX_ENUM,
483 name, (void *) decl);
484 }
485
486 /**
487 * Registers a structure declaration within a declaration scope.
488 *
489 * @param scope Declaration scope
490 * @param name Structure name (non-NULL)
491 * @param decl Structure field class to register (copied)
492 * @returns 0 if registration went okay, negative value otherwise
493 */
494 static
495 int ctx_decl_scope_register_struct(struct ctx *ctx,
496 struct ctx_decl_scope *scope, const char *name,
497 struct ctf_field_class_struct *decl)
498 {
499 return ctx_decl_scope_register_prefix_alias(ctx, scope, _PREFIX_STRUCT,
500 name, (void *) decl);
501 }
502
503 /**
504 * Registers a variant declaration within a declaration scope.
505 *
506 * @param scope Declaration scope
507 * @param name Variant name (non-NULL)
508 * @param decl Variant field class to register
509 * @returns 0 if registration went okay, negative value otherwise
510 */
511 static
512 int ctx_decl_scope_register_variant(struct ctx *ctx,
513 struct ctx_decl_scope *scope, const char *name,
514 struct ctf_field_class_variant *decl)
515 {
516 return ctx_decl_scope_register_prefix_alias(ctx, scope, _PREFIX_VARIANT,
517 name, (void *) decl);
518 }
519
520 /**
521 * Destroys a visitor context.
522 *
523 * @param ctx Visitor context to destroy
524 */
525 static
526 void ctx_destroy(struct ctx *ctx)
527 {
528 struct ctx_decl_scope *scope;
529
530 if (!ctx) {
531 goto end;
532 }
533
534 scope = ctx->current_scope;
535
536 /*
537 * Destroy all scopes, from current one to the root scope.
538 */
539 while (scope) {
540 struct ctx_decl_scope *parent_scope = scope->parent_scope;
541
542 ctx_decl_scope_destroy(scope);
543 scope = parent_scope;
544 }
545
546 bt_trace_class_put_ref(ctx->trace_class);
547
548 if (ctx->ctf_tc) {
549 ctf_trace_class_destroy(ctx->ctf_tc);
550 }
551
552 g_free(ctx);
553
554 end:
555 return;
556 }
557
558 /**
559 * Creates a new visitor context.
560 *
561 * @param trace Associated trace
562 * @returns New visitor context, or NULL on error
563 */
564 static
565 struct ctx *ctx_create(const struct ctf_metadata_decoder_config *decoder_config)
566 {
567 struct ctx *ctx = NULL;
568
569 BT_ASSERT(decoder_config);
570
571 ctx = g_new0(struct ctx, 1);
572 if (!ctx) {
573 BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR, decoder_config->log_level,
574 decoder_config->self_comp,
575 "Failed to allocate one visitor context.");
576 goto error;
577 }
578
579 ctx->log_cfg.log_level = decoder_config->log_level;
580 ctx->log_cfg.self_comp = decoder_config->self_comp;
581 ctx->log_cfg.self_comp_class = decoder_config->self_comp_class;
582
583 if (decoder_config->self_comp) {
584 ctx->trace_class = bt_trace_class_create(
585 decoder_config->self_comp);
586 if (!ctx->trace_class) {
587 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot create empty trace class.");
588 goto error;
589 }
590 }
591
592 ctx->ctf_tc = ctf_trace_class_create();
593 if (!ctx->ctf_tc) {
594 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot create CTF trace class.");
595 goto error;
596 }
597
598 /* Root declaration scope */
599 ctx->current_scope = ctx_decl_scope_create(ctx, NULL);
600 if (!ctx->current_scope) {
601 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot create declaration scope.");
602 goto error;
603 }
604
605 ctx->decoder_config = *decoder_config;
606 goto end;
607
608 error:
609 ctx_destroy(ctx);
610 ctx = NULL;
611
612 end:
613 return ctx;
614 }
615
616 /**
617 * Pushes a new declaration scope on top of a visitor context's
618 * declaration scope stack.
619 *
620 * @param ctx Visitor context
621 * @returns 0 on success, or a negative value on error
622 */
623 static
624 int ctx_push_scope(struct ctx *ctx)
625 {
626 int ret = 0;
627 struct ctx_decl_scope *new_scope;
628
629 BT_ASSERT(ctx);
630 new_scope = ctx_decl_scope_create(ctx, ctx->current_scope);
631 if (!new_scope) {
632 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot create declaration scope.");
633 ret = -ENOMEM;
634 goto end;
635 }
636
637 ctx->current_scope = new_scope;
638
639 end:
640 return ret;
641 }
642
643 static
644 void ctx_pop_scope(struct ctx *ctx)
645 {
646 struct ctx_decl_scope *parent_scope = NULL;
647
648 BT_ASSERT(ctx);
649
650 if (!ctx->current_scope) {
651 goto end;
652 }
653
654 parent_scope = ctx->current_scope->parent_scope;
655 ctx_decl_scope_destroy(ctx->current_scope);
656 ctx->current_scope = parent_scope;
657
658 end:
659 return;
660 }
661
662 static
663 int visit_field_class_specifier_list(struct ctx *ctx, struct ctf_node *ts_list,
664 struct ctf_field_class **decl);
665
666 static
667 int is_unary_string(struct bt_list_head *head)
668 {
669 int ret = TRUE;
670 struct ctf_node *node;
671
672 bt_list_for_each_entry(node, head, siblings) {
673 if (node->type != NODE_UNARY_EXPRESSION) {
674 ret = FALSE;
675 }
676
677 if (node->u.unary_expression.type != UNARY_STRING) {
678 ret = FALSE;
679 }
680 }
681
682 return ret;
683 }
684
685 static
686 const char *get_map_clock_name_value(struct bt_list_head *head)
687 {
688 int i = 0;
689 struct ctf_node *node;
690 const char *name = NULL;
691
692 bt_list_for_each_entry(node, head, siblings) {
693 char *src_string;
694 int uexpr_type = node->u.unary_expression.type;
695 int uexpr_link = node->u.unary_expression.link;
696 int cond = node->type != NODE_UNARY_EXPRESSION ||
697 uexpr_type != UNARY_STRING ||
698 !((uexpr_link != UNARY_LINK_UNKNOWN) ^ (i == 0));
699 if (cond) {
700 goto error;
701 }
702
703 /* Needs to be chained with . */
704 switch (node->u.unary_expression.link) {
705 case UNARY_DOTLINK:
706 break;
707 case UNARY_ARROWLINK:
708 case UNARY_DOTDOTDOT:
709 goto error;
710 default:
711 break;
712 }
713
714 src_string = node->u.unary_expression.u.string;
715
716 switch (i) {
717 case 0:
718 if (strcmp("clock", src_string)) {
719 goto error;
720 }
721 break;
722 case 1:
723 name = src_string;
724 break;
725 case 2:
726 if (strcmp("value", src_string)) {
727 goto error;
728 }
729 break;
730 default:
731 /* Extra identifier, unknown */
732 goto error;
733 }
734
735 i++;
736 }
737
738 return name;
739
740 error:
741 return NULL;
742 }
743
744 static
745 int is_unary_unsigned(struct bt_list_head *head)
746 {
747 int ret = TRUE;
748 struct ctf_node *node;
749
750 bt_list_for_each_entry(node, head, siblings) {
751 if (node->type != NODE_UNARY_EXPRESSION) {
752 ret = FALSE;
753 }
754
755 if (node->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT) {
756 ret = FALSE;
757 }
758 }
759
760 return ret;
761 }
762
763 static
764 int get_unary_unsigned(struct ctx *ctx, struct bt_list_head *head,
765 uint64_t *value)
766 {
767 int i = 0;
768 int ret = 0;
769 struct ctf_node *node;
770
771 *value = 0;
772
773 if (bt_list_empty(head)) {
774 ret = -1;
775 goto end;
776 }
777
778 bt_list_for_each_entry(node, head, siblings) {
779 int uexpr_type = node->u.unary_expression.type;
780 int uexpr_link = node->u.unary_expression.link;
781 int cond = node->type != NODE_UNARY_EXPRESSION ||
782 uexpr_type != UNARY_UNSIGNED_CONSTANT ||
783 uexpr_link != UNARY_LINK_UNKNOWN || i != 0;
784 if (cond) {
785 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Invalid constant unsigned integer.");
786 ret = -EINVAL;
787 goto end;
788 }
789
790 *value = node->u.unary_expression.u.unsigned_constant;
791 i++;
792 }
793
794 end:
795 return ret;
796 }
797
798 static
799 int is_unary_signed(struct bt_list_head *head)
800 {
801 int ret = TRUE;
802 struct ctf_node *node;
803
804 bt_list_for_each_entry(node, head, siblings) {
805 if (node->type != NODE_UNARY_EXPRESSION) {
806 ret = FALSE;
807 }
808
809 if (node->u.unary_expression.type != UNARY_SIGNED_CONSTANT) {
810 ret = FALSE;
811 }
812 }
813
814 return ret;
815 }
816
817 static
818 int get_unary_signed(struct bt_list_head *head, int64_t *value)
819 {
820 int i = 0;
821 int ret = 0;
822 struct ctf_node *node;
823
824 bt_list_for_each_entry(node, head, siblings) {
825 int uexpr_type = node->u.unary_expression.type;
826 int uexpr_link = node->u.unary_expression.link;
827 int cond = node->type != NODE_UNARY_EXPRESSION ||
828 (uexpr_type != UNARY_UNSIGNED_CONSTANT &&
829 uexpr_type != UNARY_SIGNED_CONSTANT) ||
830 uexpr_link != UNARY_LINK_UNKNOWN || i != 0;
831 if (cond) {
832 ret = -EINVAL;
833 goto end;
834 }
835
836 switch (uexpr_type) {
837 case UNARY_UNSIGNED_CONSTANT:
838 *value = (int64_t)
839 node->u.unary_expression.u.unsigned_constant;
840 break;
841 case UNARY_SIGNED_CONSTANT:
842 *value = node->u.unary_expression.u.signed_constant;
843 break;
844 default:
845 ret = -EINVAL;
846 goto end;
847 }
848
849 i++;
850 }
851
852 end:
853 return ret;
854 }
855
856 static
857 int get_unary_uuid(struct ctx *ctx, struct bt_list_head *head,
858 bt_uuid_t uuid)
859 {
860 return ctf_ast_get_unary_uuid(head, uuid, ctx->log_cfg.log_level,
861 ctx->log_cfg.self_comp);
862 }
863
864 static
865 int get_boolean(struct ctx *ctx, struct ctf_node *unary_expr)
866 {
867 int ret = 0;
868
869 if (unary_expr->type != NODE_UNARY_EXPRESSION) {
870 _BT_COMP_LOGE_APPEND_CAUSE_NODE(unary_expr,
871 "Expecting unary expression: node-type=%d",
872 unary_expr->type);
873 ret = -EINVAL;
874 goto end;
875 }
876
877 switch (unary_expr->u.unary_expression.type) {
878 case UNARY_UNSIGNED_CONSTANT:
879 ret = (unary_expr->u.unary_expression.u.unsigned_constant != 0);
880 break;
881 case UNARY_SIGNED_CONSTANT:
882 ret = (unary_expr->u.unary_expression.u.signed_constant != 0);
883 break;
884 case UNARY_STRING:
885 {
886 const char *str = unary_expr->u.unary_expression.u.string;
887
888 if (strcmp(str, "true") == 0 || strcmp(str, "TRUE") == 0) {
889 ret = TRUE;
890 } else if (strcmp(str, "false") == 0 || strcmp(str, "FALSE") == 0) {
891 ret = FALSE;
892 } else {
893 _BT_COMP_LOGE_APPEND_CAUSE_NODE(unary_expr,
894 "Unexpected boolean value: value=\"%s\"", str);
895 ret = -EINVAL;
896 goto end;
897 }
898 break;
899 }
900 default:
901 _BT_COMP_LOGE_APPEND_CAUSE_NODE(unary_expr,
902 "Unexpected unary expression type: node-type=%d",
903 unary_expr->u.unary_expression.type);
904 ret = -EINVAL;
905 goto end;
906 }
907
908 end:
909 return ret;
910 }
911
912 static
913 enum ctf_byte_order byte_order_from_unary_expr(struct ctx *ctx,
914 struct ctf_node *unary_expr)
915 {
916 const char *str;
917 enum ctf_byte_order bo = CTF_BYTE_ORDER_UNKNOWN;
918
919 if (unary_expr->u.unary_expression.type != UNARY_STRING) {
920 _BT_COMP_LOGE_APPEND_CAUSE_NODE(unary_expr,
921 "\"byte_order\" attribute: expecting `be`, `le`, `network`, or `native`.");
922 goto end;
923 }
924
925 str = unary_expr->u.unary_expression.u.string;
926
927 if (strcmp(str, "be") == 0 || strcmp(str, "network") == 0) {
928 bo = CTF_BYTE_ORDER_BIG;
929 } else if (strcmp(str, "le") == 0) {
930 bo = CTF_BYTE_ORDER_LITTLE;
931 } else if (strcmp(str, "native") == 0) {
932 bo = CTF_BYTE_ORDER_DEFAULT;
933 } else {
934 _BT_COMP_LOGE_APPEND_CAUSE_NODE(unary_expr,
935 "Unexpected \"byte_order\" attribute value: "
936 "expecting `be`, `le`, `network`, or `native`: value=\"%s\"",
937 str);
938 goto end;
939 }
940
941 end:
942 return bo;
943 }
944
945 static
946 enum ctf_byte_order get_real_byte_order(struct ctx *ctx,
947 struct ctf_node *uexpr)
948 {
949 enum ctf_byte_order bo = byte_order_from_unary_expr(ctx, uexpr);
950
951 if (bo == CTF_BYTE_ORDER_DEFAULT) {
952 bo = ctx->ctf_tc->default_byte_order;
953 }
954
955 return bo;
956 }
957
958 static
959 int is_align_valid(uint64_t align)
960 {
961 return (align != 0) && !(align & (align - UINT64_C(1)));
962 }
963
964 static
965 int get_class_specifier_name(struct ctx *ctx, struct ctf_node *cls_specifier,
966 GString *str)
967 {
968 int ret = 0;
969
970 if (cls_specifier->type != NODE_TYPE_SPECIFIER) {
971 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier,
972 "Unexpected node type: node-type=%d",
973 cls_specifier->type);
974 ret = -EINVAL;
975 goto end;
976 }
977
978 switch (cls_specifier->u.field_class_specifier.type) {
979 case TYPESPEC_VOID:
980 g_string_append(str, "void");
981 break;
982 case TYPESPEC_CHAR:
983 g_string_append(str, "char");
984 break;
985 case TYPESPEC_SHORT:
986 g_string_append(str, "short");
987 break;
988 case TYPESPEC_INT:
989 g_string_append(str, "int");
990 break;
991 case TYPESPEC_LONG:
992 g_string_append(str, "long");
993 break;
994 case TYPESPEC_FLOAT:
995 g_string_append(str, "float");
996 break;
997 case TYPESPEC_DOUBLE:
998 g_string_append(str, "double");
999 break;
1000 case TYPESPEC_SIGNED:
1001 g_string_append(str, "signed");
1002 break;
1003 case TYPESPEC_UNSIGNED:
1004 g_string_append(str, "unsigned");
1005 break;
1006 case TYPESPEC_BOOL:
1007 g_string_append(str, "bool");
1008 break;
1009 case TYPESPEC_COMPLEX:
1010 g_string_append(str, "_Complex");
1011 break;
1012 case TYPESPEC_IMAGINARY:
1013 g_string_append(str, "_Imaginary");
1014 break;
1015 case TYPESPEC_CONST:
1016 g_string_append(str, "const");
1017 break;
1018 case TYPESPEC_ID_TYPE:
1019 if (cls_specifier->u.field_class_specifier.id_type) {
1020 g_string_append(str,
1021 cls_specifier->u.field_class_specifier.id_type);
1022 }
1023 break;
1024 case TYPESPEC_STRUCT:
1025 {
1026 struct ctf_node *node = cls_specifier->u.field_class_specifier.node;
1027
1028 if (!node->u._struct.name) {
1029 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Unexpected empty structure field class name.");
1030 ret = -EINVAL;
1031 goto end;
1032 }
1033
1034 g_string_append(str, "struct ");
1035 g_string_append(str, node->u._struct.name);
1036 break;
1037 }
1038 case TYPESPEC_VARIANT:
1039 {
1040 struct ctf_node *node = cls_specifier->u.field_class_specifier.node;
1041
1042 if (!node->u.variant.name) {
1043 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Unexpected empty variant field class name.");
1044 ret = -EINVAL;
1045 goto end;
1046 }
1047
1048 g_string_append(str, "variant ");
1049 g_string_append(str, node->u.variant.name);
1050 break;
1051 }
1052 case TYPESPEC_ENUM:
1053 {
1054 struct ctf_node *node = cls_specifier->u.field_class_specifier.node;
1055
1056 if (!node->u._enum.enum_id) {
1057 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
1058 "Unexpected empty enumeration field class (`enum`) name.");
1059 ret = -EINVAL;
1060 goto end;
1061 }
1062
1063 g_string_append(str, "enum ");
1064 g_string_append(str, node->u._enum.enum_id);
1065 break;
1066 }
1067 case TYPESPEC_FLOATING_POINT:
1068 case TYPESPEC_INTEGER:
1069 case TYPESPEC_STRING:
1070 default:
1071 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier->u.field_class_specifier.node,
1072 "Unexpected field class specifier type: %d",
1073 cls_specifier->u.field_class_specifier.type);
1074 ret = -EINVAL;
1075 goto end;
1076 }
1077
1078 end:
1079 return ret;
1080 }
1081
1082 static
1083 int get_class_specifier_list_name(struct ctx *ctx,
1084 struct ctf_node *cls_specifier_list, GString *str)
1085 {
1086 int ret = 0;
1087 struct ctf_node *iter;
1088 int alias_item_nr = 0;
1089 struct bt_list_head *head =
1090 &cls_specifier_list->u.field_class_specifier_list.head;
1091
1092 bt_list_for_each_entry(iter, head, siblings) {
1093 if (alias_item_nr != 0) {
1094 g_string_append(str, " ");
1095 }
1096
1097 alias_item_nr++;
1098 ret = get_class_specifier_name(ctx, iter, str);
1099 if (ret) {
1100 goto end;
1101 }
1102 }
1103
1104 end:
1105 return ret;
1106 }
1107
1108 static
1109 GQuark create_class_alias_identifier(struct ctx *ctx,
1110 struct ctf_node *cls_specifier_list,
1111 struct ctf_node *node_field_class_declarator)
1112 {
1113 int ret;
1114 char *str_c;
1115 GString *str;
1116 GQuark qalias = 0;
1117 struct ctf_node *iter;
1118 struct bt_list_head *pointers =
1119 &node_field_class_declarator->u.field_class_declarator.pointers;
1120
1121 str = g_string_new("");
1122 ret = get_class_specifier_list_name(ctx, cls_specifier_list, str);
1123 if (ret) {
1124 g_string_free(str, TRUE);
1125 goto end;
1126 }
1127
1128 bt_list_for_each_entry(iter, pointers, siblings) {
1129 g_string_append(str, " *");
1130
1131 if (iter->u.pointer.const_qualifier) {
1132 g_string_append(str, " const");
1133 }
1134 }
1135
1136 str_c = g_string_free(str, FALSE);
1137 qalias = g_quark_from_string(str_c);
1138 g_free(str_c);
1139
1140 end:
1141 return qalias;
1142 }
1143
1144 static
1145 int visit_field_class_declarator(struct ctx *ctx,
1146 struct ctf_node *cls_specifier_list,
1147 GQuark *field_name, struct ctf_node *node_field_class_declarator,
1148 struct ctf_field_class **field_decl,
1149 struct ctf_field_class *nested_decl)
1150 {
1151 /*
1152 * During this whole function, nested_decl is always OURS,
1153 * whereas field_decl is an output which we create, but
1154 * belongs to the caller (it is moved).
1155 */
1156 int ret = 0;
1157 *field_decl = NULL;
1158
1159 /* Validate field class declarator node */
1160 if (node_field_class_declarator) {
1161 if (node_field_class_declarator->u.field_class_declarator.type ==
1162 TYPEDEC_UNKNOWN) {
1163 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator,
1164 "Unexpected field class declarator type: type=%d",
1165 node_field_class_declarator->u.field_class_declarator.type);
1166 ret = -EINVAL;
1167 goto error;
1168 }
1169
1170 /* TODO: GCC bitfields not supported yet */
1171 if (node_field_class_declarator->u.field_class_declarator.bitfield_len !=
1172 NULL) {
1173 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator,
1174 "GCC bitfields are not supported as of this version.");
1175 ret = -EPERM;
1176 goto error;
1177 }
1178 }
1179
1180 /* Find the right nested declaration if not provided */
1181 if (!nested_decl) {
1182 struct bt_list_head *pointers =
1183 &node_field_class_declarator->u.field_class_declarator.pointers;
1184
1185 if (node_field_class_declarator && !bt_list_empty(pointers)) {
1186 GQuark qalias;
1187
1188 /*
1189 * If we have a pointer declarator, it HAS to
1190 * be present in the field class aliases (else
1191 * fail).
1192 */
1193 qalias = create_class_alias_identifier(ctx,
1194 cls_specifier_list, node_field_class_declarator);
1195 nested_decl =
1196 ctx_decl_scope_lookup_alias(ctx,
1197 ctx->current_scope,
1198 g_quark_to_string(qalias), -1, true);
1199 if (!nested_decl) {
1200 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator,
1201 "Cannot find class alias: name=\"%s\"",
1202 g_quark_to_string(qalias));
1203 ret = -EINVAL;
1204 goto error;
1205 }
1206
1207 if (nested_decl->type == CTF_FIELD_CLASS_TYPE_INT) {
1208 /* Pointer: force integer's base to 16 */
1209 struct ctf_field_class_int *int_fc =
1210 (void *) nested_decl;
1211
1212 int_fc->disp_base =
1213 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL;
1214 }
1215 } else {
1216 ret = visit_field_class_specifier_list(ctx,
1217 cls_specifier_list, &nested_decl);
1218 if (ret) {
1219 BT_ASSERT(!nested_decl);
1220 goto error;
1221 }
1222 }
1223 }
1224
1225 BT_ASSERT(nested_decl);
1226
1227 if (!node_field_class_declarator) {
1228 *field_decl = nested_decl;
1229 nested_decl = NULL;
1230 goto end;
1231 }
1232
1233 if (node_field_class_declarator->u.field_class_declarator.type == TYPEDEC_ID) {
1234 if (node_field_class_declarator->u.field_class_declarator.u.id) {
1235 const char *id =
1236 node_field_class_declarator->u.field_class_declarator.u.id;
1237
1238 *field_name = g_quark_from_string(id);
1239 } else {
1240 *field_name = 0;
1241 }
1242
1243 *field_decl = nested_decl;
1244 nested_decl = NULL;
1245 goto end;
1246 } else {
1247 struct ctf_node *first;
1248 struct ctf_field_class *decl = NULL;
1249 struct ctf_field_class *outer_field_decl = NULL;
1250 struct bt_list_head *length =
1251 &node_field_class_declarator->
1252 u.field_class_declarator.u.nested.length;
1253
1254 /* Create array/sequence, pass nested_decl as child */
1255 if (bt_list_empty(length)) {
1256 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator,
1257 "Expecting length field reference or value.");
1258 ret = -EINVAL;
1259 goto error;
1260 }
1261
1262 first = _BT_LIST_FIRST_ENTRY(length, struct ctf_node, siblings);
1263 if (first->type != NODE_UNARY_EXPRESSION) {
1264 _BT_COMP_LOGE_APPEND_CAUSE_NODE(first,
1265 "Unexpected node type: node-type=%d",
1266 first->type);
1267 ret = -EINVAL;
1268 goto error;
1269 }
1270
1271 switch (first->u.unary_expression.type) {
1272 case UNARY_UNSIGNED_CONSTANT:
1273 {
1274 struct ctf_field_class_array *array_decl = NULL;
1275
1276 array_decl = ctf_field_class_array_create();
1277 BT_ASSERT(array_decl);
1278 array_decl->length =
1279 first->u.unary_expression.u.unsigned_constant;
1280 array_decl->base.elem_fc = nested_decl;
1281 nested_decl = NULL;
1282 decl = (void *) array_decl;
1283 break;
1284 }
1285 case UNARY_STRING:
1286 {
1287 /* Lookup unsigned integer definition, create seq. */
1288 struct ctf_field_class_sequence *seq_decl = NULL;
1289 char *length_name = ctf_ast_concatenate_unary_strings(length);
1290
1291 if (!length_name) {
1292 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator,
1293 "Cannot concatenate unary strings.");
1294 ret = -EINVAL;
1295 goto error;
1296 }
1297
1298 if (strncmp(length_name, "env.", 4) == 0) {
1299 /* This is, in fact, an array */
1300 const char *env_entry_name = &length_name[4];
1301 struct ctf_trace_class_env_entry *env_entry =
1302 ctf_trace_class_borrow_env_entry_by_name(
1303 ctx->ctf_tc, env_entry_name);
1304 struct ctf_field_class_array *array_decl;
1305
1306 if (!env_entry) {
1307 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator,
1308 "Cannot find environment entry: "
1309 "name=\"%s\"", env_entry_name);
1310 ret = -EINVAL;
1311 goto error;
1312 }
1313
1314 if (env_entry->type != CTF_TRACE_CLASS_ENV_ENTRY_TYPE_INT) {
1315 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator,
1316 "Wrong environment entry type "
1317 "(expecting integer): "
1318 "name=\"%s\"", env_entry_name);
1319 ret = -EINVAL;
1320 goto error;
1321 }
1322
1323 if (env_entry->value.i < 0) {
1324 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator,
1325 "Invalid, negative array length: "
1326 "env-entry-name=\"%s\", "
1327 "value=%" PRId64,
1328 env_entry_name,
1329 env_entry->value.i);
1330 ret = -EINVAL;
1331 goto error;
1332 }
1333
1334 array_decl = ctf_field_class_array_create();
1335 BT_ASSERT(array_decl);
1336 array_decl->length =
1337 (uint64_t) env_entry->value.i;
1338 array_decl->base.elem_fc = nested_decl;
1339 nested_decl = NULL;
1340 decl = (void *) array_decl;
1341 } else {
1342 seq_decl = ctf_field_class_sequence_create();
1343 BT_ASSERT(seq_decl);
1344 seq_decl->base.elem_fc = nested_decl;
1345 nested_decl = NULL;
1346 g_string_assign(seq_decl->length_ref,
1347 length_name);
1348 decl = (void *) seq_decl;
1349 }
1350
1351 g_free(length_name);
1352 break;
1353 }
1354 default:
1355 ret = -EINVAL;
1356 goto error;
1357 }
1358
1359 BT_ASSERT(!nested_decl);
1360 BT_ASSERT(decl);
1361 BT_ASSERT(!*field_decl);
1362
1363 /*
1364 * At this point, we found the next nested declaration.
1365 * We currently own this (and lost the ownership of
1366 * nested_decl in the meantime). Pass this next
1367 * nested declaration as the content of the outer
1368 * container, MOVING its ownership.
1369 */
1370 ret = visit_field_class_declarator(ctx, cls_specifier_list,
1371 field_name,
1372 node_field_class_declarator->
1373 u.field_class_declarator.u.nested.field_class_declarator,
1374 &outer_field_decl, decl);
1375 decl = NULL;
1376 if (ret) {
1377 BT_ASSERT(!outer_field_decl);
1378 ret = -EINVAL;
1379 goto error;
1380 }
1381
1382 BT_ASSERT(outer_field_decl);
1383 *field_decl = outer_field_decl;
1384 outer_field_decl = NULL;
1385 }
1386
1387 BT_ASSERT(*field_decl);
1388 goto end;
1389
1390 error:
1391 ctf_field_class_destroy(*field_decl);
1392 *field_decl = NULL;
1393
1394 if (ret >= 0) {
1395 ret = -1;
1396 }
1397
1398 end:
1399 ctf_field_class_destroy(nested_decl);
1400 nested_decl = NULL;
1401 return ret;
1402 }
1403
1404 static
1405 int visit_struct_decl_field(struct ctx *ctx,
1406 struct ctf_field_class_struct *struct_decl,
1407 struct ctf_node *cls_specifier_list,
1408 struct bt_list_head *field_class_declarators)
1409 {
1410 int ret = 0;
1411 struct ctf_node *iter;
1412 struct ctf_field_class *field_decl = NULL;
1413
1414 bt_list_for_each_entry(iter, field_class_declarators, siblings) {
1415 field_decl = NULL;
1416 GQuark qfield_name;
1417 const char *field_name;
1418
1419 ret = visit_field_class_declarator(ctx, cls_specifier_list,
1420 &qfield_name, iter, &field_decl, NULL);
1421 if (ret) {
1422 BT_ASSERT(!field_decl);
1423 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list,
1424 "Cannot visit field class declarator: ret=%d", ret);
1425 goto error;
1426 }
1427
1428 BT_ASSERT(field_decl);
1429 field_name = g_quark_to_string(qfield_name);
1430
1431 /* Check if field with same name already exists */
1432 if (ctf_field_class_struct_borrow_member_by_name(
1433 struct_decl, field_name)) {
1434 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list,
1435 "Duplicate field in structure field class: "
1436 "field-name=\"%s\"", field_name);
1437 ret = -EINVAL;
1438 goto error;
1439 }
1440
1441 /* Add field to structure */
1442 ctf_field_class_struct_append_member(struct_decl,
1443 field_name, field_decl);
1444 field_decl = NULL;
1445 }
1446
1447 return 0;
1448
1449 error:
1450 ctf_field_class_destroy(field_decl);
1451 field_decl = NULL;
1452 return ret;
1453 }
1454
1455 static
1456 int visit_variant_decl_field(struct ctx *ctx,
1457 struct ctf_field_class_variant *variant_decl,
1458 struct ctf_node *cls_specifier_list,
1459 struct bt_list_head *field_class_declarators)
1460 {
1461 int ret = 0;
1462 struct ctf_node *iter;
1463 struct ctf_field_class *field_decl = NULL;
1464
1465 bt_list_for_each_entry(iter, field_class_declarators, siblings) {
1466 field_decl = NULL;
1467 GQuark qfield_name;
1468 const char *field_name;
1469
1470 ret = visit_field_class_declarator(ctx, cls_specifier_list,
1471 &qfield_name, iter, &field_decl, NULL);
1472 if (ret) {
1473 BT_ASSERT(!field_decl);
1474 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list,
1475 "Cannot visit field class declarator: ret=%d", ret);
1476 goto error;
1477 }
1478
1479 BT_ASSERT(field_decl);
1480 field_name = g_quark_to_string(qfield_name);
1481
1482 /* Check if field with same name already exists */
1483 if (ctf_field_class_variant_borrow_option_by_name(
1484 variant_decl, field_name)) {
1485 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list,
1486 "Duplicate field in variant field class: "
1487 "field-name=\"%s\"", field_name);
1488 ret = -EINVAL;
1489 goto error;
1490 }
1491
1492 /* Add field to structure */
1493 ctf_field_class_variant_append_option(variant_decl,
1494 field_name, field_decl);
1495 field_decl = NULL;
1496 }
1497
1498 return 0;
1499
1500 error:
1501 ctf_field_class_destroy(field_decl);
1502 field_decl = NULL;
1503 return ret;
1504 }
1505
1506 static
1507 int visit_field_class_def(struct ctx *ctx, struct ctf_node *cls_specifier_list,
1508 struct bt_list_head *field_class_declarators)
1509 {
1510 int ret = 0;
1511 GQuark qidentifier;
1512 struct ctf_node *iter;
1513 struct ctf_field_class *class_decl = NULL;
1514
1515 bt_list_for_each_entry(iter, field_class_declarators, siblings) {
1516 ret = visit_field_class_declarator(ctx, cls_specifier_list,
1517 &qidentifier, iter, &class_decl, NULL);
1518 if (ret) {
1519 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter,
1520 "Cannot visit field class declarator: ret=%d", ret);
1521 ret = -EINVAL;
1522 goto end;
1523 }
1524
1525 /* Do not allow field class def and alias of untagged variants */
1526 if (class_decl->type == CTF_FIELD_CLASS_TYPE_VARIANT) {
1527 struct ctf_field_class_variant *var_fc =
1528 (void *) class_decl;
1529
1530 if (var_fc->tag_path.path->len == 0) {
1531 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter,
1532 "Type definition of untagged variant field class is not allowed.");
1533 ret = -EPERM;
1534 goto end;
1535 }
1536 }
1537
1538 ret = ctx_decl_scope_register_alias(ctx, ctx->current_scope,
1539 g_quark_to_string(qidentifier), class_decl);
1540 if (ret) {
1541 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter,
1542 "Cannot register field class alias: name=\"%s\"",
1543 g_quark_to_string(qidentifier));
1544 goto end;
1545 }
1546 }
1547
1548 end:
1549 ctf_field_class_destroy(class_decl);
1550 class_decl = NULL;
1551 return ret;
1552 }
1553
1554 static
1555 int visit_field_class_alias(struct ctx *ctx, struct ctf_node *target,
1556 struct ctf_node *alias)
1557 {
1558 int ret = 0;
1559 GQuark qalias;
1560 struct ctf_node *node;
1561 GQuark qdummy_field_name;
1562 struct ctf_field_class *class_decl = NULL;
1563
1564 /* Create target field class */
1565 if (bt_list_empty(&target->u.field_class_alias_target.field_class_declarators)) {
1566 node = NULL;
1567 } else {
1568 node = _BT_LIST_FIRST_ENTRY(
1569 &target->u.field_class_alias_target.field_class_declarators,
1570 struct ctf_node, siblings);
1571 }
1572
1573 ret = visit_field_class_declarator(ctx,
1574 target->u.field_class_alias_target.field_class_specifier_list,
1575 &qdummy_field_name, node, &class_decl, NULL);
1576 if (ret) {
1577 BT_ASSERT(!class_decl);
1578 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
1579 "Cannot visit field class declarator: ret=%d", ret);
1580 goto end;
1581 }
1582
1583 /* Do not allow field class def and alias of untagged variants */
1584 if (class_decl->type == CTF_FIELD_CLASS_TYPE_VARIANT) {
1585 struct ctf_field_class_variant *var_fc = (void *) class_decl;
1586
1587 if (var_fc->tag_path.path->len == 0) {
1588 _BT_COMP_LOGE_APPEND_CAUSE_NODE(target,
1589 "Type definition of untagged variant field class is not allowed.");
1590 ret = -EPERM;
1591 goto end;
1592 }
1593 }
1594
1595 /*
1596 * The semantic validator does not check whether the target is
1597 * abstract or not (if it has an identifier). Check it here.
1598 */
1599 if (qdummy_field_name != 0) {
1600 _BT_COMP_LOGE_APPEND_CAUSE_NODE(target,
1601 "Expecting empty identifier: id=\"%s\"",
1602 g_quark_to_string(qdummy_field_name));
1603 ret = -EINVAL;
1604 goto end;
1605 }
1606
1607 /* Create alias identifier */
1608 node = _BT_LIST_FIRST_ENTRY(&alias->u.field_class_alias_name.field_class_declarators,
1609 struct ctf_node, siblings);
1610 qalias = create_class_alias_identifier(ctx,
1611 alias->u.field_class_alias_name.field_class_specifier_list, node);
1612 ret = ctx_decl_scope_register_alias(ctx, ctx->current_scope,
1613 g_quark_to_string(qalias), class_decl);
1614 if (ret) {
1615 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
1616 "Cannot register class alias: name=\"%s\"",
1617 g_quark_to_string(qalias));
1618 goto end;
1619 }
1620
1621 end:
1622 ctf_field_class_destroy(class_decl);
1623 class_decl = NULL;
1624 return ret;
1625 }
1626
1627 static
1628 int visit_struct_decl_entry(struct ctx *ctx, struct ctf_node *entry_node,
1629 struct ctf_field_class_struct *struct_decl)
1630 {
1631 int ret = 0;
1632
1633 switch (entry_node->type) {
1634 case NODE_TYPEDEF:
1635 ret = visit_field_class_def(ctx,
1636 entry_node->u.field_class_def.field_class_specifier_list,
1637 &entry_node->u.field_class_def.field_class_declarators);
1638 if (ret) {
1639 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node,
1640 "Cannot add field class found in structure field class: ret=%d",
1641 ret);
1642 goto end;
1643 }
1644 break;
1645 case NODE_TYPEALIAS:
1646 ret = visit_field_class_alias(ctx, entry_node->u.field_class_alias.target,
1647 entry_node->u.field_class_alias.alias);
1648 if (ret) {
1649 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node,
1650 "Cannot add field class alias found in structure field class: ret=%d",
1651 ret);
1652 goto end;
1653 }
1654 break;
1655 case NODE_STRUCT_OR_VARIANT_DECLARATION:
1656 /* Field */
1657 ret = visit_struct_decl_field(ctx, struct_decl,
1658 entry_node->u.struct_or_variant_declaration.
1659 field_class_specifier_list,
1660 &entry_node->u.struct_or_variant_declaration.
1661 field_class_declarators);
1662 if (ret) {
1663 goto end;
1664 }
1665 break;
1666 default:
1667 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node,
1668 "Unexpected node type: node-type=%d", entry_node->type);
1669 ret = -EINVAL;
1670 goto end;
1671 }
1672
1673 end:
1674 return ret;
1675 }
1676
1677 static
1678 int visit_variant_decl_entry(struct ctx *ctx, struct ctf_node *entry_node,
1679 struct ctf_field_class_variant *variant_decl)
1680 {
1681 int ret = 0;
1682
1683 switch (entry_node->type) {
1684 case NODE_TYPEDEF:
1685 ret = visit_field_class_def(ctx,
1686 entry_node->u.field_class_def.field_class_specifier_list,
1687 &entry_node->u.field_class_def.field_class_declarators);
1688 if (ret) {
1689 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node,
1690 "Cannot add field class found in variant field class: ret=%d",
1691 ret);
1692 goto end;
1693 }
1694 break;
1695 case NODE_TYPEALIAS:
1696 ret = visit_field_class_alias(ctx, entry_node->u.field_class_alias.target,
1697 entry_node->u.field_class_alias.alias);
1698 if (ret) {
1699 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node,
1700 "Cannot add field class alias found in variant field class: ret=%d",
1701 ret);
1702 goto end;
1703 }
1704 break;
1705 case NODE_STRUCT_OR_VARIANT_DECLARATION:
1706 /* Field */
1707 ret = visit_variant_decl_field(ctx, variant_decl,
1708 entry_node->u.struct_or_variant_declaration.
1709 field_class_specifier_list,
1710 &entry_node->u.struct_or_variant_declaration.
1711 field_class_declarators);
1712 if (ret) {
1713 goto end;
1714 }
1715 break;
1716 default:
1717 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node,
1718 "Unexpected node type: node-type=%d",
1719 entry_node->type);
1720 ret = -EINVAL;
1721 goto end;
1722 }
1723
1724 end:
1725 return ret;
1726 }
1727
1728 static
1729 int visit_struct_decl(struct ctx *ctx, const char *name,
1730 struct bt_list_head *decl_list, int has_body,
1731 struct bt_list_head *min_align,
1732 struct ctf_field_class_struct **struct_decl)
1733 {
1734 int ret = 0;
1735
1736 BT_ASSERT(struct_decl);
1737 *struct_decl = NULL;
1738
1739 /* For named struct (without body), lookup in declaration scope */
1740 if (!has_body) {
1741 if (!name) {
1742 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Bodyless structure field class: missing name.");
1743 ret = -EPERM;
1744 goto error;
1745 }
1746
1747 *struct_decl = ctx_decl_scope_lookup_struct(ctx, ctx->current_scope,
1748 name, -1, true);
1749 if (!*struct_decl) {
1750 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot find structure field class: name=\"struct %s\"",
1751 name);
1752 ret = -EINVAL;
1753 goto error;
1754 }
1755 } else {
1756 struct ctf_node *entry_node;
1757 uint64_t min_align_value = 0;
1758
1759 if (name) {
1760 if (ctx_decl_scope_lookup_struct(ctx,
1761 ctx->current_scope, name, 1, false)) {
1762 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Structure field class already declared in local scope: "
1763 "name=\"struct %s\"", name);
1764 ret = -EINVAL;
1765 goto error;
1766 }
1767 }
1768
1769 if (!bt_list_empty(min_align)) {
1770 ret = get_unary_unsigned(ctx, min_align,
1771 &min_align_value);
1772 if (ret) {
1773 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Unexpected unary expression for structure field class's `align` attribute: "
1774 "ret=%d", ret);
1775 goto error;
1776 }
1777 }
1778
1779 *struct_decl = ctf_field_class_struct_create();
1780 BT_ASSERT(*struct_decl);
1781
1782 if (min_align_value != 0) {
1783 (*struct_decl)->base.alignment = min_align_value;
1784 }
1785
1786 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
1787
1788 bt_list_for_each_entry(entry_node, decl_list, siblings) {
1789 ret = visit_struct_decl_entry(ctx, entry_node,
1790 *struct_decl);
1791 if (ret) {
1792 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node,
1793 "Cannot visit structure field class entry: "
1794 "ret=%d", ret);
1795 ctx_pop_scope(ctx);
1796 goto error;
1797 }
1798 }
1799
1800 ctx_pop_scope(ctx);
1801
1802 if (name) {
1803 ret = ctx_decl_scope_register_struct(ctx,
1804 ctx->current_scope, name, *struct_decl);
1805 if (ret) {
1806 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot register structure field class in declaration scope: "
1807 "name=\"struct %s\", ret=%d", name, ret);
1808 goto error;
1809 }
1810 }
1811 }
1812
1813 return 0;
1814
1815 error:
1816 ctf_field_class_destroy((void *) *struct_decl);
1817 *struct_decl = NULL;
1818 return ret;
1819 }
1820
1821 static
1822 int visit_variant_decl(struct ctx *ctx, const char *name,
1823 const char *tag, struct bt_list_head *decl_list,
1824 int has_body, struct ctf_field_class_variant **variant_decl)
1825 {
1826 int ret = 0;
1827 struct ctf_field_class_variant *untagged_variant_decl = NULL;
1828
1829 BT_ASSERT(variant_decl);
1830 *variant_decl = NULL;
1831
1832 /* For named variant (without body), lookup in declaration scope */
1833 if (!has_body) {
1834 if (!name) {
1835 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Bodyless variant field class: missing name.");
1836 ret = -EPERM;
1837 goto error;
1838 }
1839
1840 untagged_variant_decl =
1841 ctx_decl_scope_lookup_variant(ctx, ctx->current_scope,
1842 name, -1, true);
1843 if (!untagged_variant_decl) {
1844 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot find variant field class: name=\"variant %s\"",
1845 name);
1846 ret = -EINVAL;
1847 goto error;
1848 }
1849 } else {
1850 struct ctf_node *entry_node;
1851
1852 if (name) {
1853 if (ctx_decl_scope_lookup_variant(ctx,
1854 ctx->current_scope, name, 1, false)) {
1855 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Variant field class already declared in local scope: "
1856 "name=\"variant %s\"", name);
1857 ret = -EINVAL;
1858 goto error;
1859 }
1860 }
1861
1862 untagged_variant_decl = ctf_field_class_variant_create();
1863 BT_ASSERT(untagged_variant_decl);
1864 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
1865
1866 bt_list_for_each_entry(entry_node, decl_list, siblings) {
1867 ret = visit_variant_decl_entry(ctx, entry_node,
1868 untagged_variant_decl);
1869 if (ret) {
1870 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node,
1871 "Cannot visit variant field class entry: "
1872 "ret=%d", ret);
1873 ctx_pop_scope(ctx);
1874 goto error;
1875 }
1876 }
1877
1878 ctx_pop_scope(ctx);
1879
1880 if (name) {
1881 ret = ctx_decl_scope_register_variant(ctx,
1882 ctx->current_scope, name,
1883 untagged_variant_decl);
1884 if (ret) {
1885 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot register variant field class in declaration scope: "
1886 "name=\"variant %s\", ret=%d", name, ret);
1887 goto error;
1888 }
1889 }
1890 }
1891
1892 /*
1893 * If tagged, create tagged variant and return; otherwise
1894 * return untagged variant.
1895 */
1896 if (!tag) {
1897 *variant_decl = untagged_variant_decl;
1898 untagged_variant_decl = NULL;
1899 } else {
1900 /*
1901 * At this point, we have a fresh untagged variant; nobody
1902 * else owns it. Set its tag now.
1903 */
1904 g_string_assign(untagged_variant_decl->tag_ref, tag);
1905 *variant_decl = untagged_variant_decl;
1906 untagged_variant_decl = NULL;
1907 }
1908
1909 BT_ASSERT(!untagged_variant_decl);
1910 BT_ASSERT(*variant_decl);
1911 return 0;
1912
1913 error:
1914 ctf_field_class_destroy((void *) untagged_variant_decl);
1915 untagged_variant_decl = NULL;
1916 ctf_field_class_destroy((void *) *variant_decl);
1917 *variant_decl = NULL;
1918 return ret;
1919 }
1920
1921 struct uori {
1922 bool is_signed;
1923 union {
1924 uint64_t u;
1925 uint64_t i;
1926 } value;
1927 };
1928
1929 static
1930 int visit_enum_decl_entry(struct ctx *ctx, struct ctf_node *enumerator,
1931 struct ctf_field_class_enum *enum_decl, struct uori *last)
1932 {
1933 int ret = 0;
1934 int nr_vals = 0;
1935 struct ctf_node *iter;
1936 struct uori start = {
1937 .is_signed = false,
1938 .value.u = 0,
1939 };
1940 struct uori end = {
1941 .is_signed = false,
1942 .value.u = 0,
1943 };
1944 const char *label = enumerator->u.enumerator.id;
1945 struct bt_list_head *values = &enumerator->u.enumerator.values;
1946
1947 bt_list_for_each_entry(iter, values, siblings) {
1948 struct uori *target;
1949
1950 if (iter->type != NODE_UNARY_EXPRESSION) {
1951 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter,
1952 "Wrong expression for enumeration field class label: "
1953 "node-type=%d, label=\"%s\"", iter->type,
1954 label);
1955 ret = -EINVAL;
1956 goto error;
1957 }
1958
1959 if (nr_vals == 0) {
1960 target = &start;
1961 } else {
1962 target = &end;
1963 }
1964
1965 switch (iter->u.unary_expression.type) {
1966 case UNARY_SIGNED_CONSTANT:
1967 target->is_signed = true;
1968 target->value.i =
1969 iter->u.unary_expression.u.signed_constant;
1970 break;
1971 case UNARY_UNSIGNED_CONSTANT:
1972 target->is_signed = false;
1973 target->value.u =
1974 iter->u.unary_expression.u.unsigned_constant;
1975 break;
1976 default:
1977 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter,
1978 "Invalid enumeration field class entry: "
1979 "expecting constant signed or unsigned integer: "
1980 "node-type=%d, label=\"%s\"",
1981 iter->u.unary_expression.type, label);
1982 ret = -EINVAL;
1983 goto error;
1984 }
1985
1986 if (nr_vals > 1) {
1987 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter,
1988 "Invalid enumeration field class entry: label=\"%s\"",
1989 label);
1990 ret = -EINVAL;
1991 goto error;
1992 }
1993
1994 nr_vals++;
1995 }
1996
1997 if (nr_vals == 0) {
1998 start = *last;
1999 }
2000
2001 if (nr_vals <= 1) {
2002 end = start;
2003 }
2004
2005 if (end.is_signed) {
2006 last->value.i = end.value.i + 1;
2007 } else {
2008 last->value.u = end.value.u + 1;
2009 }
2010
2011 ctf_field_class_enum_map_range(enum_decl, label,
2012 start.value.u, end.value.u);
2013 return 0;
2014
2015 error:
2016 return ret;
2017 }
2018
2019 static
2020 int visit_enum_decl(struct ctx *ctx, const char *name,
2021 struct ctf_node *container_cls,
2022 struct bt_list_head *enumerator_list,
2023 int has_body, struct ctf_field_class_enum **enum_decl)
2024 {
2025 int ret = 0;
2026 GQuark qdummy_id;
2027 struct ctf_field_class_int *integer_decl = NULL;
2028
2029 BT_ASSERT(enum_decl);
2030 *enum_decl = NULL;
2031
2032 /* For named enum (without body), lookup in declaration scope */
2033 if (!has_body) {
2034 if (!name) {
2035 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Bodyless enumeration field class: missing name.");
2036 ret = -EPERM;
2037 goto error;
2038 }
2039
2040 *enum_decl = ctx_decl_scope_lookup_enum(ctx, ctx->current_scope,
2041 name, -1, true);
2042 if (!*enum_decl) {
2043 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot find enumeration field class: "
2044 "name=\"enum %s\"", name);
2045 ret = -EINVAL;
2046 goto error;
2047 }
2048 } else {
2049 struct ctf_node *iter;
2050 struct uori last_value = {
2051 .is_signed = false,
2052 .value.u = 0,
2053 };
2054
2055 if (name) {
2056 if (ctx_decl_scope_lookup_enum(ctx, ctx->current_scope,
2057 name, 1, false)) {
2058 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Enumeration field class already declared in local scope: "
2059 "name=\"enum %s\"", name);
2060 ret = -EINVAL;
2061 goto error;
2062 }
2063 }
2064
2065 if (!container_cls) {
2066 integer_decl = (void *) ctx_decl_scope_lookup_alias(ctx,
2067 ctx->current_scope, "int", -1, true);
2068 if (!integer_decl) {
2069 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot find implicit `int` field class alias for enumeration field class.");
2070 ret = -EINVAL;
2071 goto error;
2072 }
2073 } else {
2074 ret = visit_field_class_declarator(ctx, container_cls,
2075 &qdummy_id, NULL, (void *) &integer_decl,
2076 NULL);
2077 if (ret) {
2078 BT_ASSERT(!integer_decl);
2079 ret = -EINVAL;
2080 goto error;
2081 }
2082 }
2083
2084 BT_ASSERT(integer_decl);
2085
2086 if (integer_decl->base.base.type != CTF_FIELD_CLASS_TYPE_INT) {
2087 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Container field class for enumeration field class is not an integer field class: "
2088 "fc-type=%d", integer_decl->base.base.type);
2089 ret = -EINVAL;
2090 goto error;
2091 }
2092
2093 *enum_decl = ctf_field_class_enum_create();
2094 BT_ASSERT(*enum_decl);
2095 (*enum_decl)->base.base.base.alignment =
2096 integer_decl->base.base.alignment;
2097 ctf_field_class_int_copy_content((void *) *enum_decl,
2098 (void *) integer_decl);
2099 last_value.is_signed = (*enum_decl)->base.is_signed;
2100
2101 bt_list_for_each_entry(iter, enumerator_list, siblings) {
2102 ret = visit_enum_decl_entry(ctx, iter, *enum_decl,
2103 &last_value);
2104 if (ret) {
2105 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter,
2106 "Cannot visit enumeration field class entry: "
2107 "ret=%d", ret);
2108 goto error;
2109 }
2110 }
2111
2112 if (name) {
2113 ret = ctx_decl_scope_register_enum(ctx,
2114 ctx->current_scope, name, *enum_decl);
2115 if (ret) {
2116 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot register enumeration field class in declaration scope: "
2117 "ret=%d", ret);
2118 goto error;
2119 }
2120 }
2121 }
2122
2123 goto end;
2124
2125 error:
2126 ctf_field_class_destroy((void *) *enum_decl);
2127 *enum_decl = NULL;
2128
2129 end:
2130 ctf_field_class_destroy((void *) integer_decl);
2131 integer_decl = NULL;
2132 return ret;
2133 }
2134
2135 static
2136 int visit_field_class_specifier(struct ctx *ctx,
2137 struct ctf_node *cls_specifier_list,
2138 struct ctf_field_class **decl)
2139 {
2140 int ret = 0;
2141 GString *str = NULL;
2142
2143 *decl = NULL;
2144 str = g_string_new("");
2145 ret = get_class_specifier_list_name(ctx, cls_specifier_list, str);
2146 if (ret) {
2147 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list,
2148 "Cannot get field class specifier list's name: ret=%d", ret);
2149 goto error;
2150 }
2151
2152 *decl = ctx_decl_scope_lookup_alias(ctx, ctx->current_scope, str->str,
2153 -1, true);
2154 if (!*decl) {
2155 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list,
2156 "Cannot find field class alias: name=\"%s\"", str->str);
2157 ret = -EINVAL;
2158 goto error;
2159 }
2160
2161 goto end;
2162
2163 error:
2164 ctf_field_class_destroy(*decl);
2165 *decl = NULL;
2166
2167 end:
2168 if (str) {
2169 g_string_free(str, TRUE);
2170 }
2171
2172 return ret;
2173 }
2174
2175 static
2176 int visit_integer_decl(struct ctx *ctx,
2177 struct bt_list_head *expressions,
2178 struct ctf_field_class_int **integer_decl)
2179 {
2180 int set = 0;
2181 int ret = 0;
2182 int signedness = 0;
2183 struct ctf_node *expression;
2184 uint64_t alignment = 0, size = 0;
2185 struct ctf_clock_class *mapped_clock_class = NULL;
2186 enum ctf_encoding encoding = CTF_ENCODING_NONE;
2187 bt_field_class_integer_preferred_display_base base =
2188 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL;
2189 enum ctf_byte_order byte_order = ctx->ctf_tc->default_byte_order;
2190
2191 *integer_decl = NULL;
2192
2193 bt_list_for_each_entry(expression, expressions, siblings) {
2194 struct ctf_node *left, *right;
2195
2196 left = _BT_LIST_FIRST_ENTRY(&expression->u.ctf_expression.left,
2197 struct ctf_node, siblings);
2198 right = _BT_LIST_FIRST_ENTRY(
2199 &expression->u.ctf_expression.right, struct ctf_node,
2200 siblings);
2201
2202 if (left->u.unary_expression.type != UNARY_STRING) {
2203 _BT_COMP_LOGE_APPEND_CAUSE_NODE(left,
2204 "Unexpected unary expression type: type=%d",
2205 left->u.unary_expression.type);
2206 ret = -EINVAL;
2207 goto error;
2208 }
2209
2210 if (strcmp(left->u.unary_expression.u.string, "signed") == 0) {
2211 if (_IS_SET(&set, _INTEGER_SIGNED_SET)) {
2212 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "signed",
2213 "integer field class");
2214 ret = -EPERM;
2215 goto error;
2216 }
2217
2218 signedness = get_boolean(ctx, right);
2219 if (signedness < 0) {
2220 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
2221 "Invalid boolean value for integer field class's `signed` attribute: "
2222 "ret=%d", ret);
2223 ret = -EINVAL;
2224 goto error;
2225 }
2226
2227 _SET(&set, _INTEGER_SIGNED_SET);
2228 } else if (strcmp(left->u.unary_expression.u.string, "byte_order") == 0) {
2229 if (_IS_SET(&set, _INTEGER_BYTE_ORDER_SET)) {
2230 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "byte_order",
2231 "integer field class");
2232 ret = -EPERM;
2233 goto error;
2234 }
2235
2236 byte_order = get_real_byte_order(ctx, right);
2237 if (byte_order == CTF_BYTE_ORDER_UNKNOWN) {
2238 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
2239 "Invalid `byte_order` attribute in integer field class: "
2240 "ret=%d", ret);
2241 ret = -EINVAL;
2242 goto error;
2243 }
2244
2245 _SET(&set, _INTEGER_BYTE_ORDER_SET);
2246 } else if (strcmp(left->u.unary_expression.u.string, "size") == 0) {
2247 if (_IS_SET(&set, _INTEGER_SIZE_SET)) {
2248 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "size",
2249 "integer field class");
2250 ret = -EPERM;
2251 goto error;
2252 }
2253
2254 if (right->u.unary_expression.type !=
2255 UNARY_UNSIGNED_CONSTANT) {
2256 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
2257 "Invalid `size` attribute in integer field class: "
2258 "expecting unsigned constant integer: "
2259 "node-type=%d",
2260 right->u.unary_expression.type);
2261 ret = -EINVAL;
2262 goto error;
2263 }
2264
2265 size = right->u.unary_expression.u.unsigned_constant;
2266 if (size == 0) {
2267 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
2268 "Invalid `size` attribute in integer field class: "
2269 "expecting positive constant integer: "
2270 "size=%" PRIu64, size);
2271 ret = -EINVAL;
2272 goto error;
2273 } else if (size > 64) {
2274 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
2275 "Invalid `size` attribute in integer field class: "
2276 "integer fields over 64 bits are not supported as of this version: "
2277 "size=%" PRIu64, size);
2278 ret = -EINVAL;
2279 goto error;
2280 }
2281
2282 _SET(&set, _INTEGER_SIZE_SET);
2283 } else if (strcmp(left->u.unary_expression.u.string, "align") == 0) {
2284 if (_IS_SET(&set, _INTEGER_ALIGN_SET)) {
2285 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "align",
2286 "integer field class");
2287 ret = -EPERM;
2288 goto error;
2289 }
2290
2291 if (right->u.unary_expression.type !=
2292 UNARY_UNSIGNED_CONSTANT) {
2293 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
2294 "Invalid `align` attribute in integer field class: "
2295 "expecting unsigned constant integer: "
2296 "node-type=%d",
2297 right->u.unary_expression.type);
2298 ret = -EINVAL;
2299 goto error;
2300 }
2301
2302 alignment =
2303 right->u.unary_expression.u.unsigned_constant;
2304 if (!is_align_valid(alignment)) {
2305 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
2306 "Invalid `align` attribute in integer field class: "
2307 "expecting power of two: "
2308 "align=%" PRIu64, alignment);
2309 ret = -EINVAL;
2310 goto error;
2311 }
2312
2313 _SET(&set, _INTEGER_ALIGN_SET);
2314 } else if (strcmp(left->u.unary_expression.u.string, "base") == 0) {
2315 if (_IS_SET(&set, _INTEGER_BASE_SET)) {
2316 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "base",
2317 "integer field class");
2318 ret = -EPERM;
2319 goto error;
2320 }
2321
2322 switch (right->u.unary_expression.type) {
2323 case UNARY_UNSIGNED_CONSTANT:
2324 {
2325 uint64_t constant = right->u.unary_expression.
2326 u.unsigned_constant;
2327
2328 switch (constant) {
2329 case 2:
2330 base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY;
2331 break;
2332 case 8:
2333 base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL;
2334 break;
2335 case 10:
2336 base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL;
2337 break;
2338 case 16:
2339 base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL;
2340 break;
2341 default:
2342 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
2343 "Invalid `base` attribute in integer field class: "
2344 "base=%" PRIu64,
2345 right->u.unary_expression.u.unsigned_constant);
2346 ret = -EINVAL;
2347 goto error;
2348 }
2349 break;
2350 }
2351 case UNARY_STRING:
2352 {
2353 char *s_right = ctf_ast_concatenate_unary_strings(
2354 &expression->u.ctf_expression.right);
2355 if (!s_right) {
2356 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
2357 "Unexpected unary expression for integer field class's `base` attribute.");
2358 ret = -EINVAL;
2359 goto error;
2360 }
2361
2362 if (strcmp(s_right, "decimal") == 0 ||
2363 strcmp(s_right, "dec") == 0 ||
2364 strcmp(s_right, "d") == 0 ||
2365 strcmp(s_right, "i") == 0 ||
2366 strcmp(s_right, "u") == 0) {
2367 base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL;
2368 } else if (strcmp(s_right, "hexadecimal") == 0 ||
2369 strcmp(s_right, "hex") == 0 ||
2370 strcmp(s_right, "x") == 0 ||
2371 strcmp(s_right, "X") == 0 ||
2372 strcmp(s_right, "p") == 0) {
2373 base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL;
2374 } else if (strcmp(s_right, "octal") == 0 ||
2375 strcmp(s_right, "oct") == 0 ||
2376 strcmp(s_right, "o") == 0) {
2377 base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL;
2378 } else if (strcmp(s_right, "binary") == 0 ||
2379 strcmp(s_right, "b") == 0) {
2380 base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY;
2381 } else {
2382 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
2383 "Unexpected unary expression for integer field class's `base` attribute: "
2384 "base=\"%s\"", s_right);
2385 g_free(s_right);
2386 ret = -EINVAL;
2387 goto error;
2388 }
2389
2390 g_free(s_right);
2391 break;
2392 }
2393 default:
2394 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
2395 "Invalid `base` attribute in integer field class: "
2396 "expecting unsigned constant integer or unary string.");
2397 ret = -EINVAL;
2398 goto error;
2399 }
2400
2401 _SET(&set, _INTEGER_BASE_SET);
2402 } else if (strcmp(left->u.unary_expression.u.string, "encoding") == 0) {
2403 char *s_right;
2404
2405 if (_IS_SET(&set, _INTEGER_ENCODING_SET)) {
2406 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "encoding",
2407 "integer field class");
2408 ret = -EPERM;
2409 goto error;
2410 }
2411
2412 if (right->u.unary_expression.type != UNARY_STRING) {
2413 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
2414 "Invalid `encoding` attribute in integer field class: "
2415 "expecting unary string.");
2416 ret = -EINVAL;
2417 goto error;
2418 }
2419
2420 s_right = ctf_ast_concatenate_unary_strings(
2421 &expression->u.ctf_expression.right);
2422 if (!s_right) {
2423 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
2424 "Unexpected unary expression for integer field class's `encoding` attribute.");
2425 ret = -EINVAL;
2426 goto error;
2427 }
2428
2429 if (strcmp(s_right, "UTF8") == 0 ||
2430 strcmp(s_right, "utf8") == 0 ||
2431 strcmp(s_right, "utf-8") == 0 ||
2432 strcmp(s_right, "UTF-8") == 0 ||
2433 strcmp(s_right, "ASCII") == 0 ||
2434 strcmp(s_right, "ascii") == 0) {
2435 encoding = CTF_ENCODING_UTF8;
2436 } else if (strcmp(s_right, "none") == 0) {
2437 encoding = CTF_ENCODING_NONE;
2438 } else {
2439 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
2440 "Invalid `encoding` attribute in integer field class: "
2441 "unknown encoding: encoding=\"%s\"",
2442 s_right);
2443 g_free(s_right);
2444 ret = -EINVAL;
2445 goto error;
2446 }
2447
2448 g_free(s_right);
2449 _SET(&set, _INTEGER_ENCODING_SET);
2450 } else if (strcmp(left->u.unary_expression.u.string, "map") == 0) {
2451 const char *clock_name;
2452
2453 if (_IS_SET(&set, _INTEGER_MAP_SET)) {
2454 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "map",
2455 "integer field class");
2456 ret = -EPERM;
2457 goto error;
2458 }
2459
2460 if (right->u.unary_expression.type != UNARY_STRING) {
2461 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
2462 "Invalid `map` attribute in integer field class: "
2463 "expecting unary string.");
2464 ret = -EINVAL;
2465 goto error;
2466 }
2467
2468 clock_name =
2469 get_map_clock_name_value(
2470 &expression->u.ctf_expression.right);
2471 if (!clock_name) {
2472 char *s_right = ctf_ast_concatenate_unary_strings(
2473 &expression->u.ctf_expression.right);
2474
2475 if (!s_right) {
2476 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
2477 "Unexpected unary expression for integer field class's `map` attribute.");
2478 ret = -EINVAL;
2479 goto error;
2480 }
2481
2482 _BT_COMP_LOGE_NODE(right,
2483 "Invalid `map` attribute in integer field class: "
2484 "cannot find clock class at this point: name=\"%s\"",
2485 s_right);
2486 _SET(&set, _INTEGER_MAP_SET);
2487 g_free(s_right);
2488 continue;
2489 }
2490
2491 mapped_clock_class =
2492 ctf_trace_class_borrow_clock_class_by_name(
2493 ctx->ctf_tc, clock_name);
2494 if (!mapped_clock_class) {
2495 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
2496 "Invalid `map` attribute in integer field class: "
2497 "cannot find clock class at this point: name=\"%s\"",
2498 clock_name);
2499 ret = -EINVAL;
2500 goto error;
2501 }
2502
2503 _SET(&set, _INTEGER_MAP_SET);
2504 } else {
2505 _BT_COMP_LOGW_NODE(left,
2506 "Unknown attribute in integer field class: "
2507 "attr-name=\"%s\"",
2508 left->u.unary_expression.u.string);
2509 }
2510 }
2511
2512 if (!_IS_SET(&set, _INTEGER_SIZE_SET)) {
2513 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Missing `size` attribute in integer field class.");
2514 ret = -EPERM;
2515 goto error;
2516 }
2517
2518 if (!_IS_SET(&set, _INTEGER_ALIGN_SET)) {
2519 if (size % CHAR_BIT) {
2520 /* Bit-packed alignment */
2521 alignment = 1;
2522 } else {
2523 /* Byte-packed alignment */
2524 alignment = CHAR_BIT;
2525 }
2526 }
2527
2528 *integer_decl = ctf_field_class_int_create();
2529 BT_ASSERT(*integer_decl);
2530 (*integer_decl)->base.base.alignment = alignment;
2531 (*integer_decl)->base.byte_order = byte_order;
2532 (*integer_decl)->base.size = size;
2533 (*integer_decl)->is_signed = (signedness > 0);
2534 (*integer_decl)->disp_base = base;
2535 (*integer_decl)->encoding = encoding;
2536 (*integer_decl)->mapped_clock_class = mapped_clock_class;
2537 return 0;
2538
2539 error:
2540 ctf_field_class_destroy((void *) *integer_decl);
2541 *integer_decl = NULL;
2542 return ret;
2543 }
2544
2545 static
2546 int visit_floating_point_number_decl(struct ctx *ctx,
2547 struct bt_list_head *expressions,
2548 struct ctf_field_class_float **float_decl)
2549 {
2550 int set = 0;
2551 int ret = 0;
2552 struct ctf_node *expression;
2553 uint64_t alignment = 1, exp_dig = 0, mant_dig = 0;
2554 enum ctf_byte_order byte_order = ctx->ctf_tc->default_byte_order;
2555
2556 *float_decl = NULL;
2557
2558 bt_list_for_each_entry(expression, expressions, siblings) {
2559 struct ctf_node *left, *right;
2560
2561 left = _BT_LIST_FIRST_ENTRY(&expression->u.ctf_expression.left,
2562 struct ctf_node, siblings);
2563 right = _BT_LIST_FIRST_ENTRY(
2564 &expression->u.ctf_expression.right, struct ctf_node,
2565 siblings);
2566
2567 if (left->u.unary_expression.type != UNARY_STRING) {
2568 _BT_COMP_LOGE_APPEND_CAUSE_NODE(left,
2569 "Unexpected unary expression type: type=%d",
2570 left->u.unary_expression.type);
2571 ret = -EINVAL;
2572 goto error;
2573 }
2574
2575 if (strcmp(left->u.unary_expression.u.string, "byte_order") == 0) {
2576 if (_IS_SET(&set, _FLOAT_BYTE_ORDER_SET)) {
2577 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "byte_order",
2578 "floating point number field class");
2579 ret = -EPERM;
2580 goto error;
2581 }
2582
2583 byte_order = get_real_byte_order(ctx, right);
2584 if (byte_order == CTF_BYTE_ORDER_UNKNOWN) {
2585 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
2586 "Invalid `byte_order` attribute in floating point number field class: "
2587 "ret=%d", ret);
2588 ret = -EINVAL;
2589 goto error;
2590 }
2591
2592 _SET(&set, _FLOAT_BYTE_ORDER_SET);
2593 } else if (strcmp(left->u.unary_expression.u.string, "exp_dig") == 0) {
2594 if (_IS_SET(&set, _FLOAT_EXP_DIG_SET)) {
2595 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "exp_dig",
2596 "floating point number field class");
2597 ret = -EPERM;
2598 goto error;
2599 }
2600
2601 if (right->u.unary_expression.type !=
2602 UNARY_UNSIGNED_CONSTANT) {
2603 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
2604 "Invalid `exp_dig` attribute in floating point number field class: "
2605 "expecting unsigned constant integer: "
2606 "node-type=%d",
2607 right->u.unary_expression.type);
2608 ret = -EINVAL;
2609 goto error;
2610 }
2611
2612 exp_dig = right->u.unary_expression.u.unsigned_constant;
2613 _SET(&set, _FLOAT_EXP_DIG_SET);
2614 } else if (strcmp(left->u.unary_expression.u.string, "mant_dig") == 0) {
2615 if (_IS_SET(&set, _FLOAT_MANT_DIG_SET)) {
2616 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "mant_dig",
2617 "floating point number field class");
2618 ret = -EPERM;
2619 goto error;
2620 }
2621
2622 if (right->u.unary_expression.type !=
2623 UNARY_UNSIGNED_CONSTANT) {
2624 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
2625 "Invalid `mant_dig` attribute in floating point number field class: "
2626 "expecting unsigned constant integer: "
2627 "node-type=%d",
2628 right->u.unary_expression.type);
2629 ret = -EINVAL;
2630 goto error;
2631 }
2632
2633 mant_dig = right->u.unary_expression.u.
2634 unsigned_constant;
2635 _SET(&set, _FLOAT_MANT_DIG_SET);
2636 } else if (strcmp(left->u.unary_expression.u.string, "align") == 0) {
2637 if (_IS_SET(&set, _FLOAT_ALIGN_SET)) {
2638 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "align",
2639 "floating point number field class");
2640 ret = -EPERM;
2641 goto error;
2642 }
2643
2644 if (right->u.unary_expression.type !=
2645 UNARY_UNSIGNED_CONSTANT) {
2646 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
2647 "Invalid `align` attribute in floating point number field class: "
2648 "expecting unsigned constant integer: "
2649 "node-type=%d",
2650 right->u.unary_expression.type);
2651 ret = -EINVAL;
2652 goto error;
2653 }
2654
2655 alignment = right->u.unary_expression.u.
2656 unsigned_constant;
2657
2658 if (!is_align_valid(alignment)) {
2659 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
2660 "Invalid `align` attribute in floating point number field class: "
2661 "expecting power of two: "
2662 "align=%" PRIu64, alignment);
2663 ret = -EINVAL;
2664 goto error;
2665 }
2666
2667 _SET(&set, _FLOAT_ALIGN_SET);
2668 } else {
2669 _BT_COMP_LOGW_NODE(left,
2670 "Unknown attribute in floating point number field class: "
2671 "attr-name=\"%s\"",
2672 left->u.unary_expression.u.string);
2673 }
2674 }
2675
2676 if (!_IS_SET(&set, _FLOAT_MANT_DIG_SET)) {
2677 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Missing `mant_dig` attribute in floating point number field class.");
2678 ret = -EPERM;
2679 goto error;
2680 }
2681
2682 if (!_IS_SET(&set, _FLOAT_EXP_DIG_SET)) {
2683 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Missing `exp_dig` attribute in floating point number field class.");
2684 ret = -EPERM;
2685 goto error;
2686 }
2687
2688 if (mant_dig != 24 && mant_dig != 53) {
2689 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("`mant_dig` attribute: expecting 24 or 53.");
2690 ret = -EPERM;
2691 goto error;
2692 }
2693
2694 if (mant_dig == 24 && exp_dig != 8) {
2695 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("`exp_dig` attribute: expecting 8 because `mant_dig` is 24.");
2696 ret = -EPERM;
2697 goto error;
2698 }
2699
2700 if (mant_dig == 53 && exp_dig != 11) {
2701 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("`exp_dig` attribute: expecting 11 because `mant_dig` is 53.");
2702 ret = -EPERM;
2703 goto error;
2704 }
2705
2706 if (!_IS_SET(&set, _INTEGER_ALIGN_SET)) {
2707 if ((mant_dig + exp_dig) % CHAR_BIT) {
2708 /* Bit-packed alignment */
2709 alignment = 1;
2710 } else {
2711 /* Byte-packed alignment */
2712 alignment = CHAR_BIT;
2713 }
2714 }
2715
2716 *float_decl = ctf_field_class_float_create();
2717 BT_ASSERT(*float_decl);
2718 (*float_decl)->base.base.alignment = alignment;
2719 (*float_decl)->base.byte_order = byte_order;
2720 (*float_decl)->base.size = mant_dig + exp_dig;
2721 return 0;
2722
2723 error:
2724 ctf_field_class_destroy((void *) *float_decl);
2725 *float_decl = NULL;
2726 return ret;
2727 }
2728
2729 static
2730 int visit_string_decl(struct ctx *ctx,
2731 struct bt_list_head *expressions,
2732 struct ctf_field_class_string **string_decl)
2733 {
2734 int set = 0;
2735 int ret = 0;
2736 struct ctf_node *expression;
2737 enum ctf_encoding encoding = CTF_ENCODING_UTF8;
2738
2739 *string_decl = NULL;
2740
2741 bt_list_for_each_entry(expression, expressions, siblings) {
2742 struct ctf_node *left, *right;
2743
2744 left = _BT_LIST_FIRST_ENTRY(&expression->u.ctf_expression.left,
2745 struct ctf_node, siblings);
2746 right = _BT_LIST_FIRST_ENTRY(
2747 &expression->u.ctf_expression.right, struct ctf_node,
2748 siblings);
2749
2750 if (left->u.unary_expression.type != UNARY_STRING) {
2751 _BT_COMP_LOGE_APPEND_CAUSE_NODE(left,
2752 "Unexpected unary expression type: type=%d",
2753 left->u.unary_expression.type);
2754 ret = -EINVAL;
2755 goto error;
2756 }
2757
2758 if (strcmp(left->u.unary_expression.u.string, "encoding") == 0) {
2759 char *s_right;
2760
2761 if (_IS_SET(&set, _STRING_ENCODING_SET)) {
2762 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left, "encoding",
2763 "string field class");
2764 ret = -EPERM;
2765 goto error;
2766 }
2767
2768 if (right->u.unary_expression.type != UNARY_STRING) {
2769 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
2770 "Invalid `encoding` attribute in string field class: "
2771 "expecting unary string.");
2772 ret = -EINVAL;
2773 goto error;
2774 }
2775
2776 s_right = ctf_ast_concatenate_unary_strings(
2777 &expression->u.ctf_expression.right);
2778 if (!s_right) {
2779 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
2780 "Unexpected unary expression for string field class's `encoding` attribute.");
2781 ret = -EINVAL;
2782 goto error;
2783 }
2784
2785 if (strcmp(s_right, "UTF8") == 0 ||
2786 strcmp(s_right, "utf8") == 0 ||
2787 strcmp(s_right, "utf-8") == 0 ||
2788 strcmp(s_right, "UTF-8") == 0 ||
2789 strcmp(s_right, "ASCII") == 0 ||
2790 strcmp(s_right, "ascii") == 0) {
2791 encoding = CTF_ENCODING_UTF8;
2792 } else if (strcmp(s_right, "none") == 0) {
2793 encoding = CTF_ENCODING_NONE;
2794 } else {
2795 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right,
2796 "Invalid `encoding` attribute in string field class: "
2797 "unknown encoding: encoding=\"%s\"",
2798 s_right);
2799 g_free(s_right);
2800 ret = -EINVAL;
2801 goto error;
2802 }
2803
2804 g_free(s_right);
2805 _SET(&set, _STRING_ENCODING_SET);
2806 } else {
2807 _BT_COMP_LOGW_NODE(left,
2808 "Unknown attribute in string field class: "
2809 "attr-name=\"%s\"",
2810 left->u.unary_expression.u.string);
2811 }
2812 }
2813
2814 *string_decl = ctf_field_class_string_create();
2815 BT_ASSERT(*string_decl);
2816 (*string_decl)->encoding = encoding;
2817 return 0;
2818
2819 error:
2820 ctf_field_class_destroy((void *) *string_decl);
2821 *string_decl = NULL;
2822 return ret;
2823 }
2824
2825 static
2826 int visit_field_class_specifier_list(struct ctx *ctx,
2827 struct ctf_node *ts_list, struct ctf_field_class **decl)
2828 {
2829 int ret = 0;
2830 struct ctf_node *first, *node;
2831
2832 *decl = NULL;
2833
2834 if (ts_list->type != NODE_TYPE_SPECIFIER_LIST) {
2835 _BT_COMP_LOGE_APPEND_CAUSE_NODE(ts_list,
2836 "Unexpected node type: node-type=%d", ts_list->type);
2837 ret = -EINVAL;
2838 goto error;
2839 }
2840
2841 first = _BT_LIST_FIRST_ENTRY(&ts_list->u.field_class_specifier_list.head,
2842 struct ctf_node, siblings);
2843 if (first->type != NODE_TYPE_SPECIFIER) {
2844 _BT_COMP_LOGE_APPEND_CAUSE_NODE(first,
2845 "Unexpected node type: node-type=%d", first->type);
2846 ret = -EINVAL;
2847 goto error;
2848 }
2849
2850 node = first->u.field_class_specifier.node;
2851
2852 switch (first->u.field_class_specifier.type) {
2853 case TYPESPEC_INTEGER:
2854 ret = visit_integer_decl(ctx, &node->u.integer.expressions,
2855 (void *) decl);
2856 if (ret) {
2857 BT_ASSERT(!*decl);
2858 goto error;
2859 }
2860 break;
2861 case TYPESPEC_FLOATING_POINT:
2862 ret = visit_floating_point_number_decl(ctx,
2863 &node->u.floating_point.expressions, (void *) decl);
2864 if (ret) {
2865 BT_ASSERT(!*decl);
2866 goto error;
2867 }
2868 break;
2869 case TYPESPEC_STRING:
2870 ret = visit_string_decl(ctx,
2871 &node->u.string.expressions, (void *) decl);
2872 if (ret) {
2873 BT_ASSERT(!*decl);
2874 goto error;
2875 }
2876 break;
2877 case TYPESPEC_STRUCT:
2878 ret = visit_struct_decl(ctx, node->u._struct.name,
2879 &node->u._struct.declaration_list,
2880 node->u._struct.has_body,
2881 &node->u._struct.min_align, (void *) decl);
2882 if (ret) {
2883 BT_ASSERT(!*decl);
2884 goto error;
2885 }
2886 break;
2887 case TYPESPEC_VARIANT:
2888 ret = visit_variant_decl(ctx, node->u.variant.name,
2889 node->u.variant.choice,
2890 &node->u.variant.declaration_list,
2891 node->u.variant.has_body, (void *) decl);
2892 if (ret) {
2893 BT_ASSERT(!*decl);
2894 goto error;
2895 }
2896 break;
2897 case TYPESPEC_ENUM:
2898 ret = visit_enum_decl(ctx, node->u._enum.enum_id,
2899 node->u._enum.container_field_class,
2900 &node->u._enum.enumerator_list,
2901 node->u._enum.has_body, (void *) decl);
2902 if (ret) {
2903 BT_ASSERT(!*decl);
2904 goto error;
2905 }
2906 break;
2907 case TYPESPEC_VOID:
2908 case TYPESPEC_CHAR:
2909 case TYPESPEC_SHORT:
2910 case TYPESPEC_INT:
2911 case TYPESPEC_LONG:
2912 case TYPESPEC_FLOAT:
2913 case TYPESPEC_DOUBLE:
2914 case TYPESPEC_SIGNED:
2915 case TYPESPEC_UNSIGNED:
2916 case TYPESPEC_BOOL:
2917 case TYPESPEC_COMPLEX:
2918 case TYPESPEC_IMAGINARY:
2919 case TYPESPEC_CONST:
2920 case TYPESPEC_ID_TYPE:
2921 ret = visit_field_class_specifier(ctx, ts_list, decl);
2922 if (ret) {
2923 _BT_COMP_LOGE_APPEND_CAUSE_NODE(first,
2924 "Cannot visit field class specifier: ret=%d",
2925 ret);
2926 BT_ASSERT(!*decl);
2927 goto error;
2928 }
2929 break;
2930 default:
2931 _BT_COMP_LOGE_APPEND_CAUSE_NODE(first,
2932 "Unexpected field class specifier type: node-type=%d",
2933 first->u.field_class_specifier.type);
2934 ret = -EINVAL;
2935 goto error;
2936 }
2937
2938 BT_ASSERT(*decl);
2939 return 0;
2940
2941 error:
2942 ctf_field_class_destroy((void *) *decl);
2943 *decl = NULL;
2944 return ret;
2945 }
2946
2947 static
2948 int visit_event_decl_entry(struct ctx *ctx, struct ctf_node *node,
2949 struct ctf_event_class *event_class, uint64_t *stream_id,
2950 int *set)
2951 {
2952 int ret = 0;
2953 char *left = NULL;
2954
2955 switch (node->type) {
2956 case NODE_TYPEDEF:
2957 ret = visit_field_class_def(ctx, node->u.field_class_def.field_class_specifier_list,
2958 &node->u.field_class_def.field_class_declarators);
2959 if (ret) {
2960 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
2961 "Cannot add field class found in event class.");
2962 goto error;
2963 }
2964 break;
2965 case NODE_TYPEALIAS:
2966 ret = visit_field_class_alias(ctx, node->u.field_class_alias.target,
2967 node->u.field_class_alias.alias);
2968 if (ret) {
2969 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
2970 "Cannot add field class alias found in event class.");
2971 goto error;
2972 }
2973 break;
2974 case NODE_CTF_EXPRESSION:
2975 {
2976 left = ctf_ast_concatenate_unary_strings(&node->u.ctf_expression.left);
2977 if (!left) {
2978 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Cannot concatenate unary strings.");
2979 ret = -EINVAL;
2980 goto error;
2981 }
2982
2983 if (strcmp(left, "name") == 0) {
2984 /* This is already known at this stage */
2985 if (_IS_SET(set, _EVENT_NAME_SET)) {
2986 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "name", "event class");
2987 ret = -EPERM;
2988 goto error;
2989 }
2990
2991 _SET(set, _EVENT_NAME_SET);
2992 } else if (strcmp(left, "id") == 0) {
2993 int64_t id = -1;
2994
2995 if (_IS_SET(set, _EVENT_ID_SET)) {
2996 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "id", "event class");
2997 ret = -EPERM;
2998 goto error;
2999 }
3000
3001 ret = get_unary_unsigned(ctx,
3002 &node->u.ctf_expression.right,
3003 (uint64_t *) &id);
3004 /* Only read "id" if get_unary_unsigned() succeeded. */
3005 if (ret || (!ret && id < 0)) {
3006 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3007 "Unexpected unary expression for event class's `id` attribute.");
3008 ret = -EINVAL;
3009 goto error;
3010 }
3011
3012 event_class->id = id;
3013 _SET(set, _EVENT_ID_SET);
3014 } else if (strcmp(left, "stream_id") == 0) {
3015 if (_IS_SET(set, _EVENT_STREAM_ID_SET)) {
3016 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "stream_id",
3017 "event class");
3018 ret = -EPERM;
3019 goto error;
3020 }
3021
3022 ret = get_unary_unsigned(ctx,
3023 &node->u.ctf_expression.right, stream_id);
3024
3025 /*
3026 * Only read "stream_id" if get_unary_unsigned()
3027 * succeeded.
3028 */
3029 if (ret) {
3030 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3031 "Unexpected unary expression for event class's `stream_id` attribute.");
3032 ret = -EINVAL;
3033 goto error;
3034 }
3035
3036 _SET(set, _EVENT_STREAM_ID_SET);
3037 } else if (strcmp(left, "context") == 0) {
3038 if (_IS_SET(set, _EVENT_CONTEXT_SET)) {
3039 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3040 "Duplicate `context` entry in event class.");
3041 ret = -EPERM;
3042 goto error;
3043 }
3044
3045 ret = visit_field_class_specifier_list(ctx,
3046 _BT_LIST_FIRST_ENTRY(
3047 &node->u.ctf_expression.right,
3048 struct ctf_node, siblings),
3049 &event_class->spec_context_fc);
3050 if (ret) {
3051 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3052 "Cannot create event class's context field class.");
3053 goto error;
3054 }
3055
3056 BT_ASSERT(event_class->spec_context_fc);
3057 _SET(set, _EVENT_CONTEXT_SET);
3058 } else if (strcmp(left, "fields") == 0) {
3059 if (_IS_SET(set, _EVENT_FIELDS_SET)) {
3060 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3061 "Duplicate `fields` entry in event class.");
3062 ret = -EPERM;
3063 goto error;
3064 }
3065
3066 ret = visit_field_class_specifier_list(ctx,
3067 _BT_LIST_FIRST_ENTRY(
3068 &node->u.ctf_expression.right,
3069 struct ctf_node, siblings),
3070 &event_class->payload_fc);
3071 if (ret) {
3072 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3073 "Cannot create event class's payload field class.");
3074 goto error;
3075 }
3076
3077 BT_ASSERT(event_class->payload_fc);
3078 _SET(set, _EVENT_FIELDS_SET);
3079 } else if (strcmp(left, "loglevel") == 0) {
3080 uint64_t loglevel_value;
3081 bool is_log_level_known = true;
3082 bt_event_class_log_level log_level = -1;
3083
3084 if (_IS_SET(set, _EVENT_LOG_LEVEL_SET)) {
3085 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "loglevel",
3086 "event class");
3087 ret = -EPERM;
3088 goto error;
3089 }
3090
3091 ret = get_unary_unsigned(ctx,
3092 &node->u.ctf_expression.right, &loglevel_value);
3093 if (ret) {
3094 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3095 "Unexpected unary expression for event class's `loglevel` attribute.");
3096 ret = -EINVAL;
3097 goto error;
3098 }
3099
3100 switch (loglevel_value) {
3101 case 0:
3102 log_level = BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY;
3103 break;
3104 case 1:
3105 log_level = BT_EVENT_CLASS_LOG_LEVEL_ALERT;
3106 break;
3107 case 2:
3108 log_level = BT_EVENT_CLASS_LOG_LEVEL_CRITICAL;
3109 break;
3110 case 3:
3111 log_level = BT_EVENT_CLASS_LOG_LEVEL_ERROR;
3112 break;
3113 case 4:
3114 log_level = BT_EVENT_CLASS_LOG_LEVEL_WARNING;
3115 break;
3116 case 5:
3117 log_level = BT_EVENT_CLASS_LOG_LEVEL_NOTICE;
3118 break;
3119 case 6:
3120 log_level = BT_EVENT_CLASS_LOG_LEVEL_INFO;
3121 break;
3122 case 7:
3123 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM;
3124 break;
3125 case 8:
3126 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM;
3127 break;
3128 case 9:
3129 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS;
3130 break;
3131 case 10:
3132 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE;
3133 break;
3134 case 11:
3135 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT;
3136 break;
3137 case 12:
3138 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION;
3139 break;
3140 case 13:
3141 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE;
3142 break;
3143 case 14:
3144 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG;
3145 break;
3146 default:
3147 is_log_level_known = false;
3148 _BT_COMP_LOGW_NODE(node, "Not setting event class's log level because its value is unknown: "
3149 "log-level=%" PRIu64, loglevel_value);
3150 }
3151
3152 if (is_log_level_known) {
3153 ctf_event_class_set_log_level(event_class, log_level);
3154 }
3155
3156 _SET(set, _EVENT_LOG_LEVEL_SET);
3157 } else if (strcmp(left, "model.emf.uri") == 0) {
3158 char *right;
3159
3160 if (_IS_SET(set, _EVENT_MODEL_EMF_URI_SET)) {
3161 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "model.emf.uri",
3162 "event class");
3163 ret = -EPERM;
3164 goto error;
3165 }
3166
3167 right = ctf_ast_concatenate_unary_strings(
3168 &node->u.ctf_expression.right);
3169 if (!right) {
3170 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3171 "Unexpected unary expression for event class's `model.emf.uri` attribute.");
3172 ret = -EINVAL;
3173 goto error;
3174 }
3175
3176 if (strlen(right) == 0) {
3177 _BT_COMP_LOGW_NODE(node,
3178 "Not setting event class's EMF URI because it's empty.");
3179 } else {
3180 g_string_assign(event_class->emf_uri,
3181 right);
3182 }
3183
3184 g_free(right);
3185 _SET(set, _EVENT_MODEL_EMF_URI_SET);
3186 } else {
3187 _BT_COMP_LOGW_NODE(node,
3188 "Unknown attribute in event class: "
3189 "attr-name=\"%s\"", left);
3190 }
3191
3192 g_free(left);
3193 left = NULL;
3194 break;
3195 }
3196 default:
3197 ret = -EPERM;
3198 goto error;
3199 }
3200
3201 goto end;
3202
3203 error:
3204 g_free(left);
3205
3206 end:
3207 return ret;
3208 }
3209
3210 static
3211 char *get_event_decl_name(struct ctx *ctx, struct ctf_node *node)
3212 {
3213 char *left = NULL;
3214 char *name = NULL;
3215 struct ctf_node *iter;
3216 struct bt_list_head *decl_list = &node->u.event.declaration_list;
3217
3218 bt_list_for_each_entry(iter, decl_list, siblings) {
3219 if (iter->type != NODE_CTF_EXPRESSION) {
3220 continue;
3221 }
3222
3223 left = ctf_ast_concatenate_unary_strings(&iter->u.ctf_expression.left);
3224 if (!left) {
3225 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter,
3226 "Cannot concatenate unary strings.");
3227 goto error;
3228 }
3229
3230 if (strcmp(left, "name") == 0) {
3231 name = ctf_ast_concatenate_unary_strings(
3232 &iter->u.ctf_expression.right);
3233 if (!name) {
3234 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter,
3235 "Unexpected unary expression for event class's `name` attribute.");
3236 goto error;
3237 }
3238 }
3239
3240 g_free(left);
3241 left = NULL;
3242
3243 if (name) {
3244 break;
3245 }
3246 }
3247
3248 return name;
3249
3250 error:
3251 g_free(left);
3252 return NULL;
3253 }
3254
3255 static
3256 int visit_event_decl(struct ctx *ctx, struct ctf_node *node)
3257 {
3258 int ret = 0;
3259 int set = 0;
3260 struct ctf_node *iter;
3261 uint64_t stream_id = 0;
3262 char *event_name = NULL;
3263 struct ctf_event_class *event_class = NULL;
3264 struct ctf_stream_class *stream_class = NULL;
3265 struct bt_list_head *decl_list = &node->u.event.declaration_list;
3266 bool pop_scope = false;
3267
3268 if (node->visited) {
3269 goto end;
3270 }
3271
3272 node->visited = TRUE;
3273 event_name = get_event_decl_name(ctx, node);
3274 if (!event_name) {
3275 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3276 "Missing `name` attribute in event class.");
3277 ret = -EPERM;
3278 goto error;
3279 }
3280
3281 event_class = ctf_event_class_create();
3282 BT_ASSERT(event_class);
3283 g_string_assign(event_class->name, event_name);
3284 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
3285 pop_scope = true;
3286
3287 bt_list_for_each_entry(iter, decl_list, siblings) {
3288 ret = visit_event_decl_entry(ctx, iter, event_class,
3289 &stream_id, &set);
3290 if (ret) {
3291 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter, "Cannot visit event class's entry: "
3292 "ret=%d", ret);
3293 goto error;
3294 }
3295 }
3296
3297 if (!_IS_SET(&set, _EVENT_STREAM_ID_SET)) {
3298 /*
3299 * Allow missing stream_id if there is only a single
3300 * stream class.
3301 */
3302 switch (ctx->ctf_tc->stream_classes->len) {
3303 case 0:
3304 /* Create implicit stream class if there's none */
3305 stream_id = 0;
3306 stream_class = ctf_stream_class_create();
3307 BT_ASSERT(stream_class);
3308 stream_class->id = stream_id;
3309 g_ptr_array_add(ctx->ctf_tc->stream_classes,
3310 stream_class);
3311 break;
3312 case 1:
3313 /* Single stream class: get its ID */
3314 stream_class = ctx->ctf_tc->stream_classes->pdata[0];
3315 stream_id = stream_class->id;
3316 break;
3317 default:
3318 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3319 "Missing `stream_id` attribute in event class.");
3320 ret = -EPERM;
3321 goto error;
3322 }
3323 }
3324
3325 /* We have the stream ID now; get the stream class if found */
3326 if (!stream_class) {
3327 stream_class = ctf_trace_class_borrow_stream_class_by_id(
3328 ctx->ctf_tc, stream_id);
3329 if (!stream_class) {
3330 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3331 "Cannot find stream class at this point: "
3332 "id=%" PRId64, stream_id);
3333 ret = -EINVAL;
3334 goto error;
3335 }
3336 }
3337
3338 BT_ASSERT(stream_class);
3339
3340 if (!_IS_SET(&set, _EVENT_ID_SET)) {
3341 /* Allow only one event without ID per stream */
3342 if (stream_class->event_classes->len != 0) {
3343 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3344 "Missing `id` attribute in event class.");
3345 ret = -EPERM;
3346 goto error;
3347 }
3348
3349 /* Automatic ID */
3350 event_class->id = 0;
3351 }
3352
3353 if (ctf_stream_class_borrow_event_class_by_id(stream_class,
3354 event_class->id)) {
3355 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3356 "Duplicate event class (same ID) in the same stream class: "
3357 "id=%" PRId64, event_class->id);
3358 ret = -EEXIST;
3359 goto error;
3360 }
3361
3362 ctf_stream_class_append_event_class(stream_class, event_class);
3363 event_class = NULL;
3364 goto end;
3365
3366 error:
3367 ctf_event_class_destroy(event_class);
3368 event_class = NULL;
3369
3370 if (ret >= 0) {
3371 ret = -1;
3372 }
3373
3374 end:
3375 if (pop_scope) {
3376 ctx_pop_scope(ctx);
3377 }
3378
3379 g_free(event_name);
3380
3381 return ret;
3382 }
3383
3384 static
3385 int auto_map_field_to_trace_clock_class(struct ctx *ctx,
3386 struct ctf_field_class *fc)
3387 {
3388 struct ctf_clock_class *clock_class_to_map_to = NULL;
3389 struct ctf_field_class_int *int_fc = (void *) fc;
3390 int ret = 0;
3391 uint64_t clock_class_count;
3392
3393 if (!fc) {
3394 goto end;
3395 }
3396
3397 if (fc->type != CTF_FIELD_CLASS_TYPE_INT &&
3398 fc->type != CTF_FIELD_CLASS_TYPE_ENUM) {
3399 goto end;
3400 }
3401
3402 if (int_fc->mapped_clock_class) {
3403 /* Already mapped */
3404 goto end;
3405 }
3406
3407 clock_class_count = ctx->ctf_tc->clock_classes->len;
3408
3409 switch (clock_class_count) {
3410 case 0:
3411 /*
3412 * No clock class exists in the trace at this point. Create an
3413 * implicit one at 1 GHz, named `default`, and use this clock
3414 * class.
3415 */
3416 clock_class_to_map_to = ctf_clock_class_create();
3417 BT_ASSERT(clock_class_to_map_to);
3418 clock_class_to_map_to->frequency = UINT64_C(1000000000);
3419 g_string_assign(clock_class_to_map_to->name, "default");
3420 BT_ASSERT(ret == 0);
3421 g_ptr_array_add(ctx->ctf_tc->clock_classes,
3422 clock_class_to_map_to);
3423 break;
3424 case 1:
3425 /*
3426 * Only one clock class exists in the trace at this point: use
3427 * this one.
3428 */
3429 clock_class_to_map_to = ctx->ctf_tc->clock_classes->pdata[0];
3430 break;
3431 default:
3432 /*
3433 * Timestamp field not mapped to a clock class and there's more
3434 * than one clock class in the trace: this is an error.
3435 */
3436 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Timestamp field found with no mapped clock class, "
3437 "but there's more than one clock class in the trace at this point.");
3438 ret = -1;
3439 goto end;
3440 }
3441
3442 BT_ASSERT(clock_class_to_map_to);
3443 int_fc->mapped_clock_class = clock_class_to_map_to;
3444
3445 end:
3446 return ret;
3447 }
3448
3449 static
3450 int auto_map_fields_to_trace_clock_class(struct ctx *ctx,
3451 struct ctf_field_class *root_fc, const char *field_name)
3452 {
3453 int ret = 0;
3454 uint64_t i, count;
3455 struct ctf_field_class_struct *struct_fc = (void *) root_fc;
3456 struct ctf_field_class_variant *var_fc = (void *) root_fc;
3457
3458 if (!root_fc) {
3459 goto end;
3460 }
3461
3462 if (root_fc->type != CTF_FIELD_CLASS_TYPE_STRUCT &&
3463 root_fc->type != CTF_FIELD_CLASS_TYPE_VARIANT) {
3464 goto end;
3465 }
3466
3467 if (root_fc->type == CTF_FIELD_CLASS_TYPE_STRUCT) {
3468 count = struct_fc->members->len;
3469 } else {
3470 count = var_fc->options->len;
3471 }
3472
3473 for (i = 0; i < count; i++) {
3474 struct ctf_named_field_class *named_fc = NULL;
3475
3476 if (root_fc->type == CTF_FIELD_CLASS_TYPE_STRUCT) {
3477 named_fc = ctf_field_class_struct_borrow_member_by_index(
3478 struct_fc, i);
3479 } else if (root_fc->type == CTF_FIELD_CLASS_TYPE_VARIANT) {
3480 named_fc = ctf_field_class_variant_borrow_option_by_index(
3481 var_fc, i);
3482 } else {
3483 bt_common_abort();
3484 }
3485
3486 if (strcmp(named_fc->name->str, field_name) == 0) {
3487 ret = auto_map_field_to_trace_clock_class(ctx,
3488 named_fc->fc);
3489 if (ret) {
3490 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot automatically map field to trace's clock class: "
3491 "field-name=\"%s\"", field_name);
3492 goto end;
3493 }
3494 }
3495
3496 ret = auto_map_fields_to_trace_clock_class(ctx, named_fc->fc,
3497 field_name);
3498 if (ret) {
3499 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot automatically map structure or variant field class's fields to trace's clock class: "
3500 "field-name=\"%s\", root-field-name=\"%s\"",
3501 field_name, named_fc->name->str);
3502 goto end;
3503 }
3504 }
3505
3506 end:
3507 return ret;
3508 }
3509
3510 static
3511 int visit_stream_decl_entry(struct ctx *ctx, struct ctf_node *node,
3512 struct ctf_stream_class *stream_class, int *set)
3513 {
3514 int ret = 0;
3515 char *left = NULL;
3516
3517 switch (node->type) {
3518 case NODE_TYPEDEF:
3519 ret = visit_field_class_def(ctx, node->u.field_class_def.field_class_specifier_list,
3520 &node->u.field_class_def.field_class_declarators);
3521 if (ret) {
3522 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3523 "Cannot add field class found in stream class.");
3524 goto error;
3525 }
3526 break;
3527 case NODE_TYPEALIAS:
3528 ret = visit_field_class_alias(ctx, node->u.field_class_alias.target,
3529 node->u.field_class_alias.alias);
3530 if (ret) {
3531 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3532 "Cannot add field class alias found in stream class.");
3533 goto error;
3534 }
3535 break;
3536 case NODE_CTF_EXPRESSION:
3537 {
3538 left = ctf_ast_concatenate_unary_strings(&node->u.ctf_expression.left);
3539 if (!left) {
3540 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Cannot concatenate unary strings.");
3541 ret = -EINVAL;
3542 goto error;
3543 }
3544
3545 if (strcmp(left, "id") == 0) {
3546 int64_t id;
3547
3548 if (_IS_SET(set, _STREAM_ID_SET)) {
3549 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "id",
3550 "stream declaration");
3551 ret = -EPERM;
3552 goto error;
3553 }
3554
3555 ret = get_unary_unsigned(ctx,
3556 &node->u.ctf_expression.right,
3557 (uint64_t *) &id);
3558
3559 /* Only read "id" if get_unary_unsigned() succeeded. */
3560 if (ret || (!ret && id < 0)) {
3561 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3562 "Unexpected unary expression for stream class's `id` attribute.");
3563 ret = -EINVAL;
3564 goto error;
3565 }
3566
3567 if (ctf_trace_class_borrow_stream_class_by_id(
3568 ctx->ctf_tc, id)) {
3569 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3570 "Duplicate stream class (same ID): id=%" PRId64,
3571 id);
3572 ret = -EEXIST;
3573 goto error;
3574 }
3575
3576 stream_class->id = id;
3577 _SET(set, _STREAM_ID_SET);
3578 } else if (strcmp(left, "event.header") == 0) {
3579 if (_IS_SET(set, _STREAM_EVENT_HEADER_SET)) {
3580 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3581 "Duplicate `event.header` entry in stream class.");
3582 ret = -EPERM;
3583 goto error;
3584 }
3585
3586 ret = visit_field_class_specifier_list(ctx,
3587 _BT_LIST_FIRST_ENTRY(
3588 &node->u.ctf_expression.right,
3589 struct ctf_node, siblings),
3590 &stream_class->event_header_fc);
3591 if (ret) {
3592 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3593 "Cannot create stream class's event header field class.");
3594 goto error;
3595 }
3596
3597 BT_ASSERT(stream_class->event_header_fc);
3598 ret = auto_map_fields_to_trace_clock_class(ctx,
3599 stream_class->event_header_fc, "timestamp");
3600 if (ret) {
3601 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3602 "Cannot automatically map specific event header field class fields named `timestamp` to trace's clock class.");
3603 goto error;
3604 }
3605
3606 _SET(set, _STREAM_EVENT_HEADER_SET);
3607 } else if (strcmp(left, "event.context") == 0) {
3608 if (_IS_SET(set, _STREAM_EVENT_CONTEXT_SET)) {
3609 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3610 "Duplicate `event.context` entry in stream class.");
3611 ret = -EPERM;
3612 goto error;
3613 }
3614
3615 ret = visit_field_class_specifier_list(ctx,
3616 _BT_LIST_FIRST_ENTRY(
3617 &node->u.ctf_expression.right,
3618 struct ctf_node, siblings),
3619 &stream_class->event_common_context_fc);
3620 if (ret) {
3621 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3622 "Cannot create stream class's event context field class.");
3623 goto error;
3624 }
3625
3626 BT_ASSERT(stream_class->event_common_context_fc);
3627 _SET(set, _STREAM_EVENT_CONTEXT_SET);
3628 } else if (strcmp(left, "packet.context") == 0) {
3629 if (_IS_SET(set, _STREAM_PACKET_CONTEXT_SET)) {
3630 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3631 "Duplicate `packet.context` entry in stream class.");
3632 ret = -EPERM;
3633 goto error;
3634 }
3635
3636 ret = visit_field_class_specifier_list(ctx,
3637 _BT_LIST_FIRST_ENTRY(
3638 &node->u.ctf_expression.right,
3639 struct ctf_node, siblings),
3640 &stream_class->packet_context_fc);
3641 if (ret) {
3642 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3643 "Cannot create stream class's packet context field class.");
3644 goto error;
3645 }
3646
3647 BT_ASSERT(stream_class->packet_context_fc);
3648 ret = auto_map_fields_to_trace_clock_class(ctx,
3649 stream_class->packet_context_fc,
3650 "timestamp_begin");
3651 if (ret) {
3652 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3653 "Cannot automatically map specific packet context field class fields named `timestamp_begin` to trace's clock class.");
3654 goto error;
3655 }
3656
3657 ret = auto_map_fields_to_trace_clock_class(ctx,
3658 stream_class->packet_context_fc,
3659 "timestamp_end");
3660 if (ret) {
3661 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3662 "Cannot automatically map specific packet context field class fields named `timestamp_end` to trace's clock class.");
3663 goto error;
3664 }
3665
3666 _SET(set, _STREAM_PACKET_CONTEXT_SET);
3667 } else {
3668 _BT_COMP_LOGW_NODE(node,
3669 "Unknown attribute in stream class: "
3670 "attr-name=\"%s\"", left);
3671 }
3672
3673 g_free(left);
3674 left = NULL;
3675 break;
3676 }
3677
3678 default:
3679 ret = -EPERM;
3680 goto error;
3681 }
3682
3683 return 0;
3684
3685 error:
3686 g_free(left);
3687 return ret;
3688 }
3689
3690 static
3691 int visit_stream_decl(struct ctx *ctx, struct ctf_node *node)
3692 {
3693 int set = 0;
3694 int ret = 0;
3695 struct ctf_node *iter;
3696 struct ctf_stream_class *stream_class = NULL;
3697 struct bt_list_head *decl_list = &node->u.stream.declaration_list;
3698
3699 if (node->visited) {
3700 goto end;
3701 }
3702
3703 node->visited = TRUE;
3704 stream_class = ctf_stream_class_create();
3705 BT_ASSERT(stream_class);
3706 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
3707
3708 bt_list_for_each_entry(iter, decl_list, siblings) {
3709 ret = visit_stream_decl_entry(ctx, iter, stream_class, &set);
3710 if (ret) {
3711 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter,
3712 "Cannot visit stream class's entry: "
3713 "ret=%d", ret);
3714 ctx_pop_scope(ctx);
3715 goto error;
3716 }
3717 }
3718
3719 ctx_pop_scope(ctx);
3720
3721 if (_IS_SET(&set, _STREAM_ID_SET)) {
3722 /* Check that packet header has `stream_id` field */
3723 struct ctf_named_field_class *named_fc = NULL;
3724
3725 if (!ctx->ctf_tc->packet_header_fc) {
3726 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3727 "Stream class has a `id` attribute, "
3728 "but trace has no packet header field class.");
3729 ret = -EINVAL;
3730 goto error;
3731 }
3732
3733 named_fc = ctf_field_class_struct_borrow_member_by_name(
3734 (void *) ctx->ctf_tc->packet_header_fc, "stream_id");
3735 if (!named_fc) {
3736 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3737 "Stream class has a `id` attribute, "
3738 "but trace's packet header field class has no `stream_id` field.");
3739 ret = -EINVAL;
3740 goto error;
3741 }
3742
3743 if (named_fc->fc->type != CTF_FIELD_CLASS_TYPE_INT &&
3744 named_fc->fc->type != CTF_FIELD_CLASS_TYPE_ENUM) {
3745 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3746 "Stream class has a `id` attribute, "
3747 "but trace's packet header field class's `stream_id` field is not an integer field class.");
3748 ret = -EINVAL;
3749 goto error;
3750 }
3751 } else {
3752 /* Allow only _one_ ID-less stream */
3753 if (ctx->ctf_tc->stream_classes->len != 0) {
3754 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3755 "Missing `id` attribute in stream class as there's more than one stream class in the trace.");
3756 ret = -EPERM;
3757 goto error;
3758 }
3759
3760 /* Automatic ID: 0 */
3761 stream_class->id = 0;
3762 }
3763
3764 /*
3765 * Make sure that this stream class's ID is currently unique in
3766 * the trace.
3767 */
3768 if (ctf_trace_class_borrow_stream_class_by_id(ctx->ctf_tc,
3769 stream_class->id)) {
3770 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3771 "Duplicate stream class (same ID): id=%" PRId64,
3772 stream_class->id);
3773 ret = -EINVAL;
3774 goto error;
3775 }
3776
3777 g_ptr_array_add(ctx->ctf_tc->stream_classes, stream_class);
3778 stream_class = NULL;
3779 goto end;
3780
3781 error:
3782 ctf_stream_class_destroy(stream_class);
3783 stream_class = NULL;
3784
3785 end:
3786 return ret;
3787 }
3788
3789 static
3790 int visit_trace_decl_entry(struct ctx *ctx, struct ctf_node *node, int *set)
3791 {
3792 int ret = 0;
3793 char *left = NULL;
3794 uint64_t val;
3795
3796 switch (node->type) {
3797 case NODE_TYPEDEF:
3798 ret = visit_field_class_def(ctx, node->u.field_class_def.field_class_specifier_list,
3799 &node->u.field_class_def.field_class_declarators);
3800 if (ret) {
3801 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3802 "Cannot add field class found in trace (`trace` block).");
3803 goto error;
3804 }
3805 break;
3806 case NODE_TYPEALIAS:
3807 ret = visit_field_class_alias(ctx, node->u.field_class_alias.target,
3808 node->u.field_class_alias.alias);
3809 if (ret) {
3810 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3811 "Cannot add field class alias found in trace (`trace` block).");
3812 goto error;
3813 }
3814 break;
3815 case NODE_CTF_EXPRESSION:
3816 {
3817 left = ctf_ast_concatenate_unary_strings(&node->u.ctf_expression.left);
3818 if (!left) {
3819 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Cannot concatenate unary strings.");
3820 ret = -EINVAL;
3821 goto error;
3822 }
3823
3824 if (strcmp(left, "major") == 0) {
3825 if (_IS_SET(set, _TRACE_MAJOR_SET)) {
3826 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "major", "trace");
3827 ret = -EPERM;
3828 goto error;
3829 }
3830
3831 ret = get_unary_unsigned(ctx,
3832 &node->u.ctf_expression.right, &val);
3833 if (ret) {
3834 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3835 "Unexpected unary expression for trace's `major` attribute.");
3836 ret = -EINVAL;
3837 goto error;
3838 }
3839
3840 if (val != 1) {
3841 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3842 "Invalid trace's `minor` attribute: expecting 1.");
3843 ret = -EINVAL;
3844 goto error;
3845 }
3846
3847 ctx->ctf_tc->major = val;
3848 _SET(set, _TRACE_MAJOR_SET);
3849 } else if (strcmp(left, "minor") == 0) {
3850 if (_IS_SET(set, _TRACE_MINOR_SET)) {
3851 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "minor", "trace");
3852 ret = -EPERM;
3853 goto error;
3854 }
3855
3856 ret = get_unary_unsigned(ctx,
3857 &node->u.ctf_expression.right, &val);
3858 if (ret) {
3859 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3860 "Unexpected unary expression for trace's `minor` attribute.");
3861 ret = -EINVAL;
3862 goto error;
3863 }
3864
3865 if (val != 8) {
3866 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3867 "Invalid trace's `minor` attribute: expecting 8.");
3868 ret = -EINVAL;
3869 goto error;
3870 }
3871
3872 ctx->ctf_tc->minor = val;
3873 _SET(set, _TRACE_MINOR_SET);
3874 } else if (strcmp(left, "uuid") == 0) {
3875 if (_IS_SET(set, _TRACE_UUID_SET)) {
3876 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "uuid", "trace");
3877 ret = -EPERM;
3878 goto error;
3879 }
3880
3881 ret = get_unary_uuid(ctx,
3882 &node->u.ctf_expression.right,
3883 ctx->ctf_tc->uuid);
3884 if (ret) {
3885 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3886 "Invalid trace's `uuid` attribute.");
3887 goto error;
3888 }
3889
3890 ctx->ctf_tc->is_uuid_set = true;
3891 _SET(set, _TRACE_UUID_SET);
3892 } else if (strcmp(left, "byte_order") == 0) {
3893 /* Default byte order is already known at this stage */
3894 if (_IS_SET(set, _TRACE_BYTE_ORDER_SET)) {
3895 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "byte_order",
3896 "trace");
3897 ret = -EPERM;
3898 goto error;
3899 }
3900
3901 BT_ASSERT(ctx->ctf_tc->default_byte_order != CTF_BYTE_ORDER_UNKNOWN);
3902 _SET(set, _TRACE_BYTE_ORDER_SET);
3903 } else if (strcmp(left, "packet.header") == 0) {
3904 if (_IS_SET(set, _TRACE_PACKET_HEADER_SET)) {
3905 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3906 "Duplicate `packet.header` entry in trace.");
3907 ret = -EPERM;
3908 goto error;
3909 }
3910
3911 ret = visit_field_class_specifier_list(ctx,
3912 _BT_LIST_FIRST_ENTRY(
3913 &node->u.ctf_expression.right,
3914 struct ctf_node, siblings),
3915 &ctx->ctf_tc->packet_header_fc);
3916 if (ret) {
3917 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3918 "Cannot create trace's packet header field class.");
3919 goto error;
3920 }
3921
3922 BT_ASSERT(ctx->ctf_tc->packet_header_fc);
3923 _SET(set, _TRACE_PACKET_HEADER_SET);
3924 } else {
3925 _BT_COMP_LOGW_NODE(node,
3926 "Unknown attribute in stream class: "
3927 "attr-name=\"%s\"", left);
3928 }
3929
3930 g_free(left);
3931 left = NULL;
3932 break;
3933 }
3934 default:
3935 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Unknown expression in trace.");
3936 ret = -EINVAL;
3937 goto error;
3938 }
3939
3940 return 0;
3941
3942 error:
3943 g_free(left);
3944 return ret;
3945 }
3946
3947 static
3948 int visit_trace_decl(struct ctx *ctx, struct ctf_node *node)
3949 {
3950 int ret = 0;
3951 int set = 0;
3952 struct ctf_node *iter;
3953 struct bt_list_head *decl_list = &node->u.trace.declaration_list;
3954
3955 if (node->visited) {
3956 goto end;
3957 }
3958
3959 node->visited = TRUE;
3960
3961 if (ctx->is_trace_visited) {
3962 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node, "Duplicate trace (`trace` block).");
3963 ret = -EEXIST;
3964 goto error;
3965 }
3966
3967 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
3968
3969 bt_list_for_each_entry(iter, decl_list, siblings) {
3970 ret = visit_trace_decl_entry(ctx, iter, &set);
3971 if (ret) {
3972 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter, "Cannot visit trace's entry (`trace` block): "
3973 "ret=%d", ret);
3974 ctx_pop_scope(ctx);
3975 goto error;
3976 }
3977 }
3978
3979 ctx_pop_scope(ctx);
3980
3981 if (!_IS_SET(&set, _TRACE_MAJOR_SET)) {
3982 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3983 "Missing `major` attribute in trace (`trace` block).");
3984 ret = -EPERM;
3985 goto error;
3986 }
3987
3988 if (!_IS_SET(&set, _TRACE_MINOR_SET)) {
3989 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3990 "Missing `minor` attribute in trace (`trace` block).");
3991 ret = -EPERM;
3992 goto error;
3993 }
3994
3995 if (!_IS_SET(&set, _TRACE_BYTE_ORDER_SET)) {
3996 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
3997 "Missing `byte_order` attribute in trace (`trace` block).");
3998 ret = -EPERM;
3999 goto error;
4000 }
4001
4002 ctx->is_trace_visited = true;
4003
4004 end:
4005 return 0;
4006
4007 error:
4008 return ret;
4009 }
4010
4011 static
4012 int visit_env(struct ctx *ctx, struct ctf_node *node)
4013 {
4014 int ret = 0;
4015 char *left = NULL;
4016 struct ctf_node *entry_node;
4017 struct bt_list_head *decl_list = &node->u.env.declaration_list;
4018
4019 if (node->visited) {
4020 goto end;
4021 }
4022
4023 node->visited = TRUE;
4024
4025 bt_list_for_each_entry(entry_node, decl_list, siblings) {
4026 struct bt_list_head *right_head =
4027 &entry_node->u.ctf_expression.right;
4028
4029 if (entry_node->type != NODE_CTF_EXPRESSION) {
4030 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node,
4031 "Wrong expression in environment entry: "
4032 "node-type=%d", entry_node->type);
4033 ret = -EPERM;
4034 goto error;
4035 }
4036
4037 left = ctf_ast_concatenate_unary_strings(
4038 &entry_node->u.ctf_expression.left);
4039 if (!left) {
4040 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node,
4041 "Cannot get environment entry's name.");
4042 ret = -EINVAL;
4043 goto error;
4044 }
4045
4046 if (is_unary_string(right_head)) {
4047 char *right = ctf_ast_concatenate_unary_strings(right_head);
4048
4049 if (!right) {
4050 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node,
4051 "Unexpected unary expression for environment entry's value: "
4052 "name=\"%s\"", left);
4053 ret = -EINVAL;
4054 goto error;
4055 }
4056
4057 if (strcmp(left, "tracer_name") == 0) {
4058 if (strncmp(right, "lttng", 5) == 0) {
4059 BT_COMP_LOGI("Detected LTTng trace from `%s` environment value: "
4060 "tracer-name=\"%s\"",
4061 left, right);
4062 ctx->is_lttng = true;
4063 }
4064 }
4065
4066 ctf_trace_class_append_env_entry(ctx->ctf_tc,
4067 left, CTF_TRACE_CLASS_ENV_ENTRY_TYPE_STR,
4068 right, 0);
4069 g_free(right);
4070 } else if (is_unary_unsigned(right_head) ||
4071 is_unary_signed(right_head)) {
4072 int64_t v;
4073
4074 if (is_unary_unsigned(right_head)) {
4075 ret = get_unary_unsigned(ctx, right_head,
4076 (uint64_t *) &v);
4077 } else {
4078 ret = get_unary_signed(right_head, &v);
4079 }
4080 if (ret) {
4081 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node,
4082 "Unexpected unary expression for environment entry's value: "
4083 "name=\"%s\"", left);
4084 ret = -EINVAL;
4085 goto error;
4086 }
4087
4088 ctf_trace_class_append_env_entry(ctx->ctf_tc,
4089 left, CTF_TRACE_CLASS_ENV_ENTRY_TYPE_INT,
4090 NULL, v);
4091 } else {
4092 _BT_COMP_LOGW_NODE(entry_node,
4093 "Environment entry has unknown type: "
4094 "name=\"%s\"", left);
4095 }
4096
4097 g_free(left);
4098 left = NULL;
4099 }
4100
4101 end:
4102 return 0;
4103
4104 error:
4105 g_free(left);
4106 return ret;
4107 }
4108
4109 static
4110 int set_trace_byte_order(struct ctx *ctx, struct ctf_node *trace_node)
4111 {
4112 int ret = 0;
4113 int set = 0;
4114 char *left = NULL;
4115 struct ctf_node *node;
4116 struct bt_list_head *decl_list = &trace_node->u.trace.declaration_list;
4117
4118 bt_list_for_each_entry(node, decl_list, siblings) {
4119 if (node->type == NODE_CTF_EXPRESSION) {
4120 struct ctf_node *right_node;
4121
4122 left = ctf_ast_concatenate_unary_strings(
4123 &node->u.ctf_expression.left);
4124 if (!left) {
4125 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
4126 "Cannot concatenate unary strings.");
4127 ret = -EINVAL;
4128 goto error;
4129 }
4130
4131 if (strcmp(left, "byte_order") == 0) {
4132 enum ctf_byte_order bo;
4133
4134 if (_IS_SET(&set, _TRACE_BYTE_ORDER_SET)) {
4135 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node, "byte_order",
4136 "trace");
4137 ret = -EPERM;
4138 goto error;
4139 }
4140
4141 _SET(&set, _TRACE_BYTE_ORDER_SET);
4142 right_node = _BT_LIST_FIRST_ENTRY(
4143 &node->u.ctf_expression.right,
4144 struct ctf_node, siblings);
4145 bo = byte_order_from_unary_expr(ctx,
4146 right_node);
4147 if (bo == CTF_BYTE_ORDER_UNKNOWN) {
4148 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
4149 "Invalid `byte_order` attribute in trace (`trace` block): "
4150 "expecting `le`, `be`, or `network`.");
4151 ret = -EINVAL;
4152 goto error;
4153 } else if (bo == CTF_BYTE_ORDER_DEFAULT) {
4154 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
4155 "Invalid `byte_order` attribute in trace (`trace` block): "
4156 "cannot be set to `native` here.");
4157 ret = -EPERM;
4158 goto error;
4159 }
4160
4161 ctx->ctf_tc->default_byte_order = bo;
4162 }
4163
4164 g_free(left);
4165 left = NULL;
4166 }
4167 }
4168
4169 if (!_IS_SET(&set, _TRACE_BYTE_ORDER_SET)) {
4170 _BT_COMP_LOGE_APPEND_CAUSE_NODE(trace_node,
4171 "Missing `byte_order` attribute in trace (`trace` block).");
4172 ret = -EINVAL;
4173 goto error;
4174 }
4175
4176 return 0;
4177
4178 error:
4179 g_free(left);
4180 return ret;
4181 }
4182
4183 static
4184 int visit_clock_decl_entry(struct ctx *ctx, struct ctf_node *entry_node,
4185 struct ctf_clock_class *clock, int *set, int64_t *offset_seconds,
4186 uint64_t *offset_cycles)
4187 {
4188 int ret = 0;
4189 char *left = NULL;
4190
4191 if (entry_node->type != NODE_CTF_EXPRESSION) {
4192 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node,
4193 "Unexpected node type: node-type=%d",
4194 entry_node->type);
4195 ret = -EPERM;
4196 goto error;
4197 }
4198
4199 left = ctf_ast_concatenate_unary_strings(&entry_node->u.ctf_expression.left);
4200 if (!left) {
4201 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node, "Cannot concatenate unary strings.");
4202 ret = -EINVAL;
4203 goto error;
4204 }
4205
4206 if (strcmp(left, "name") == 0) {
4207 char *right;
4208
4209 if (_IS_SET(set, _CLOCK_NAME_SET)) {
4210 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node, "name", "clock class");
4211 ret = -EPERM;
4212 goto error;
4213 }
4214
4215 right = ctf_ast_concatenate_unary_strings(
4216 &entry_node->u.ctf_expression.right);
4217 if (!right) {
4218 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node,
4219 "Unexpected unary expression for clock class's `name` attribute.");
4220 ret = -EINVAL;
4221 goto error;
4222 }
4223
4224 g_string_assign(clock->name, right);
4225 g_free(right);
4226 _SET(set, _CLOCK_NAME_SET);
4227 } else if (strcmp(left, "uuid") == 0) {
4228 bt_uuid_t uuid;
4229
4230 if (_IS_SET(set, _CLOCK_UUID_SET)) {
4231 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node, "uuid", "clock class");
4232 ret = -EPERM;
4233 goto error;
4234 }
4235
4236 ret = get_unary_uuid(ctx, &entry_node->u.ctf_expression.right,
4237 uuid);
4238 if (ret) {
4239 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node,
4240 "Invalid clock class's `uuid` attribute.");
4241 goto error;
4242 }
4243
4244 clock->has_uuid = true;
4245 bt_uuid_copy(clock->uuid, uuid);
4246 _SET(set, _CLOCK_UUID_SET);
4247 } else if (strcmp(left, "description") == 0) {
4248 char *right;
4249
4250 if (_IS_SET(set, _CLOCK_DESCRIPTION_SET)) {
4251 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node, "description",
4252 "clock class");
4253 ret = -EPERM;
4254 goto error;
4255 }
4256
4257 right = ctf_ast_concatenate_unary_strings(
4258 &entry_node->u.ctf_expression.right);
4259 if (!right) {
4260 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node,
4261 "Unexpected unary expression for clock class's `description` attribute.");
4262 ret = -EINVAL;
4263 goto error;
4264 }
4265
4266 g_string_assign(clock->description, right);
4267 g_free(right);
4268 _SET(set, _CLOCK_DESCRIPTION_SET);
4269 } else if (strcmp(left, "freq") == 0) {
4270 uint64_t freq = UINT64_C(-1);
4271
4272 if (_IS_SET(set, _CLOCK_FREQ_SET)) {
4273 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node, "freq", "clock class");
4274 ret = -EPERM;
4275 goto error;
4276 }
4277
4278 ret = get_unary_unsigned(ctx,
4279 &entry_node->u.ctf_expression.right, &freq);
4280 if (ret) {
4281 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node,
4282 "Unexpected unary expression for clock class's `freq` attribute.");
4283 ret = -EINVAL;
4284 goto error;
4285 }
4286
4287 if (freq == UINT64_C(-1) || freq == 0) {
4288 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node,
4289 "Invalid clock class frequency: freq=%" PRIu64,
4290 freq);
4291 ret = -EINVAL;
4292 goto error;
4293 }
4294
4295 clock->frequency = freq;
4296 _SET(set, _CLOCK_FREQ_SET);
4297 } else if (strcmp(left, "precision") == 0) {
4298 uint64_t precision;
4299
4300 if (_IS_SET(set, _CLOCK_PRECISION_SET)) {
4301 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node, "precision",
4302 "clock class");
4303 ret = -EPERM;
4304 goto error;
4305 }
4306
4307 ret = get_unary_unsigned(ctx,
4308 &entry_node->u.ctf_expression.right, &precision);
4309 if (ret) {
4310 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node,
4311 "Unexpected unary expression for clock class's `precision` attribute.");
4312 ret = -EINVAL;
4313 goto error;
4314 }
4315
4316 clock->precision = precision;
4317 _SET(set, _CLOCK_PRECISION_SET);
4318 } else if (strcmp(left, "offset_s") == 0) {
4319 if (_IS_SET(set, _CLOCK_OFFSET_S_SET)) {
4320 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node, "offset_s",
4321 "clock class");
4322 ret = -EPERM;
4323 goto error;
4324 }
4325
4326 ret = get_unary_signed(
4327 &entry_node->u.ctf_expression.right, offset_seconds);
4328 if (ret) {
4329 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node,
4330 "Unexpected unary expression for clock class's `offset_s` attribute.");
4331 ret = -EINVAL;
4332 goto error;
4333 }
4334
4335 _SET(set, _CLOCK_OFFSET_S_SET);
4336 } else if (strcmp(left, "offset") == 0) {
4337 if (_IS_SET(set, _CLOCK_OFFSET_SET)) {
4338 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node, "offset", "clock class");
4339 ret = -EPERM;
4340 goto error;
4341 }
4342
4343 ret = get_unary_unsigned(ctx,
4344 &entry_node->u.ctf_expression.right, offset_cycles);
4345 if (ret) {
4346 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node,
4347 "Unexpected unary expression for clock class's `offset` attribute.");
4348 ret = -EINVAL;
4349 goto error;
4350 }
4351
4352 _SET(set, _CLOCK_OFFSET_SET);
4353 } else if (strcmp(left, "absolute") == 0) {
4354 struct ctf_node *right;
4355
4356 if (_IS_SET(set, _CLOCK_ABSOLUTE_SET)) {
4357 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node, "absolute",
4358 "clock class");
4359 ret = -EPERM;
4360 goto error;
4361 }
4362
4363 right = _BT_LIST_FIRST_ENTRY(
4364 &entry_node->u.ctf_expression.right,
4365 struct ctf_node, siblings);
4366 ret = get_boolean(ctx, right);
4367 if (ret < 0) {
4368 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node,
4369 "Unexpected unary expression for clock class's `absolute` attribute.");
4370 ret = -EINVAL;
4371 goto error;
4372 }
4373
4374 clock->is_absolute = ret;
4375 _SET(set, _CLOCK_ABSOLUTE_SET);
4376 } else {
4377 _BT_COMP_LOGW_NODE(entry_node,
4378 "Unknown attribute in clock class: attr-name=\"%s\"",
4379 left);
4380 }
4381
4382 g_free(left);
4383 left = NULL;
4384 return 0;
4385
4386 error:
4387 g_free(left);
4388 return ret;
4389 }
4390
4391 static inline
4392 uint64_t cycles_from_ns(uint64_t frequency, uint64_t ns)
4393 {
4394 uint64_t cycles;
4395
4396 /* 1GHz */
4397 if (frequency == UINT64_C(1000000000)) {
4398 cycles = ns;
4399 } else {
4400 cycles = (uint64_t) (((double) ns * (double) frequency) / 1e9);
4401 }
4402
4403 return cycles;
4404 }
4405
4406 static
4407 void calibrate_clock_class_offsets(int64_t *offset_seconds,
4408 uint64_t *offset_cycles, uint64_t freq)
4409 {
4410 if (*offset_cycles >= freq) {
4411 const uint64_t s_in_offset_cycles = *offset_cycles / freq;
4412
4413 *offset_seconds += (int64_t) s_in_offset_cycles;
4414 *offset_cycles -= (s_in_offset_cycles * freq);
4415 }
4416 }
4417
4418 static
4419 void apply_clock_class_is_absolute(struct ctx *ctx,
4420 struct ctf_clock_class *clock)
4421 {
4422 if (ctx->decoder_config.force_clock_class_origin_unix_epoch) {
4423 clock->is_absolute = true;
4424 }
4425
4426 return;
4427 }
4428
4429 static
4430 void apply_clock_class_offset(struct ctx *ctx,
4431 struct ctf_clock_class *clock)
4432 {
4433 uint64_t freq;
4434 int64_t offset_s_to_apply = ctx->decoder_config.clock_class_offset_s;
4435 uint64_t offset_ns_to_apply;
4436 int64_t cur_offset_s;
4437 uint64_t cur_offset_cycles;
4438
4439 if (ctx->decoder_config.clock_class_offset_s == 0 &&
4440 ctx->decoder_config.clock_class_offset_ns == 0) {
4441 goto end;
4442 }
4443
4444 /* Transfer nanoseconds to seconds as much as possible */
4445 if (ctx->decoder_config.clock_class_offset_ns < 0) {
4446 const int64_t abs_ns = -ctx->decoder_config.clock_class_offset_ns;
4447 const int64_t abs_extra_s = abs_ns / INT64_C(1000000000) + 1;
4448 const int64_t extra_s = -abs_extra_s;
4449 const int64_t offset_ns = ctx->decoder_config.clock_class_offset_ns -
4450 (extra_s * INT64_C(1000000000));
4451
4452 BT_ASSERT(offset_ns > 0);
4453 offset_ns_to_apply = (uint64_t) offset_ns;
4454 offset_s_to_apply += extra_s;
4455 } else {
4456 const int64_t extra_s = ctx->decoder_config.clock_class_offset_ns /
4457 INT64_C(1000000000);
4458 const int64_t offset_ns = ctx->decoder_config.clock_class_offset_ns -
4459 (extra_s * INT64_C(1000000000));
4460
4461 BT_ASSERT(offset_ns >= 0);
4462 offset_ns_to_apply = (uint64_t) offset_ns;
4463 offset_s_to_apply += extra_s;
4464 }
4465
4466 freq = clock->frequency;
4467 cur_offset_s = clock->offset_seconds;
4468 cur_offset_cycles = clock->offset_cycles;
4469
4470 /* Apply offsets */
4471 cur_offset_s += offset_s_to_apply;
4472 cur_offset_cycles += cycles_from_ns(freq, offset_ns_to_apply);
4473
4474 /*
4475 * Recalibrate offsets because the part in cycles can be greater
4476 * than the frequency at this point.
4477 */
4478 calibrate_clock_class_offsets(&cur_offset_s, &cur_offset_cycles, freq);
4479
4480 /* Set final offsets */
4481 clock->offset_seconds = cur_offset_s;
4482 clock->offset_cycles = cur_offset_cycles;
4483
4484 end:
4485 return;
4486 }
4487
4488 static
4489 int visit_clock_decl(struct ctx *ctx, struct ctf_node *clock_node)
4490 {
4491 int ret = 0;
4492 int set = 0;
4493 struct ctf_clock_class *clock;
4494 struct ctf_node *entry_node;
4495 struct bt_list_head *decl_list = &clock_node->u.clock.declaration_list;
4496 const char *clock_class_name;
4497 int64_t offset_seconds = 0;
4498 uint64_t offset_cycles = 0;
4499 uint64_t freq;
4500
4501 if (clock_node->visited) {
4502 return 0;
4503 }
4504
4505 clock_node->visited = TRUE;
4506
4507 /* CTF 1.8's default frequency for a clock class is 1 GHz */
4508 clock = ctf_clock_class_create();
4509 if (!clock) {
4510 _BT_COMP_LOGE_APPEND_CAUSE_NODE(clock_node,
4511 "Cannot create default clock class.");
4512 ret = -ENOMEM;
4513 goto end;
4514 }
4515
4516 bt_list_for_each_entry(entry_node, decl_list, siblings) {
4517 ret = visit_clock_decl_entry(ctx, entry_node, clock, &set,
4518 &offset_seconds, &offset_cycles);
4519 if (ret) {
4520 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node,
4521 "Cannot visit clock class's entry: ret=%d",
4522 ret);
4523 goto end;
4524 }
4525 }
4526
4527 if (!_IS_SET(&set, _CLOCK_NAME_SET)) {
4528 _BT_COMP_LOGE_APPEND_CAUSE_NODE(clock_node,
4529 "Missing `name` attribute in clock class.");
4530 ret = -EPERM;
4531 goto end;
4532 }
4533
4534 clock_class_name = clock->name->str;
4535 BT_ASSERT(clock_class_name);
4536 if (ctx->is_lttng && strcmp(clock_class_name, "monotonic") == 0) {
4537 /*
4538 * Old versions of LTTng forgot to set its clock class
4539 * as absolute, even if it is. This is important because
4540 * it's a condition to be able to sort messages
4541 * from different sources.
4542 */
4543 clock->is_absolute = true;
4544 }
4545
4546 /*
4547 * Adjust offsets so that the part in cycles is less than the
4548 * frequency (move to the part in seconds).
4549 */
4550 freq = clock->frequency;
4551 calibrate_clock_class_offsets(&offset_seconds, &offset_cycles, freq);
4552 BT_ASSERT(offset_cycles < clock->frequency);
4553 clock->offset_seconds = offset_seconds;
4554 clock->offset_cycles = offset_cycles;
4555 apply_clock_class_offset(ctx, clock);
4556 apply_clock_class_is_absolute(ctx, clock);
4557 g_ptr_array_add(ctx->ctf_tc->clock_classes, clock);
4558 clock = NULL;
4559
4560 end:
4561 if (clock) {
4562 ctf_clock_class_destroy(clock);
4563 }
4564
4565 return ret;
4566 }
4567
4568 static
4569 int visit_root_decl(struct ctx *ctx, struct ctf_node *root_decl_node)
4570 {
4571 int ret = 0;
4572
4573 if (root_decl_node->visited) {
4574 goto end;
4575 }
4576
4577 root_decl_node->visited = TRUE;
4578
4579 switch (root_decl_node->type) {
4580 case NODE_TYPEDEF:
4581 ret = visit_field_class_def(ctx,
4582 root_decl_node->u.field_class_def.field_class_specifier_list,
4583 &root_decl_node->u.field_class_def.field_class_declarators);
4584 if (ret) {
4585 _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node,
4586 "Cannot add field class found in root scope.");
4587 goto end;
4588 }
4589 break;
4590 case NODE_TYPEALIAS:
4591 ret = visit_field_class_alias(ctx, root_decl_node->u.field_class_alias.target,
4592 root_decl_node->u.field_class_alias.alias);
4593 if (ret) {
4594 _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node,
4595 "Cannot add field class alias found in root scope.");
4596 goto end;
4597 }
4598 break;
4599 case NODE_TYPE_SPECIFIER_LIST:
4600 {
4601 struct ctf_field_class *decl = NULL;
4602
4603 /*
4604 * Just add the field class specifier to the root
4605 * declaration scope. Put local reference.
4606 */
4607 ret = visit_field_class_specifier_list(ctx, root_decl_node, &decl);
4608 if (ret) {
4609 _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node,
4610 "Cannot visit root scope's field class: "
4611 "ret=%d", ret);
4612 BT_ASSERT(!decl);
4613 goto end;
4614 }
4615
4616 ctf_field_class_destroy(decl);
4617 decl = NULL;
4618 break;
4619 }
4620 default:
4621 _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node,
4622 "Unexpected node type: node-type=%d",
4623 root_decl_node->type);
4624 ret = -EPERM;
4625 goto end;
4626 }
4627
4628 end:
4629 return ret;
4630 }
4631
4632 BT_HIDDEN
4633 struct ctf_visitor_generate_ir *ctf_visitor_generate_ir_create(
4634 const struct ctf_metadata_decoder_config *decoder_config)
4635 {
4636 struct ctx *ctx = NULL;
4637
4638 /* Create visitor's context */
4639 ctx = ctx_create(decoder_config);
4640 if (!ctx) {
4641 BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR, decoder_config->log_level,
4642 decoder_config->self_comp,
4643 "Cannot create visitor's context.");
4644 goto error;
4645 }
4646
4647 goto end;
4648
4649 error:
4650 ctx_destroy(ctx);
4651 ctx = NULL;
4652
4653 end:
4654 return (void *) ctx;
4655 }
4656
4657 BT_HIDDEN
4658 void ctf_visitor_generate_ir_destroy(struct ctf_visitor_generate_ir *visitor)
4659 {
4660 ctx_destroy((void *) visitor);
4661 }
4662
4663 BT_HIDDEN
4664 bt_trace_class *ctf_visitor_generate_ir_get_ir_trace_class(
4665 struct ctf_visitor_generate_ir *visitor)
4666 {
4667 struct ctx *ctx = (void *) visitor;
4668
4669 BT_ASSERT_DBG(ctx);
4670
4671 if (ctx->trace_class) {
4672 bt_trace_class_get_ref(ctx->trace_class);
4673 }
4674
4675 return ctx->trace_class;
4676 }
4677
4678 BT_HIDDEN
4679 struct ctf_trace_class *ctf_visitor_generate_ir_borrow_ctf_trace_class(
4680 struct ctf_visitor_generate_ir *visitor)
4681 {
4682 struct ctx *ctx = (void *) visitor;
4683
4684 BT_ASSERT_DBG(ctx);
4685 BT_ASSERT_DBG(ctx->ctf_tc);
4686 return ctx->ctf_tc;
4687 }
4688
4689 BT_HIDDEN
4690 int ctf_visitor_generate_ir_visit_node(struct ctf_visitor_generate_ir *visitor,
4691 struct ctf_node *node)
4692 {
4693 int ret = 0;
4694 struct ctx *ctx = (void *) visitor;
4695
4696 BT_COMP_LOGI_STR("Visiting metadata's AST to generate CTF IR objects.");
4697
4698 switch (node->type) {
4699 case NODE_ROOT:
4700 {
4701 struct ctf_node *iter;
4702 bool got_trace_decl = false;
4703
4704 /*
4705 * The first thing we need is the native byte order of
4706 * the trace block, because early class aliases can have
4707 * a `byte_order` attribute set to `native`. If we don't
4708 * have the native byte order yet, and we don't have any
4709 * trace block yet, then fail with EINCOMPLETE.
4710 */
4711 if (ctx->ctf_tc->default_byte_order == CTF_BYTE_ORDER_UNKNOWN) {
4712 bt_list_for_each_entry(iter, &node->u.root.trace, siblings) {
4713 if (got_trace_decl) {
4714 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
4715 "Duplicate trace (`trace` block).");
4716 ret = -1;
4717 goto end;
4718 }
4719
4720 ret = set_trace_byte_order(ctx, iter);
4721 if (ret) {
4722 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
4723 "Cannot set trace's native byte order: "
4724 "ret=%d", ret);
4725 goto end;
4726 }
4727
4728 got_trace_decl = true;
4729 }
4730
4731 if (!got_trace_decl) {
4732 BT_COMP_LOGD_STR("Incomplete AST: need trace (`trace` block).");
4733 ret = -EINCOMPLETE;
4734 goto end;
4735 }
4736 }
4737
4738 BT_ASSERT(ctx->ctf_tc->default_byte_order == CTF_BYTE_ORDER_LITTLE ||
4739 ctx->ctf_tc->default_byte_order == CTF_BYTE_ORDER_BIG);
4740 BT_ASSERT(ctx->current_scope &&
4741 !ctx->current_scope->parent_scope);
4742
4743 /* Environment */
4744 bt_list_for_each_entry(iter, &node->u.root.env, siblings) {
4745 ret = visit_env(ctx, iter);
4746 if (ret) {
4747 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter,
4748 "Cannot visit trace's environment (`env` block) entry: "
4749 "ret=%d", ret);
4750 goto end;
4751 }
4752 }
4753
4754 BT_ASSERT(ctx->current_scope &&
4755 !ctx->current_scope->parent_scope);
4756
4757 /*
4758 * Visit clock blocks.
4759 */
4760 bt_list_for_each_entry(iter, &node->u.root.clock, siblings) {
4761 ret = visit_clock_decl(ctx, iter);
4762 if (ret) {
4763 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter,
4764 "Cannot visit clock class: ret=%d",
4765 ret);
4766 goto end;
4767 }
4768 }
4769
4770 BT_ASSERT(ctx->current_scope &&
4771 !ctx->current_scope->parent_scope);
4772
4773 /*
4774 * Visit root declarations next, as they can be used by any
4775 * following entity.
4776 */
4777 bt_list_for_each_entry(iter, &node->u.root.declaration_list,
4778 siblings) {
4779 ret = visit_root_decl(ctx, iter);
4780 if (ret) {
4781 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter,
4782 "Cannot visit root entry: ret=%d",
4783 ret);
4784 goto end;
4785 }
4786 }
4787
4788 BT_ASSERT(ctx->current_scope &&
4789 !ctx->current_scope->parent_scope);
4790
4791 /* Callsite blocks are not supported */
4792 bt_list_for_each_entry(iter, &node->u.root.callsite, siblings) {
4793 _BT_COMP_LOGW_NODE(iter,
4794 "\"callsite\" blocks are not supported as of this version.");
4795 }
4796
4797 BT_ASSERT(ctx->current_scope &&
4798 !ctx->current_scope->parent_scope);
4799
4800 /* Trace */
4801 bt_list_for_each_entry(iter, &node->u.root.trace, siblings) {
4802 ret = visit_trace_decl(ctx, iter);
4803 if (ret) {
4804 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter,
4805 "Cannot visit trace (`trace` block): "
4806 "ret=%d", ret);
4807 goto end;
4808 }
4809 }
4810
4811 BT_ASSERT(ctx->current_scope &&
4812 !ctx->current_scope->parent_scope);
4813
4814 /* Streams */
4815 bt_list_for_each_entry(iter, &node->u.root.stream, siblings) {
4816 ret = visit_stream_decl(ctx, iter);
4817 if (ret) {
4818 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter,
4819 "Cannot visit stream class: ret=%d",
4820 ret);
4821 goto end;
4822 }
4823 }
4824
4825 BT_ASSERT(ctx->current_scope &&
4826 !ctx->current_scope->parent_scope);
4827
4828 /* Events */
4829 bt_list_for_each_entry(iter, &node->u.root.event, siblings) {
4830 ret = visit_event_decl(ctx, iter);
4831 if (ret) {
4832 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter,
4833 "Cannot visit event class: ret=%d",
4834 ret);
4835 goto end;
4836 }
4837 }
4838
4839 BT_ASSERT(ctx->current_scope &&
4840 !ctx->current_scope->parent_scope);
4841 break;
4842 }
4843 default:
4844 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node,
4845 "Unexpected node type: node-type=%d",
4846 node->type);
4847 ret = -EINVAL;
4848 goto end;
4849 }
4850
4851 /* Update default clock classes */
4852 ret = ctf_trace_class_update_default_clock_classes(ctx->ctf_tc,
4853 &ctx->log_cfg);
4854 if (ret) {
4855 ret = -EINVAL;
4856 goto end;
4857 }
4858
4859 /* Update trace class meanings */
4860 ret = ctf_trace_class_update_meanings(ctx->ctf_tc);
4861 if (ret) {
4862 ret = -EINVAL;
4863 goto end;
4864 }
4865
4866 /* Update stream class configuration */
4867 ret = ctf_trace_class_update_stream_class_config(ctx->ctf_tc);
4868 if (ret) {
4869 ret = -EINVAL;
4870 goto end;
4871 }
4872
4873 /* Update text arrays and sequences */
4874 ret = ctf_trace_class_update_text_array_sequence(ctx->ctf_tc);
4875 if (ret) {
4876 ret = -EINVAL;
4877 goto end;
4878 }
4879
4880 /* Update structure/array/sequence alignments */
4881 ret = ctf_trace_class_update_alignments(ctx->ctf_tc);
4882 if (ret) {
4883 ret = -EINVAL;
4884 goto end;
4885 }
4886
4887 /* Resolve sequence lengths and variant tags */
4888 ret = ctf_trace_class_resolve_field_classes(ctx->ctf_tc, &ctx->log_cfg);
4889 if (ret) {
4890 ret = -EINVAL;
4891 goto end;
4892 }
4893
4894 if (ctx->trace_class) {
4895 /*
4896 * Update "in IR" for field classes.
4897 *
4898 * If we have no IR trace class, then we'll have no way
4899 * to create IR fields anyway, so we leave all the
4900 * `in_ir` members false.
4901 */
4902 ret = ctf_trace_class_update_in_ir(ctx->ctf_tc);
4903 if (ret) {
4904 ret = -EINVAL;
4905 goto end;
4906 }
4907 }
4908
4909 /* Update saved value indexes */
4910 ret = ctf_trace_class_update_value_storing_indexes(ctx->ctf_tc);
4911 if (ret) {
4912 ret = -EINVAL;
4913 goto end;
4914 }
4915
4916 /* Validate what we have so far */
4917 ret = ctf_trace_class_validate(ctx->ctf_tc, &ctx->log_cfg);
4918 if (ret) {
4919 ret = -EINVAL;
4920 goto end;
4921 }
4922
4923 /*
4924 * If there are fields which are not related to the CTF format
4925 * itself in the packet header and in event header field
4926 * classes, warn about it because they are never translated.
4927 */
4928 ctf_trace_class_warn_meaningless_header_fields(ctx->ctf_tc,
4929 &ctx->log_cfg);
4930
4931 if (ctx->trace_class) {
4932 /* Copy new CTF metadata -> new IR metadata */
4933 ret = ctf_trace_class_translate(ctx->log_cfg.self_comp,
4934 ctx->trace_class, ctx->ctf_tc);
4935 if (ret) {
4936 ret = -EINVAL;
4937 goto end;
4938 }
4939 }
4940
4941 end:
4942 return ret;
4943 }
This page took 0.189515 seconds and 4 git commands to generate.