2 * SPDX-License-Identifier: MIT
4 * Copyright 2010 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
5 * Copyright 2015-2018 Philippe Proulx <philippe.proulx@efficios.com>
7 * Common Trace Format metadata visitor (generates CTF IR objects).
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"
22 #include "common/assert.h"
26 #include "common/common.h"
27 #include "common/uuid.h"
28 #include "compat/endian.h"
29 #include <babeltrace2/babeltrace.h>
36 #include "ctf-meta-visitors.h"
38 /* Bit value (left shift) */
39 #define _BV(_val) (1 << (_val))
41 /* Bit is set in a set of bits */
42 #define _IS_SET(_set, _mask) (*(_set) & (_mask))
44 /* Set bit in a set of bits */
45 #define _SET(_set, _mask) (*(_set) |= (_mask))
47 /* Try to push scope, or go to the `error` label */
48 #define _TRY_PUSH_SCOPE_OR_GOTO_ERROR() \
50 ret = ctx_push_scope(ctx); \
52 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot push scope."); \
57 /* Bits for verifying existing attributes in various declarations */
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),
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),
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),
87 _STRING_ENCODING_SET
= _BV(0),
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),
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),
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),
120 LOG_LEVEL_WARNING
= 4,
121 LOG_LEVEL_NOTICE
= 5,
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,
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'
140 /* First entry in a BT list */
141 #define _BT_LIST_FIRST_ENTRY(_ptr, _class, _member) \
142 bt_list_entry((_ptr)->next, _class, _member)
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\"", \
149 #define _BT_COMP_LOGE_NODE(_node, _msg, args...) \
150 _BT_COMP_LOGE_LINENO((_node)->lineno, _msg, ## args)
152 #define _BT_COMP_LOGE_APPEND_CAUSE_NODE(_node, _msg, args...) \
153 _BT_COMP_LOGE_APPEND_CAUSE_LINENO((_node)->lineno, _msg, ## args)
155 #define _BT_COMP_LOGW_NODE(_node, _msg, args...) \
156 _BT_COMP_LOGW_LINENO((_node)->lineno, _msg, ## args)
158 #define _BT_COMP_LOGT_NODE(_node, _msg, args...) \
159 _BT_COMP_LOGT_LINENO((_node)->lineno, _msg, ## args)
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.
166 struct ctx_decl_scope
{
168 * Alias name to field class.
170 * GQuark -> struct ctf_field_class * (owned by this)
172 GHashTable
*decl_map
;
174 /* Parent scope; NULL if this is the root declaration scope */
175 struct ctx_decl_scope
*parent_scope
;
179 * Visitor context (private).
182 struct meta_log_config log_cfg
;
184 /* Trace IR trace class being filled (owned by this) */
185 bt_trace_class
*trace_class
;
187 /* CTF meta trace being filled (owned by this) */
188 struct ctf_trace_class
*ctf_tc
;
190 /* Current declaration scope (top of the stack) (owned by this) */
191 struct ctx_decl_scope
*current_scope
;
193 /* True if trace declaration is visited */
194 bool is_trace_visited
;
196 /* True if this is an LTTng trace */
199 /* Config passed by the user */
200 struct ctf_metadata_decoder_config decoder_config
;
206 struct ctf_visitor_generate_ir
;
209 * Creates a new declaration scope.
211 * @param par_scope Parent scope (NULL if creating a root scope)
212 * @returns New declaration scope, or NULL on error
215 struct ctx_decl_scope
*ctx_decl_scope_create(struct ctx
*ctx
,
216 struct ctx_decl_scope
*par_scope
)
218 struct ctx_decl_scope
*scope
;
220 scope
= g_new(struct ctx_decl_scope
, 1);
222 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Failed to allocate one declaration scope.");
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
;
235 * Destroys a declaration scope.
237 * This function does not destroy the parent scope.
239 * @param scope Scope to destroy
242 void ctx_decl_scope_destroy(struct ctx_decl_scope
*scope
)
248 g_hash_table_destroy(scope
->decl_map
);
256 * Returns the GQuark of a prefixed alias.
258 * @param prefix Prefix character
260 * @returns Associated GQuark, or 0 on error
263 GQuark
get_prefixed_named_quark(struct ctx
*ctx
, char prefix
, const char *name
)
269 /* Prefix character + original string + '\0' */
270 char *prname
= g_new(char, strlen(name
) + 2);
272 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Failed to allocate a string.");
276 sprintf(prname
, "%c%s", prefix
, name
);
277 qname
= g_quark_from_string(prname
);
285 * Looks up a prefixed class alias within a declaration scope.
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
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
)
302 struct ctf_field_class
*decl
= NULL
;
303 struct ctx_decl_scope
*cur_scope
= scope
;
307 qname
= get_prefixed_named_quark(ctx
, prefix
, name
);
316 while (cur_scope
&& cur_levels
< levels
) {
317 decl
= g_hash_table_lookup(cur_scope
->decl_map
,
318 (gconstpointer
) GUINT_TO_POINTER(qname
));
320 /* Caller's reference */
322 decl
= ctf_field_class_copy(decl
);
329 cur_scope
= cur_scope
->parent_scope
;
338 * Looks up a class alias within a declaration scope.
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
348 struct ctf_field_class
*ctx_decl_scope_lookup_alias(struct ctx
*ctx
,
349 struct ctx_decl_scope
*scope
, const char *name
, int levels
,
352 return ctx_decl_scope_lookup_prefix_alias(ctx
, scope
, _PREFIX_ALIAS
,
357 * Looks up an enumeration within a declaration scope.
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
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
,
371 return (void *) ctx_decl_scope_lookup_prefix_alias(ctx
, scope
,
372 _PREFIX_ENUM
, name
, levels
, copy
);
376 * Looks up a structure within a declaration scope.
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
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
,
390 return (void *) ctx_decl_scope_lookup_prefix_alias(ctx
, scope
,
391 _PREFIX_STRUCT
, name
, levels
, copy
);
395 * Looks up a variant within a declaration scope.
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
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
,
409 return (void *) ctx_decl_scope_lookup_prefix_alias(ctx
, scope
,
410 _PREFIX_VARIANT
, name
, levels
, copy
);
414 * Registers a prefixed class alias within a declaration scope.
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
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
)
433 qname
= get_prefixed_named_quark(ctx
, prefix
, name
);
439 /* Make sure alias does not exist in local scope */
440 if (ctx_decl_scope_lookup_prefix_alias(ctx
, scope
, prefix
, name
, 1,
446 decl
= ctf_field_class_copy(decl
);
448 g_hash_table_insert(scope
->decl_map
, GUINT_TO_POINTER(qname
), decl
);
455 * Registers a class alias within a declaration scope.
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
463 int ctx_decl_scope_register_alias(struct ctx
*ctx
, struct ctx_decl_scope
*scope
,
464 const char *name
, struct ctf_field_class
*decl
)
466 return ctx_decl_scope_register_prefix_alias(ctx
, scope
, _PREFIX_ALIAS
,
467 name
, (void *) decl
);
471 * Registers an enumeration declaration within a declaration scope.
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
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
)
482 return ctx_decl_scope_register_prefix_alias(ctx
, scope
, _PREFIX_ENUM
,
483 name
, (void *) decl
);
487 * Registers a structure declaration within a declaration scope.
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
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
)
499 return ctx_decl_scope_register_prefix_alias(ctx
, scope
, _PREFIX_STRUCT
,
500 name
, (void *) decl
);
504 * Registers a variant declaration within a declaration scope.
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
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
)
516 return ctx_decl_scope_register_prefix_alias(ctx
, scope
, _PREFIX_VARIANT
,
517 name
, (void *) decl
);
521 * Destroys a visitor context.
523 * @param ctx Visitor context to destroy
526 void ctx_destroy(struct ctx
*ctx
)
528 struct ctx_decl_scope
*scope
;
534 scope
= ctx
->current_scope
;
537 * Destroy all scopes, from current one to the root scope.
540 struct ctx_decl_scope
*parent_scope
= scope
->parent_scope
;
542 ctx_decl_scope_destroy(scope
);
543 scope
= parent_scope
;
546 bt_trace_class_put_ref(ctx
->trace_class
);
549 ctf_trace_class_destroy(ctx
->ctf_tc
);
559 * Creates a new visitor context.
561 * @param trace Associated trace
562 * @returns New visitor context, or NULL on error
565 struct ctx
*ctx_create(const struct ctf_metadata_decoder_config
*decoder_config
)
567 struct ctx
*ctx
= NULL
;
569 BT_ASSERT(decoder_config
);
571 ctx
= g_new0(struct ctx
, 1);
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.");
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
;
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.");
592 ctx
->ctf_tc
= ctf_trace_class_create();
594 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot create CTF trace class.");
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.");
605 ctx
->decoder_config
= *decoder_config
;
617 * Pushes a new declaration scope on top of a visitor context's
618 * declaration scope stack.
620 * @param ctx Visitor context
621 * @returns 0 on success, or a negative value on error
624 int ctx_push_scope(struct ctx
*ctx
)
627 struct ctx_decl_scope
*new_scope
;
630 new_scope
= ctx_decl_scope_create(ctx
, ctx
->current_scope
);
632 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot create declaration scope.");
637 ctx
->current_scope
= new_scope
;
644 void ctx_pop_scope(struct ctx
*ctx
)
646 struct ctx_decl_scope
*parent_scope
= NULL
;
650 if (!ctx
->current_scope
) {
654 parent_scope
= ctx
->current_scope
->parent_scope
;
655 ctx_decl_scope_destroy(ctx
->current_scope
);
656 ctx
->current_scope
= parent_scope
;
663 int visit_field_class_specifier_list(struct ctx
*ctx
, struct ctf_node
*ts_list
,
664 struct ctf_field_class
**decl
);
667 int is_unary_string(struct bt_list_head
*head
)
670 struct ctf_node
*node
;
672 bt_list_for_each_entry(node
, head
, siblings
) {
673 if (node
->type
!= NODE_UNARY_EXPRESSION
) {
677 if (node
->u
.unary_expression
.type
!= UNARY_STRING
) {
686 const char *get_map_clock_name_value(struct bt_list_head
*head
)
689 struct ctf_node
*node
;
690 const char *name
= NULL
;
692 bt_list_for_each_entry(node
, head
, siblings
) {
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));
703 /* Needs to be chained with . */
704 switch (node
->u
.unary_expression
.link
) {
707 case UNARY_ARROWLINK
:
708 case UNARY_DOTDOTDOT
:
714 src_string
= node
->u
.unary_expression
.u
.string
;
718 if (strcmp("clock", src_string
)) {
726 if (strcmp("value", src_string
)) {
731 /* Extra identifier, unknown */
745 int is_unary_unsigned(struct bt_list_head
*head
)
748 struct ctf_node
*node
;
750 bt_list_for_each_entry(node
, head
, siblings
) {
751 if (node
->type
!= NODE_UNARY_EXPRESSION
) {
755 if (node
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
764 int get_unary_unsigned(struct ctx
*ctx
, struct bt_list_head
*head
,
769 struct ctf_node
*node
;
773 if (bt_list_empty(head
)) {
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;
785 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Invalid constant unsigned integer.");
790 *value
= node
->u
.unary_expression
.u
.unsigned_constant
;
799 int is_unary_signed(struct bt_list_head
*head
)
802 struct ctf_node
*node
;
804 bt_list_for_each_entry(node
, head
, siblings
) {
805 if (node
->type
!= NODE_UNARY_EXPRESSION
) {
809 if (node
->u
.unary_expression
.type
!= UNARY_SIGNED_CONSTANT
) {
818 int get_unary_signed(struct bt_list_head
*head
, int64_t *value
)
822 struct ctf_node
*node
;
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;
836 switch (uexpr_type
) {
837 case UNARY_UNSIGNED_CONSTANT
:
839 node
->u
.unary_expression
.u
.unsigned_constant
;
841 case UNARY_SIGNED_CONSTANT
:
842 *value
= node
->u
.unary_expression
.u
.signed_constant
;
857 int get_unary_uuid(struct ctx
*ctx
, struct bt_list_head
*head
,
860 return ctf_ast_get_unary_uuid(head
, uuid
, ctx
->log_cfg
.log_level
,
861 ctx
->log_cfg
.self_comp
);
865 int get_boolean(struct ctx
*ctx
, struct ctf_node
*unary_expr
)
869 if (unary_expr
->type
!= NODE_UNARY_EXPRESSION
) {
870 _BT_COMP_LOGE_APPEND_CAUSE_NODE(unary_expr
,
871 "Expecting unary expression: node-type=%d",
877 switch (unary_expr
->u
.unary_expression
.type
) {
878 case UNARY_UNSIGNED_CONSTANT
:
879 ret
= (unary_expr
->u
.unary_expression
.u
.unsigned_constant
!= 0);
881 case UNARY_SIGNED_CONSTANT
:
882 ret
= (unary_expr
->u
.unary_expression
.u
.signed_constant
!= 0);
886 const char *str
= unary_expr
->u
.unary_expression
.u
.string
;
888 if (strcmp(str
, "true") == 0 || strcmp(str
, "TRUE") == 0) {
890 } else if (strcmp(str
, "false") == 0 || strcmp(str
, "FALSE") == 0) {
893 _BT_COMP_LOGE_APPEND_CAUSE_NODE(unary_expr
,
894 "Unexpected boolean value: value=\"%s\"", str
);
901 _BT_COMP_LOGE_APPEND_CAUSE_NODE(unary_expr
,
902 "Unexpected unary expression type: node-type=%d",
903 unary_expr
->u
.unary_expression
.type
);
913 enum ctf_byte_order
byte_order_from_unary_expr(struct ctx
*ctx
,
914 struct ctf_node
*unary_expr
)
917 enum ctf_byte_order bo
= CTF_BYTE_ORDER_UNKNOWN
;
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`.");
925 str
= unary_expr
->u
.unary_expression
.u
.string
;
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
;
934 _BT_COMP_LOGE_APPEND_CAUSE_NODE(unary_expr
,
935 "Unexpected \"byte_order\" attribute value: "
936 "expecting `be`, `le`, `network`, or `native`: value=\"%s\"",
946 enum ctf_byte_order
get_real_byte_order(struct ctx
*ctx
,
947 struct ctf_node
*uexpr
)
949 enum ctf_byte_order bo
= byte_order_from_unary_expr(ctx
, uexpr
);
951 if (bo
== CTF_BYTE_ORDER_DEFAULT
) {
952 bo
= ctx
->ctf_tc
->default_byte_order
;
959 int is_align_valid(uint64_t align
)
961 return (align
!= 0) && !(align
& (align
- UINT64_C(1)));
965 int get_class_specifier_name(struct ctx
*ctx
, struct ctf_node
*cls_specifier
,
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
);
978 switch (cls_specifier
->u
.field_class_specifier
.type
) {
980 g_string_append(str
, "void");
983 g_string_append(str
, "char");
986 g_string_append(str
, "short");
989 g_string_append(str
, "int");
992 g_string_append(str
, "long");
995 g_string_append(str
, "float");
997 case TYPESPEC_DOUBLE
:
998 g_string_append(str
, "double");
1000 case TYPESPEC_SIGNED
:
1001 g_string_append(str
, "signed");
1003 case TYPESPEC_UNSIGNED
:
1004 g_string_append(str
, "unsigned");
1007 g_string_append(str
, "bool");
1009 case TYPESPEC_COMPLEX
:
1010 g_string_append(str
, "_Complex");
1012 case TYPESPEC_IMAGINARY
:
1013 g_string_append(str
, "_Imaginary");
1015 case TYPESPEC_CONST
:
1016 g_string_append(str
, "const");
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
);
1024 case TYPESPEC_STRUCT
:
1026 struct ctf_node
*node
= cls_specifier
->u
.field_class_specifier
.node
;
1028 if (!node
->u
._struct
.name
) {
1029 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Unexpected empty structure field class name.");
1034 g_string_append(str
, "struct ");
1035 g_string_append(str
, node
->u
._struct
.name
);
1038 case TYPESPEC_VARIANT
:
1040 struct ctf_node
*node
= cls_specifier
->u
.field_class_specifier
.node
;
1042 if (!node
->u
.variant
.name
) {
1043 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Unexpected empty variant field class name.");
1048 g_string_append(str
, "variant ");
1049 g_string_append(str
, node
->u
.variant
.name
);
1054 struct ctf_node
*node
= cls_specifier
->u
.field_class_specifier
.node
;
1056 if (!node
->u
._enum
.enum_id
) {
1057 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
1058 "Unexpected empty enumeration field class (`enum`) name.");
1063 g_string_append(str
, "enum ");
1064 g_string_append(str
, node
->u
._enum
.enum_id
);
1067 case TYPESPEC_FLOATING_POINT
:
1068 case TYPESPEC_INTEGER
:
1069 case TYPESPEC_STRING
:
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
);
1083 int get_class_specifier_list_name(struct ctx
*ctx
,
1084 struct ctf_node
*cls_specifier_list
, GString
*str
)
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
;
1092 bt_list_for_each_entry(iter
, head
, siblings
) {
1093 if (alias_item_nr
!= 0) {
1094 g_string_append(str
, " ");
1098 ret
= get_class_specifier_name(ctx
, iter
, str
);
1109 GQuark
create_class_alias_identifier(struct ctx
*ctx
,
1110 struct ctf_node
*cls_specifier_list
,
1111 struct ctf_node
*node_field_class_declarator
)
1117 struct ctf_node
*iter
;
1118 struct bt_list_head
*pointers
=
1119 &node_field_class_declarator
->u
.field_class_declarator
.pointers
;
1121 str
= g_string_new("");
1122 ret
= get_class_specifier_list_name(ctx
, cls_specifier_list
, str
);
1124 g_string_free(str
, TRUE
);
1128 bt_list_for_each_entry(iter
, pointers
, siblings
) {
1129 g_string_append(str
, " *");
1131 if (iter
->u
.pointer
.const_qualifier
) {
1132 g_string_append(str
, " const");
1136 str_c
= g_string_free(str
, FALSE
);
1137 qalias
= g_quark_from_string(str_c
);
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
)
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).
1159 /* Validate field class declarator node */
1160 if (node_field_class_declarator
) {
1161 if (node_field_class_declarator
->u
.field_class_declarator
.type
==
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
);
1170 /* TODO: GCC bitfields not supported yet */
1171 if (node_field_class_declarator
->u
.field_class_declarator
.bitfield_len
!=
1173 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1174 "GCC bitfields are not supported as of this version.");
1180 /* Find the right nested declaration if not provided */
1182 struct bt_list_head
*pointers
=
1183 &node_field_class_declarator
->u
.field_class_declarator
.pointers
;
1185 if (node_field_class_declarator
&& !bt_list_empty(pointers
)) {
1189 * If we have a pointer declarator, it HAS to
1190 * be present in the field class aliases (else
1193 qalias
= create_class_alias_identifier(ctx
,
1194 cls_specifier_list
, node_field_class_declarator
);
1196 ctx_decl_scope_lookup_alias(ctx
,
1198 g_quark_to_string(qalias
), -1, true);
1200 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1201 "Cannot find class alias: name=\"%s\"",
1202 g_quark_to_string(qalias
));
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
;
1213 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
;
1216 ret
= visit_field_class_specifier_list(ctx
,
1217 cls_specifier_list
, &nested_decl
);
1219 BT_ASSERT(!nested_decl
);
1225 BT_ASSERT(nested_decl
);
1227 if (!node_field_class_declarator
) {
1228 *field_decl
= nested_decl
;
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
) {
1236 node_field_class_declarator
->u
.field_class_declarator
.u
.id
;
1238 *field_name
= g_quark_from_string(id
);
1243 *field_decl
= nested_decl
;
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
;
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.");
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",
1271 switch (first
->u
.unary_expression
.type
) {
1272 case UNARY_UNSIGNED_CONSTANT
:
1274 struct ctf_field_class_array
*array_decl
= NULL
;
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
;
1282 decl
= (void *) array_decl
;
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
);
1292 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1293 "Cannot concatenate unary strings.");
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
;
1307 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node_field_class_declarator
,
1308 "Cannot find environment entry: "
1309 "name=\"%s\"", env_entry_name
);
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
);
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\", "
1329 env_entry
->value
.i
);
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
;
1340 decl
= (void *) array_decl
;
1342 seq_decl
= ctf_field_class_sequence_create();
1343 BT_ASSERT(seq_decl
);
1344 seq_decl
->base
.elem_fc
= nested_decl
;
1346 g_string_assign(seq_decl
->length_ref
,
1348 decl
= (void *) seq_decl
;
1351 g_free(length_name
);
1359 BT_ASSERT(!nested_decl
);
1361 BT_ASSERT(!*field_decl
);
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.
1370 ret
= visit_field_class_declarator(ctx
, cls_specifier_list
,
1372 node_field_class_declarator
->
1373 u
.field_class_declarator
.u
.nested
.field_class_declarator
,
1374 &outer_field_decl
, decl
);
1377 BT_ASSERT(!outer_field_decl
);
1382 BT_ASSERT(outer_field_decl
);
1383 *field_decl
= outer_field_decl
;
1384 outer_field_decl
= NULL
;
1387 BT_ASSERT(*field_decl
);
1391 ctf_field_class_destroy(*field_decl
);
1399 ctf_field_class_destroy(nested_decl
);
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
)
1411 struct ctf_node
*iter
;
1412 struct ctf_field_class
*field_decl
= NULL
;
1414 bt_list_for_each_entry(iter
, field_class_declarators
, siblings
) {
1417 const char *field_name
;
1419 ret
= visit_field_class_declarator(ctx
, cls_specifier_list
,
1420 &qfield_name
, iter
, &field_decl
, NULL
);
1422 BT_ASSERT(!field_decl
);
1423 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
1424 "Cannot visit field class declarator: ret=%d", ret
);
1428 BT_ASSERT(field_decl
);
1429 field_name
= g_quark_to_string(qfield_name
);
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
);
1441 /* Add field to structure */
1442 ctf_field_class_struct_append_member(struct_decl
,
1443 field_name
, field_decl
);
1450 ctf_field_class_destroy(field_decl
);
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
)
1462 struct ctf_node
*iter
;
1463 struct ctf_field_class
*field_decl
= NULL
;
1465 bt_list_for_each_entry(iter
, field_class_declarators
, siblings
) {
1468 const char *field_name
;
1470 ret
= visit_field_class_declarator(ctx
, cls_specifier_list
,
1471 &qfield_name
, iter
, &field_decl
, NULL
);
1473 BT_ASSERT(!field_decl
);
1474 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
1475 "Cannot visit field class declarator: ret=%d", ret
);
1479 BT_ASSERT(field_decl
);
1480 field_name
= g_quark_to_string(qfield_name
);
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
);
1492 /* Add field to structure */
1493 ctf_field_class_variant_append_option(variant_decl
,
1494 field_name
, field_decl
);
1501 ctf_field_class_destroy(field_decl
);
1507 int visit_field_class_def(struct ctx
*ctx
, struct ctf_node
*cls_specifier_list
,
1508 struct bt_list_head
*field_class_declarators
)
1512 struct ctf_node
*iter
;
1513 struct ctf_field_class
*class_decl
= NULL
;
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
);
1519 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
1520 "Cannot visit field class declarator: ret=%d", ret
);
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
;
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.");
1538 ret
= ctx_decl_scope_register_alias(ctx
, ctx
->current_scope
,
1539 g_quark_to_string(qidentifier
), class_decl
);
1541 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
1542 "Cannot register field class alias: name=\"%s\"",
1543 g_quark_to_string(qidentifier
));
1549 ctf_field_class_destroy(class_decl
);
1555 int visit_field_class_alias(struct ctx
*ctx
, struct ctf_node
*target
,
1556 struct ctf_node
*alias
)
1560 struct ctf_node
*node
;
1561 GQuark qdummy_field_name
;
1562 struct ctf_field_class
*class_decl
= NULL
;
1564 /* Create target field class */
1565 if (bt_list_empty(&target
->u
.field_class_alias_target
.field_class_declarators
)) {
1568 node
= _BT_LIST_FIRST_ENTRY(
1569 &target
->u
.field_class_alias_target
.field_class_declarators
,
1570 struct ctf_node
, siblings
);
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
);
1577 BT_ASSERT(!class_decl
);
1578 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
1579 "Cannot visit field class declarator: ret=%d", ret
);
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
;
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.");
1596 * The semantic validator does not check whether the target is
1597 * abstract or not (if it has an identifier). Check it here.
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
));
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
);
1615 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
1616 "Cannot register class alias: name=\"%s\"",
1617 g_quark_to_string(qalias
));
1622 ctf_field_class_destroy(class_decl
);
1628 int visit_struct_decl_entry(struct ctx
*ctx
, struct ctf_node
*entry_node
,
1629 struct ctf_field_class_struct
*struct_decl
)
1633 switch (entry_node
->type
) {
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
);
1639 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
1640 "Cannot add field class found in structure field class: ret=%d",
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
);
1649 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
1650 "Cannot add field class alias found in structure field class: ret=%d",
1655 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
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
);
1667 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
1668 "Unexpected node type: node-type=%d", entry_node
->type
);
1678 int visit_variant_decl_entry(struct ctx
*ctx
, struct ctf_node
*entry_node
,
1679 struct ctf_field_class_variant
*variant_decl
)
1683 switch (entry_node
->type
) {
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
);
1689 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
1690 "Cannot add field class found in variant field class: ret=%d",
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
);
1699 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
1700 "Cannot add field class alias found in variant field class: ret=%d",
1705 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
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
);
1717 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
1718 "Unexpected node type: node-type=%d",
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
)
1736 BT_ASSERT(struct_decl
);
1737 *struct_decl
= NULL
;
1739 /* For named struct (without body), lookup in declaration scope */
1742 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Bodyless structure field class: missing name.");
1747 *struct_decl
= ctx_decl_scope_lookup_struct(ctx
, ctx
->current_scope
,
1749 if (!*struct_decl
) {
1750 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot find structure field class: name=\"struct %s\"",
1756 struct ctf_node
*entry_node
;
1757 uint64_t min_align_value
= 0;
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
);
1769 if (!bt_list_empty(min_align
)) {
1770 ret
= get_unary_unsigned(ctx
, min_align
,
1773 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Unexpected unary expression for structure field class's `align` attribute: "
1779 *struct_decl
= ctf_field_class_struct_create();
1780 BT_ASSERT(*struct_decl
);
1782 if (min_align_value
!= 0) {
1783 (*struct_decl
)->base
.alignment
= min_align_value
;
1786 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
1788 bt_list_for_each_entry(entry_node
, decl_list
, siblings
) {
1789 ret
= visit_struct_decl_entry(ctx
, entry_node
,
1792 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
1793 "Cannot visit structure field class entry: "
1803 ret
= ctx_decl_scope_register_struct(ctx
,
1804 ctx
->current_scope
, name
, *struct_decl
);
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
);
1816 ctf_field_class_destroy((void *) *struct_decl
);
1817 *struct_decl
= NULL
;
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
)
1827 struct ctf_field_class_variant
*untagged_variant_decl
= NULL
;
1829 BT_ASSERT(variant_decl
);
1830 *variant_decl
= NULL
;
1832 /* For named variant (without body), lookup in declaration scope */
1835 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Bodyless variant field class: missing name.");
1840 untagged_variant_decl
=
1841 ctx_decl_scope_lookup_variant(ctx
, ctx
->current_scope
,
1843 if (!untagged_variant_decl
) {
1844 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot find variant field class: name=\"variant %s\"",
1850 struct ctf_node
*entry_node
;
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
);
1862 untagged_variant_decl
= ctf_field_class_variant_create();
1863 BT_ASSERT(untagged_variant_decl
);
1864 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
1866 bt_list_for_each_entry(entry_node
, decl_list
, siblings
) {
1867 ret
= visit_variant_decl_entry(ctx
, entry_node
,
1868 untagged_variant_decl
);
1870 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
1871 "Cannot visit variant field class entry: "
1881 ret
= ctx_decl_scope_register_variant(ctx
,
1882 ctx
->current_scope
, name
,
1883 untagged_variant_decl
);
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
);
1893 * If tagged, create tagged variant and return; otherwise
1894 * return untagged variant.
1897 *variant_decl
= untagged_variant_decl
;
1898 untagged_variant_decl
= NULL
;
1901 * At this point, we have a fresh untagged variant; nobody
1902 * else owns it. Set its tag now.
1904 g_string_assign(untagged_variant_decl
->tag_ref
, tag
);
1905 *variant_decl
= untagged_variant_decl
;
1906 untagged_variant_decl
= NULL
;
1909 BT_ASSERT(!untagged_variant_decl
);
1910 BT_ASSERT(*variant_decl
);
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
;
1930 int visit_enum_decl_entry(struct ctx
*ctx
, struct ctf_node
*enumerator
,
1931 struct ctf_field_class_enum
*enum_decl
, struct uori
*last
)
1935 struct ctf_node
*iter
;
1936 struct uori start
= {
1944 const char *label
= enumerator
->u
.enumerator
.id
;
1945 struct bt_list_head
*values
= &enumerator
->u
.enumerator
.values
;
1947 bt_list_for_each_entry(iter
, values
, siblings
) {
1948 struct uori
*target
;
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
,
1965 switch (iter
->u
.unary_expression
.type
) {
1966 case UNARY_SIGNED_CONSTANT
:
1967 target
->is_signed
= true;
1969 iter
->u
.unary_expression
.u
.signed_constant
;
1971 case UNARY_UNSIGNED_CONSTANT
:
1972 target
->is_signed
= false;
1974 iter
->u
.unary_expression
.u
.unsigned_constant
;
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
);
1987 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
1988 "Invalid enumeration field class entry: label=\"%s\"",
2005 if (end
.is_signed
) {
2006 last
->value
.i
= end
.value
.i
+ 1;
2008 last
->value
.u
= end
.value
.u
+ 1;
2011 ctf_field_class_enum_map_range(enum_decl
, label
,
2012 start
.value
.u
, end
.value
.u
);
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
)
2027 struct ctf_field_class_int
*integer_decl
= NULL
;
2029 BT_ASSERT(enum_decl
);
2032 /* For named enum (without body), lookup in declaration scope */
2035 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Bodyless enumeration field class: missing name.");
2040 *enum_decl
= ctx_decl_scope_lookup_enum(ctx
, ctx
->current_scope
,
2043 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot find enumeration field class: "
2044 "name=\"enum %s\"", name
);
2049 struct ctf_node
*iter
;
2050 struct uori last_value
= {
2056 if (ctx_decl_scope_lookup_enum(ctx
, ctx
->current_scope
,
2058 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Enumeration field class already declared in local scope: "
2059 "name=\"enum %s\"", name
);
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.");
2074 ret
= visit_field_class_declarator(ctx
, container_cls
,
2075 &qdummy_id
, NULL
, (void *) &integer_decl
,
2078 BT_ASSERT(!integer_decl
);
2084 BT_ASSERT(integer_decl
);
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
);
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
;
2101 bt_list_for_each_entry(iter
, enumerator_list
, siblings
) {
2102 ret
= visit_enum_decl_entry(ctx
, iter
, *enum_decl
,
2105 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
2106 "Cannot visit enumeration field class entry: "
2113 ret
= ctx_decl_scope_register_enum(ctx
,
2114 ctx
->current_scope
, name
, *enum_decl
);
2116 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot register enumeration field class in declaration scope: "
2126 ctf_field_class_destroy((void *) *enum_decl
);
2130 ctf_field_class_destroy((void *) integer_decl
);
2131 integer_decl
= NULL
;
2136 int visit_field_class_specifier(struct ctx
*ctx
,
2137 struct ctf_node
*cls_specifier_list
,
2138 struct ctf_field_class
**decl
)
2141 GString
*str
= NULL
;
2144 str
= g_string_new("");
2145 ret
= get_class_specifier_list_name(ctx
, cls_specifier_list
, str
);
2147 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
2148 "Cannot get field class specifier list's name: ret=%d", ret
);
2152 *decl
= ctx_decl_scope_lookup_alias(ctx
, ctx
->current_scope
, str
->str
,
2155 _BT_COMP_LOGE_APPEND_CAUSE_NODE(cls_specifier_list
,
2156 "Cannot find field class alias: name=\"%s\"", str
->str
);
2164 ctf_field_class_destroy(*decl
);
2169 g_string_free(str
, TRUE
);
2176 int visit_integer_decl(struct ctx
*ctx
,
2177 struct bt_list_head
*expressions
,
2178 struct ctf_field_class_int
**integer_decl
)
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
;
2191 *integer_decl
= NULL
;
2193 bt_list_for_each_entry(expression
, expressions
, siblings
) {
2194 struct ctf_node
*left
, *right
;
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
,
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
);
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");
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: "
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");
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: "
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");
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: "
2260 right
->u
.unary_expression
.type
);
2265 size
= right
->u
.unary_expression
.u
.unsigned_constant
;
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
);
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
);
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");
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: "
2297 right
->u
.unary_expression
.type
);
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
);
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");
2322 switch (right
->u
.unary_expression
.type
) {
2323 case UNARY_UNSIGNED_CONSTANT
:
2325 uint64_t constant
= right
->u
.unary_expression
.
2326 u
.unsigned_constant
;
2330 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY
;
2333 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL
;
2336 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
;
2339 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
;
2342 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2343 "Invalid `base` attribute in integer field class: "
2345 right
->u
.unary_expression
.u
.unsigned_constant
);
2353 char *s_right
= ctf_ast_concatenate_unary_strings(
2354 &expression
->u
.ctf_expression
.right
);
2356 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2357 "Unexpected unary expression for integer field class's `base` attribute.");
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
;
2382 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2383 "Unexpected unary expression for integer field class's `base` attribute: "
2384 "base=\"%s\"", s_right
);
2394 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2395 "Invalid `base` attribute in integer field class: "
2396 "expecting unsigned constant integer or unary string.");
2401 _SET(&set
, _INTEGER_BASE_SET
);
2402 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "encoding") == 0) {
2405 if (_IS_SET(&set
, _INTEGER_ENCODING_SET
)) {
2406 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "encoding",
2407 "integer field class");
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.");
2420 s_right
= ctf_ast_concatenate_unary_strings(
2421 &expression
->u
.ctf_expression
.right
);
2423 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2424 "Unexpected unary expression for integer field class's `encoding` attribute.");
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
;
2439 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2440 "Invalid `encoding` attribute in integer field class: "
2441 "unknown encoding: encoding=\"%s\"",
2449 _SET(&set
, _INTEGER_ENCODING_SET
);
2450 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "map") == 0) {
2451 const char *clock_name
;
2453 if (_IS_SET(&set
, _INTEGER_MAP_SET
)) {
2454 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "map",
2455 "integer field class");
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.");
2469 get_map_clock_name_value(
2470 &expression
->u
.ctf_expression
.right
);
2472 char *s_right
= ctf_ast_concatenate_unary_strings(
2473 &expression
->u
.ctf_expression
.right
);
2476 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2477 "Unexpected unary expression for integer field class's `map` attribute.");
2482 _BT_COMP_LOGE_NODE(right
,
2483 "Invalid `map` attribute in integer field class: "
2484 "cannot find clock class at this point: name=\"%s\"",
2486 _SET(&set
, _INTEGER_MAP_SET
);
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\"",
2503 _SET(&set
, _INTEGER_MAP_SET
);
2505 _BT_COMP_LOGW_NODE(left
,
2506 "Unknown attribute in integer field class: "
2508 left
->u
.unary_expression
.u
.string
);
2512 if (!_IS_SET(&set
, _INTEGER_SIZE_SET
)) {
2513 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Missing `size` attribute in integer field class.");
2518 if (!_IS_SET(&set
, _INTEGER_ALIGN_SET
)) {
2519 if (size
% CHAR_BIT
) {
2520 /* Bit-packed alignment */
2523 /* Byte-packed alignment */
2524 alignment
= CHAR_BIT
;
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
;
2540 ctf_field_class_destroy((void *) *integer_decl
);
2541 *integer_decl
= NULL
;
2546 int visit_floating_point_number_decl(struct ctx
*ctx
,
2547 struct bt_list_head
*expressions
,
2548 struct ctf_field_class_float
**float_decl
)
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
;
2558 bt_list_for_each_entry(expression
, expressions
, siblings
) {
2559 struct ctf_node
*left
, *right
;
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
,
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
);
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");
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: "
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");
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: "
2607 right
->u
.unary_expression
.type
);
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");
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: "
2628 right
->u
.unary_expression
.type
);
2633 mant_dig
= right
->u
.unary_expression
.u
.
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");
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: "
2650 right
->u
.unary_expression
.type
);
2655 alignment
= right
->u
.unary_expression
.u
.
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
);
2667 _SET(&set
, _FLOAT_ALIGN_SET
);
2669 _BT_COMP_LOGW_NODE(left
,
2670 "Unknown attribute in floating point number field class: "
2672 left
->u
.unary_expression
.u
.string
);
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.");
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.");
2688 if (mant_dig
!= 24 && mant_dig
!= 53) {
2689 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("`mant_dig` attribute: expecting 24 or 53.");
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.");
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.");
2706 if (!_IS_SET(&set
, _INTEGER_ALIGN_SET
)) {
2707 if ((mant_dig
+ exp_dig
) % CHAR_BIT
) {
2708 /* Bit-packed alignment */
2711 /* Byte-packed alignment */
2712 alignment
= CHAR_BIT
;
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
;
2724 ctf_field_class_destroy((void *) *float_decl
);
2730 int visit_string_decl(struct ctx
*ctx
,
2731 struct bt_list_head
*expressions
,
2732 struct ctf_field_class_string
**string_decl
)
2736 struct ctf_node
*expression
;
2737 enum ctf_encoding encoding
= CTF_ENCODING_UTF8
;
2739 *string_decl
= NULL
;
2741 bt_list_for_each_entry(expression
, expressions
, siblings
) {
2742 struct ctf_node
*left
, *right
;
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
,
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
);
2758 if (strcmp(left
->u
.unary_expression
.u
.string
, "encoding") == 0) {
2761 if (_IS_SET(&set
, _STRING_ENCODING_SET
)) {
2762 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(left
, "encoding",
2763 "string field class");
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.");
2776 s_right
= ctf_ast_concatenate_unary_strings(
2777 &expression
->u
.ctf_expression
.right
);
2779 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2780 "Unexpected unary expression for string field class's `encoding` attribute.");
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
;
2795 _BT_COMP_LOGE_APPEND_CAUSE_NODE(right
,
2796 "Invalid `encoding` attribute in string field class: "
2797 "unknown encoding: encoding=\"%s\"",
2805 _SET(&set
, _STRING_ENCODING_SET
);
2807 _BT_COMP_LOGW_NODE(left
,
2808 "Unknown attribute in string field class: "
2810 left
->u
.unary_expression
.u
.string
);
2814 *string_decl
= ctf_field_class_string_create();
2815 BT_ASSERT(*string_decl
);
2816 (*string_decl
)->encoding
= encoding
;
2820 ctf_field_class_destroy((void *) *string_decl
);
2821 *string_decl
= NULL
;
2826 int visit_field_class_specifier_list(struct ctx
*ctx
,
2827 struct ctf_node
*ts_list
, struct ctf_field_class
**decl
)
2830 struct ctf_node
*first
, *node
;
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
);
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
);
2850 node
= first
->u
.field_class_specifier
.node
;
2852 switch (first
->u
.field_class_specifier
.type
) {
2853 case TYPESPEC_INTEGER
:
2854 ret
= visit_integer_decl(ctx
, &node
->u
.integer
.expressions
,
2861 case TYPESPEC_FLOATING_POINT
:
2862 ret
= visit_floating_point_number_decl(ctx
,
2863 &node
->u
.floating_point
.expressions
, (void *) decl
);
2869 case TYPESPEC_STRING
:
2870 ret
= visit_string_decl(ctx
,
2871 &node
->u
.string
.expressions
, (void *) decl
);
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
);
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
);
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
);
2909 case TYPESPEC_SHORT
:
2912 case TYPESPEC_FLOAT
:
2913 case TYPESPEC_DOUBLE
:
2914 case TYPESPEC_SIGNED
:
2915 case TYPESPEC_UNSIGNED
:
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
);
2923 _BT_COMP_LOGE_APPEND_CAUSE_NODE(first
,
2924 "Cannot visit field class specifier: ret=%d",
2931 _BT_COMP_LOGE_APPEND_CAUSE_NODE(first
,
2932 "Unexpected field class specifier type: node-type=%d",
2933 first
->u
.field_class_specifier
.type
);
2942 ctf_field_class_destroy((void *) *decl
);
2948 int visit_event_decl_entry(struct ctx
*ctx
, struct ctf_node
*node
,
2949 struct ctf_event_class
*event_class
, uint64_t *stream_id
,
2955 switch (node
->type
) {
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
);
2960 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
2961 "Cannot add field class found in event class.");
2965 case NODE_TYPEALIAS
:
2966 ret
= visit_field_class_alias(ctx
, node
->u
.field_class_alias
.target
,
2967 node
->u
.field_class_alias
.alias
);
2969 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
2970 "Cannot add field class alias found in event class.");
2974 case NODE_CTF_EXPRESSION
:
2976 left
= ctf_ast_concatenate_unary_strings(&node
->u
.ctf_expression
.left
);
2978 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot concatenate unary strings.");
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");
2991 _SET(set
, _EVENT_NAME_SET
);
2992 } else if (strcmp(left
, "id") == 0) {
2995 if (_IS_SET(set
, _EVENT_ID_SET
)) {
2996 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "id", "event class");
3001 ret
= get_unary_unsigned(ctx
,
3002 &node
->u
.ctf_expression
.right
,
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.");
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",
3022 ret
= get_unary_unsigned(ctx
,
3023 &node
->u
.ctf_expression
.right
, stream_id
);
3026 * Only read "stream_id" if get_unary_unsigned()
3030 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3031 "Unexpected unary expression for event class's `stream_id` attribute.");
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.");
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
);
3051 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3052 "Cannot create event class's context field class.");
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.");
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
);
3072 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3073 "Cannot create event class's payload field class.");
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;
3084 if (_IS_SET(set
, _EVENT_LOG_LEVEL_SET
)) {
3085 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "loglevel",
3091 ret
= get_unary_unsigned(ctx
,
3092 &node
->u
.ctf_expression
.right
, &loglevel_value
);
3094 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3095 "Unexpected unary expression for event class's `loglevel` attribute.");
3100 switch (loglevel_value
) {
3102 log_level
= BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY
;
3105 log_level
= BT_EVENT_CLASS_LOG_LEVEL_ALERT
;
3108 log_level
= BT_EVENT_CLASS_LOG_LEVEL_CRITICAL
;
3111 log_level
= BT_EVENT_CLASS_LOG_LEVEL_ERROR
;
3114 log_level
= BT_EVENT_CLASS_LOG_LEVEL_WARNING
;
3117 log_level
= BT_EVENT_CLASS_LOG_LEVEL_NOTICE
;
3120 log_level
= BT_EVENT_CLASS_LOG_LEVEL_INFO
;
3123 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM
;
3126 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM
;
3129 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS
;
3132 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE
;
3135 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT
;
3138 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION
;
3141 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE
;
3144 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG
;
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
);
3152 if (is_log_level_known
) {
3153 ctf_event_class_set_log_level(event_class
, log_level
);
3156 _SET(set
, _EVENT_LOG_LEVEL_SET
);
3157 } else if (strcmp(left
, "model.emf.uri") == 0) {
3160 if (_IS_SET(set
, _EVENT_MODEL_EMF_URI_SET
)) {
3161 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "model.emf.uri",
3167 right
= ctf_ast_concatenate_unary_strings(
3168 &node
->u
.ctf_expression
.right
);
3170 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3171 "Unexpected unary expression for event class's `model.emf.uri` attribute.");
3176 if (strlen(right
) == 0) {
3177 _BT_COMP_LOGW_NODE(node
,
3178 "Not setting event class's EMF URI because it's empty.");
3180 g_string_assign(event_class
->emf_uri
,
3185 _SET(set
, _EVENT_MODEL_EMF_URI_SET
);
3187 _BT_COMP_LOGW_NODE(node
,
3188 "Unknown attribute in event class: "
3189 "attr-name=\"%s\"", left
);
3211 char *get_event_decl_name(struct ctx
*ctx
, struct ctf_node
*node
)
3215 struct ctf_node
*iter
;
3216 struct bt_list_head
*decl_list
= &node
->u
.event
.declaration_list
;
3218 bt_list_for_each_entry(iter
, decl_list
, siblings
) {
3219 if (iter
->type
!= NODE_CTF_EXPRESSION
) {
3223 left
= ctf_ast_concatenate_unary_strings(&iter
->u
.ctf_expression
.left
);
3225 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
3226 "Cannot concatenate unary strings.");
3230 if (strcmp(left
, "name") == 0) {
3231 name
= ctf_ast_concatenate_unary_strings(
3232 &iter
->u
.ctf_expression
.right
);
3234 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
3235 "Unexpected unary expression for event class's `name` attribute.");
3256 int visit_event_decl(struct ctx
*ctx
, struct ctf_node
*node
)
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;
3268 if (node
->visited
) {
3272 node
->visited
= TRUE
;
3273 event_name
= get_event_decl_name(ctx
, node
);
3275 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3276 "Missing `name` attribute in event class.");
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();
3287 bt_list_for_each_entry(iter
, decl_list
, siblings
) {
3288 ret
= visit_event_decl_entry(ctx
, iter
, event_class
,
3291 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
, "Cannot visit event class's entry: "
3297 if (!_IS_SET(&set
, _EVENT_STREAM_ID_SET
)) {
3299 * Allow missing stream_id if there is only a single
3302 switch (ctx
->ctf_tc
->stream_classes
->len
) {
3304 /* Create implicit stream class if there's none */
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
,
3313 /* Single stream class: get its ID */
3314 stream_class
= ctx
->ctf_tc
->stream_classes
->pdata
[0];
3315 stream_id
= stream_class
->id
;
3318 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3319 "Missing `stream_id` attribute in event class.");
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
);
3338 BT_ASSERT(stream_class
);
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.");
3350 event_class
->id
= 0;
3353 if (ctf_stream_class_borrow_event_class_by_id(stream_class
,
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
);
3362 ctf_stream_class_append_event_class(stream_class
, event_class
);
3367 ctf_event_class_destroy(event_class
);
3385 int auto_map_field_to_trace_clock_class(struct ctx
*ctx
,
3386 struct ctf_field_class
*fc
)
3388 struct ctf_clock_class
*clock_class_to_map_to
= NULL
;
3389 struct ctf_field_class_int
*int_fc
= (void *) fc
;
3391 uint64_t clock_class_count
;
3397 if (fc
->type
!= CTF_FIELD_CLASS_TYPE_INT
&&
3398 fc
->type
!= CTF_FIELD_CLASS_TYPE_ENUM
) {
3402 if (int_fc
->mapped_clock_class
) {
3403 /* Already mapped */
3407 clock_class_count
= ctx
->ctf_tc
->clock_classes
->len
;
3409 switch (clock_class_count
) {
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
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
);
3426 * Only one clock class exists in the trace at this point: use
3429 clock_class_to_map_to
= ctx
->ctf_tc
->clock_classes
->pdata
[0];
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.
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.");
3442 BT_ASSERT(clock_class_to_map_to
);
3443 int_fc
->mapped_clock_class
= clock_class_to_map_to
;
3450 int auto_map_fields_to_trace_clock_class(struct ctx
*ctx
,
3451 struct ctf_field_class
*root_fc
, const char *field_name
)
3455 struct ctf_field_class_struct
*struct_fc
= (void *) root_fc
;
3456 struct ctf_field_class_variant
*var_fc
= (void *) root_fc
;
3462 if (root_fc
->type
!= CTF_FIELD_CLASS_TYPE_STRUCT
&&
3463 root_fc
->type
!= CTF_FIELD_CLASS_TYPE_VARIANT
) {
3467 if (root_fc
->type
== CTF_FIELD_CLASS_TYPE_STRUCT
) {
3468 count
= struct_fc
->members
->len
;
3470 count
= var_fc
->options
->len
;
3473 for (i
= 0; i
< count
; i
++) {
3474 struct ctf_named_field_class
*named_fc
= NULL
;
3476 if (root_fc
->type
== CTF_FIELD_CLASS_TYPE_STRUCT
) {
3477 named_fc
= ctf_field_class_struct_borrow_member_by_index(
3479 } else if (root_fc
->type
== CTF_FIELD_CLASS_TYPE_VARIANT
) {
3480 named_fc
= ctf_field_class_variant_borrow_option_by_index(
3486 if (strcmp(named_fc
->name
->str
, field_name
) == 0) {
3487 ret
= auto_map_field_to_trace_clock_class(ctx
,
3490 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot automatically map field to trace's clock class: "
3491 "field-name=\"%s\"", field_name
);
3496 ret
= auto_map_fields_to_trace_clock_class(ctx
, named_fc
->fc
,
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
);
3511 int visit_stream_decl_entry(struct ctx
*ctx
, struct ctf_node
*node
,
3512 struct ctf_stream_class
*stream_class
, int *set
)
3517 switch (node
->type
) {
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
);
3522 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3523 "Cannot add field class found in stream class.");
3527 case NODE_TYPEALIAS
:
3528 ret
= visit_field_class_alias(ctx
, node
->u
.field_class_alias
.target
,
3529 node
->u
.field_class_alias
.alias
);
3531 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3532 "Cannot add field class alias found in stream class.");
3536 case NODE_CTF_EXPRESSION
:
3538 left
= ctf_ast_concatenate_unary_strings(&node
->u
.ctf_expression
.left
);
3540 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot concatenate unary strings.");
3545 if (strcmp(left
, "id") == 0) {
3548 if (_IS_SET(set
, _STREAM_ID_SET
)) {
3549 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "id",
3550 "stream declaration");
3555 ret
= get_unary_unsigned(ctx
,
3556 &node
->u
.ctf_expression
.right
,
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.");
3567 if (ctf_trace_class_borrow_stream_class_by_id(
3569 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3570 "Duplicate stream class (same ID): id=%" PRId64
,
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.");
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
);
3592 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3593 "Cannot create stream class's event header field class.");
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");
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.");
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.");
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
);
3621 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3622 "Cannot create stream class's event context field class.");
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.");
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
);
3642 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3643 "Cannot create stream class's packet context field class.");
3647 BT_ASSERT(stream_class
->packet_context_fc
);
3648 ret
= auto_map_fields_to_trace_clock_class(ctx
,
3649 stream_class
->packet_context_fc
,
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.");
3657 ret
= auto_map_fields_to_trace_clock_class(ctx
,
3658 stream_class
->packet_context_fc
,
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.");
3666 _SET(set
, _STREAM_PACKET_CONTEXT_SET
);
3668 _BT_COMP_LOGW_NODE(node
,
3669 "Unknown attribute in stream class: "
3670 "attr-name=\"%s\"", left
);
3691 int visit_stream_decl(struct ctx
*ctx
, struct ctf_node
*node
)
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
;
3699 if (node
->visited
) {
3703 node
->visited
= TRUE
;
3704 stream_class
= ctf_stream_class_create();
3705 BT_ASSERT(stream_class
);
3706 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
3708 bt_list_for_each_entry(iter
, decl_list
, siblings
) {
3709 ret
= visit_stream_decl_entry(ctx
, iter
, stream_class
, &set
);
3711 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
3712 "Cannot visit stream class's entry: "
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
;
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.");
3733 named_fc
= ctf_field_class_struct_borrow_member_by_name(
3734 (void *) ctx
->ctf_tc
->packet_header_fc
, "stream_id");
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.");
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.");
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.");
3760 /* Automatic ID: 0 */
3761 stream_class
->id
= 0;
3765 * Make sure that this stream class's ID is currently unique in
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
,
3777 g_ptr_array_add(ctx
->ctf_tc
->stream_classes
, stream_class
);
3778 stream_class
= NULL
;
3782 ctf_stream_class_destroy(stream_class
);
3783 stream_class
= NULL
;
3790 int visit_trace_decl_entry(struct ctx
*ctx
, struct ctf_node
*node
, int *set
)
3796 switch (node
->type
) {
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
);
3801 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3802 "Cannot add field class found in trace (`trace` block).");
3806 case NODE_TYPEALIAS
:
3807 ret
= visit_field_class_alias(ctx
, node
->u
.field_class_alias
.target
,
3808 node
->u
.field_class_alias
.alias
);
3810 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3811 "Cannot add field class alias found in trace (`trace` block).");
3815 case NODE_CTF_EXPRESSION
:
3817 left
= ctf_ast_concatenate_unary_strings(&node
->u
.ctf_expression
.left
);
3819 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Cannot concatenate unary strings.");
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");
3831 ret
= get_unary_unsigned(ctx
,
3832 &node
->u
.ctf_expression
.right
, &val
);
3834 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3835 "Unexpected unary expression for trace's `major` attribute.");
3841 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3842 "Invalid trace's `minor` attribute: expecting 1.");
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");
3856 ret
= get_unary_unsigned(ctx
,
3857 &node
->u
.ctf_expression
.right
, &val
);
3859 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3860 "Unexpected unary expression for trace's `minor` attribute.");
3866 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3867 "Invalid trace's `minor` attribute: expecting 8.");
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");
3881 ret
= get_unary_uuid(ctx
,
3882 &node
->u
.ctf_expression
.right
,
3885 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3886 "Invalid trace's `uuid` attribute.");
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",
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.");
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
);
3917 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3918 "Cannot create trace's packet header field class.");
3922 BT_ASSERT(ctx
->ctf_tc
->packet_header_fc
);
3923 _SET(set
, _TRACE_PACKET_HEADER_SET
);
3925 _BT_COMP_LOGW_NODE(node
,
3926 "Unknown attribute in stream class: "
3927 "attr-name=\"%s\"", left
);
3935 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Unknown expression in trace.");
3948 int visit_trace_decl(struct ctx
*ctx
, struct ctf_node
*node
)
3952 struct ctf_node
*iter
;
3953 struct bt_list_head
*decl_list
= &node
->u
.trace
.declaration_list
;
3955 if (node
->visited
) {
3959 node
->visited
= TRUE
;
3961 if (ctx
->is_trace_visited
) {
3962 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
, "Duplicate trace (`trace` block).");
3967 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
3969 bt_list_for_each_entry(iter
, decl_list
, siblings
) {
3970 ret
= visit_trace_decl_entry(ctx
, iter
, &set
);
3972 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
, "Cannot visit trace's entry (`trace` block): "
3981 if (!_IS_SET(&set
, _TRACE_MAJOR_SET
)) {
3982 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3983 "Missing `major` attribute in trace (`trace` block).");
3988 if (!_IS_SET(&set
, _TRACE_MINOR_SET
)) {
3989 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
3990 "Missing `minor` attribute in trace (`trace` block).");
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).");
4002 ctx
->is_trace_visited
= true;
4012 int visit_env(struct ctx
*ctx
, struct ctf_node
*node
)
4016 struct ctf_node
*entry_node
;
4017 struct bt_list_head
*decl_list
= &node
->u
.env
.declaration_list
;
4019 if (node
->visited
) {
4023 node
->visited
= TRUE
;
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
;
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
);
4037 left
= ctf_ast_concatenate_unary_strings(
4038 &entry_node
->u
.ctf_expression
.left
);
4040 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
4041 "Cannot get environment entry's name.");
4046 if (is_unary_string(right_head
)) {
4047 char *right
= ctf_ast_concatenate_unary_strings(right_head
);
4050 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
4051 "Unexpected unary expression for environment entry's value: "
4052 "name=\"%s\"", left
);
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\"",
4062 ctx
->is_lttng
= true;
4066 ctf_trace_class_append_env_entry(ctx
->ctf_tc
,
4067 left
, CTF_TRACE_CLASS_ENV_ENTRY_TYPE_STR
,
4070 } else if (is_unary_unsigned(right_head
) ||
4071 is_unary_signed(right_head
)) {
4074 if (is_unary_unsigned(right_head
)) {
4075 ret
= get_unary_unsigned(ctx
, right_head
,
4078 ret
= get_unary_signed(right_head
, &v
);
4081 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
4082 "Unexpected unary expression for environment entry's value: "
4083 "name=\"%s\"", left
);
4088 ctf_trace_class_append_env_entry(ctx
->ctf_tc
,
4089 left
, CTF_TRACE_CLASS_ENV_ENTRY_TYPE_INT
,
4092 _BT_COMP_LOGW_NODE(entry_node
,
4093 "Environment entry has unknown type: "
4094 "name=\"%s\"", left
);
4110 int set_trace_byte_order(struct ctx
*ctx
, struct ctf_node
*trace_node
)
4115 struct ctf_node
*node
;
4116 struct bt_list_head
*decl_list
= &trace_node
->u
.trace
.declaration_list
;
4118 bt_list_for_each_entry(node
, decl_list
, siblings
) {
4119 if (node
->type
== NODE_CTF_EXPRESSION
) {
4120 struct ctf_node
*right_node
;
4122 left
= ctf_ast_concatenate_unary_strings(
4123 &node
->u
.ctf_expression
.left
);
4125 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
4126 "Cannot concatenate unary strings.");
4131 if (strcmp(left
, "byte_order") == 0) {
4132 enum ctf_byte_order bo
;
4134 if (_IS_SET(&set
, _TRACE_BYTE_ORDER_SET
)) {
4135 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(node
, "byte_order",
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
,
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`.");
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.");
4161 ctx
->ctf_tc
->default_byte_order
= bo
;
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).");
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
)
4191 if (entry_node
->type
!= NODE_CTF_EXPRESSION
) {
4192 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
4193 "Unexpected node type: node-type=%d",
4199 left
= ctf_ast_concatenate_unary_strings(&entry_node
->u
.ctf_expression
.left
);
4201 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
, "Cannot concatenate unary strings.");
4206 if (strcmp(left
, "name") == 0) {
4209 if (_IS_SET(set
, _CLOCK_NAME_SET
)) {
4210 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "name", "clock class");
4215 right
= ctf_ast_concatenate_unary_strings(
4216 &entry_node
->u
.ctf_expression
.right
);
4218 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
4219 "Unexpected unary expression for clock class's `name` attribute.");
4224 g_string_assign(clock
->name
, right
);
4226 _SET(set
, _CLOCK_NAME_SET
);
4227 } else if (strcmp(left
, "uuid") == 0) {
4230 if (_IS_SET(set
, _CLOCK_UUID_SET
)) {
4231 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "uuid", "clock class");
4236 ret
= get_unary_uuid(ctx
, &entry_node
->u
.ctf_expression
.right
,
4239 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
4240 "Invalid clock class's `uuid` attribute.");
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) {
4250 if (_IS_SET(set
, _CLOCK_DESCRIPTION_SET
)) {
4251 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "description",
4257 right
= ctf_ast_concatenate_unary_strings(
4258 &entry_node
->u
.ctf_expression
.right
);
4260 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
4261 "Unexpected unary expression for clock class's `description` attribute.");
4266 g_string_assign(clock
->description
, right
);
4268 _SET(set
, _CLOCK_DESCRIPTION_SET
);
4269 } else if (strcmp(left
, "freq") == 0) {
4270 uint64_t freq
= UINT64_C(-1);
4272 if (_IS_SET(set
, _CLOCK_FREQ_SET
)) {
4273 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "freq", "clock class");
4278 ret
= get_unary_unsigned(ctx
,
4279 &entry_node
->u
.ctf_expression
.right
, &freq
);
4281 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
4282 "Unexpected unary expression for clock class's `freq` attribute.");
4287 if (freq
== UINT64_C(-1) || freq
== 0) {
4288 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
4289 "Invalid clock class frequency: freq=%" PRIu64
,
4295 clock
->frequency
= freq
;
4296 _SET(set
, _CLOCK_FREQ_SET
);
4297 } else if (strcmp(left
, "precision") == 0) {
4300 if (_IS_SET(set
, _CLOCK_PRECISION_SET
)) {
4301 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "precision",
4307 ret
= get_unary_unsigned(ctx
,
4308 &entry_node
->u
.ctf_expression
.right
, &precision
);
4310 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
4311 "Unexpected unary expression for clock class's `precision` attribute.");
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",
4326 ret
= get_unary_signed(
4327 &entry_node
->u
.ctf_expression
.right
, offset_seconds
);
4329 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
4330 "Unexpected unary expression for clock class's `offset_s` attribute.");
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");
4343 ret
= get_unary_unsigned(ctx
,
4344 &entry_node
->u
.ctf_expression
.right
, offset_cycles
);
4346 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
4347 "Unexpected unary expression for clock class's `offset` attribute.");
4352 _SET(set
, _CLOCK_OFFSET_SET
);
4353 } else if (strcmp(left
, "absolute") == 0) {
4354 struct ctf_node
*right
;
4356 if (_IS_SET(set
, _CLOCK_ABSOLUTE_SET
)) {
4357 _BT_COMP_LOGE_APPEND_CAUSE_DUP_ATTR(entry_node
, "absolute",
4363 right
= _BT_LIST_FIRST_ENTRY(
4364 &entry_node
->u
.ctf_expression
.right
,
4365 struct ctf_node
, siblings
);
4366 ret
= get_boolean(ctx
, right
);
4368 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
4369 "Unexpected unary expression for clock class's `absolute` attribute.");
4374 clock
->is_absolute
= ret
;
4375 _SET(set
, _CLOCK_ABSOLUTE_SET
);
4377 _BT_COMP_LOGW_NODE(entry_node
,
4378 "Unknown attribute in clock class: attr-name=\"%s\"",
4392 uint64_t cycles_from_ns(uint64_t frequency
, uint64_t ns
)
4397 if (frequency
== UINT64_C(1000000000)) {
4400 cycles
= (uint64_t) (((double) ns
* (double) frequency
) / 1e9
);
4407 void calibrate_clock_class_offsets(int64_t *offset_seconds
,
4408 uint64_t *offset_cycles
, uint64_t freq
)
4410 if (*offset_cycles
>= freq
) {
4411 const uint64_t s_in_offset_cycles
= *offset_cycles
/ freq
;
4413 *offset_seconds
+= (int64_t) s_in_offset_cycles
;
4414 *offset_cycles
-= (s_in_offset_cycles
* freq
);
4419 void apply_clock_class_is_absolute(struct ctx
*ctx
,
4420 struct ctf_clock_class
*clock
)
4422 if (ctx
->decoder_config
.force_clock_class_origin_unix_epoch
) {
4423 clock
->is_absolute
= true;
4430 void apply_clock_class_offset(struct ctx
*ctx
,
4431 struct ctf_clock_class
*clock
)
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
;
4439 if (ctx
->decoder_config
.clock_class_offset_s
== 0 &&
4440 ctx
->decoder_config
.clock_class_offset_ns
== 0) {
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));
4452 BT_ASSERT(offset_ns
> 0);
4453 offset_ns_to_apply
= (uint64_t) offset_ns
;
4454 offset_s_to_apply
+= extra_s
;
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));
4461 BT_ASSERT(offset_ns
>= 0);
4462 offset_ns_to_apply
= (uint64_t) offset_ns
;
4463 offset_s_to_apply
+= extra_s
;
4466 freq
= clock
->frequency
;
4467 cur_offset_s
= clock
->offset_seconds
;
4468 cur_offset_cycles
= clock
->offset_cycles
;
4471 cur_offset_s
+= offset_s_to_apply
;
4472 cur_offset_cycles
+= cycles_from_ns(freq
, offset_ns_to_apply
);
4475 * Recalibrate offsets because the part in cycles can be greater
4476 * than the frequency at this point.
4478 calibrate_clock_class_offsets(&cur_offset_s
, &cur_offset_cycles
, freq
);
4480 /* Set final offsets */
4481 clock
->offset_seconds
= cur_offset_s
;
4482 clock
->offset_cycles
= cur_offset_cycles
;
4489 int visit_clock_decl(struct ctx
*ctx
, struct ctf_node
*clock_node
)
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;
4501 if (clock_node
->visited
) {
4505 clock_node
->visited
= TRUE
;
4507 /* CTF 1.8's default frequency for a clock class is 1 GHz */
4508 clock
= ctf_clock_class_create();
4510 _BT_COMP_LOGE_APPEND_CAUSE_NODE(clock_node
,
4511 "Cannot create default clock class.");
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
);
4520 _BT_COMP_LOGE_APPEND_CAUSE_NODE(entry_node
,
4521 "Cannot visit clock class's entry: ret=%d",
4527 if (!_IS_SET(&set
, _CLOCK_NAME_SET
)) {
4528 _BT_COMP_LOGE_APPEND_CAUSE_NODE(clock_node
,
4529 "Missing `name` attribute in clock class.");
4534 clock_class_name
= clock
->name
->str
;
4535 BT_ASSERT(clock_class_name
);
4536 if (ctx
->is_lttng
&& strcmp(clock_class_name
, "monotonic") == 0) {
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.
4543 clock
->is_absolute
= true;
4547 * Adjust offsets so that the part in cycles is less than the
4548 * frequency (move to the part in seconds).
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
);
4562 ctf_clock_class_destroy(clock
);
4569 int visit_root_decl(struct ctx
*ctx
, struct ctf_node
*root_decl_node
)
4573 if (root_decl_node
->visited
) {
4577 root_decl_node
->visited
= TRUE
;
4579 switch (root_decl_node
->type
) {
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
);
4585 _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node
,
4586 "Cannot add field class found in root scope.");
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
);
4594 _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node
,
4595 "Cannot add field class alias found in root scope.");
4599 case NODE_TYPE_SPECIFIER_LIST
:
4601 struct ctf_field_class
*decl
= NULL
;
4604 * Just add the field class specifier to the root
4605 * declaration scope. Put local reference.
4607 ret
= visit_field_class_specifier_list(ctx
, root_decl_node
, &decl
);
4609 _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node
,
4610 "Cannot visit root scope's field class: "
4616 ctf_field_class_destroy(decl
);
4621 _BT_COMP_LOGE_APPEND_CAUSE_NODE(root_decl_node
,
4622 "Unexpected node type: node-type=%d",
4623 root_decl_node
->type
);
4633 struct ctf_visitor_generate_ir
*ctf_visitor_generate_ir_create(
4634 const struct ctf_metadata_decoder_config
*decoder_config
)
4636 struct ctx
*ctx
= NULL
;
4638 /* Create visitor's context */
4639 ctx
= ctx_create(decoder_config
);
4641 BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR
, decoder_config
->log_level
,
4642 decoder_config
->self_comp
,
4643 "Cannot create visitor's context.");
4654 return (void *) ctx
;
4658 void ctf_visitor_generate_ir_destroy(struct ctf_visitor_generate_ir
*visitor
)
4660 ctx_destroy((void *) visitor
);
4664 bt_trace_class
*ctf_visitor_generate_ir_get_ir_trace_class(
4665 struct ctf_visitor_generate_ir
*visitor
)
4667 struct ctx
*ctx
= (void *) visitor
;
4671 if (ctx
->trace_class
) {
4672 bt_trace_class_get_ref(ctx
->trace_class
);
4675 return ctx
->trace_class
;
4679 struct ctf_trace_class
*ctf_visitor_generate_ir_borrow_ctf_trace_class(
4680 struct ctf_visitor_generate_ir
*visitor
)
4682 struct ctx
*ctx
= (void *) visitor
;
4685 BT_ASSERT_DBG(ctx
->ctf_tc
);
4690 int ctf_visitor_generate_ir_visit_node(struct ctf_visitor_generate_ir
*visitor
,
4691 struct ctf_node
*node
)
4694 struct ctx
*ctx
= (void *) visitor
;
4696 BT_COMP_LOGI_STR("Visiting metadata's AST to generate CTF IR objects.");
4698 switch (node
->type
) {
4701 struct ctf_node
*iter
;
4702 bool got_trace_decl
= false;
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.
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).");
4720 ret
= set_trace_byte_order(ctx
, iter
);
4722 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
4723 "Cannot set trace's native byte order: "
4728 got_trace_decl
= true;
4731 if (!got_trace_decl
) {
4732 BT_COMP_LOGD_STR("Incomplete AST: need trace (`trace` block).");
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
);
4744 bt_list_for_each_entry(iter
, &node
->u
.root
.env
, siblings
) {
4745 ret
= visit_env(ctx
, iter
);
4747 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
4748 "Cannot visit trace's environment (`env` block) entry: "
4754 BT_ASSERT(ctx
->current_scope
&&
4755 !ctx
->current_scope
->parent_scope
);
4758 * Visit clock blocks.
4760 bt_list_for_each_entry(iter
, &node
->u
.root
.clock
, siblings
) {
4761 ret
= visit_clock_decl(ctx
, iter
);
4763 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
4764 "Cannot visit clock class: ret=%d",
4770 BT_ASSERT(ctx
->current_scope
&&
4771 !ctx
->current_scope
->parent_scope
);
4774 * Visit root declarations next, as they can be used by any
4777 bt_list_for_each_entry(iter
, &node
->u
.root
.declaration_list
,
4779 ret
= visit_root_decl(ctx
, iter
);
4781 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
4782 "Cannot visit root entry: ret=%d",
4788 BT_ASSERT(ctx
->current_scope
&&
4789 !ctx
->current_scope
->parent_scope
);
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.");
4797 BT_ASSERT(ctx
->current_scope
&&
4798 !ctx
->current_scope
->parent_scope
);
4801 bt_list_for_each_entry(iter
, &node
->u
.root
.trace
, siblings
) {
4802 ret
= visit_trace_decl(ctx
, iter
);
4804 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
4805 "Cannot visit trace (`trace` block): "
4811 BT_ASSERT(ctx
->current_scope
&&
4812 !ctx
->current_scope
->parent_scope
);
4815 bt_list_for_each_entry(iter
, &node
->u
.root
.stream
, siblings
) {
4816 ret
= visit_stream_decl(ctx
, iter
);
4818 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
4819 "Cannot visit stream class: ret=%d",
4825 BT_ASSERT(ctx
->current_scope
&&
4826 !ctx
->current_scope
->parent_scope
);
4829 bt_list_for_each_entry(iter
, &node
->u
.root
.event
, siblings
) {
4830 ret
= visit_event_decl(ctx
, iter
);
4832 _BT_COMP_LOGE_APPEND_CAUSE_NODE(iter
,
4833 "Cannot visit event class: ret=%d",
4839 BT_ASSERT(ctx
->current_scope
&&
4840 !ctx
->current_scope
->parent_scope
);
4844 _BT_COMP_LOGE_APPEND_CAUSE_NODE(node
,
4845 "Unexpected node type: node-type=%d",
4851 /* Update default clock classes */
4852 ret
= ctf_trace_class_update_default_clock_classes(ctx
->ctf_tc
,
4859 /* Update trace class meanings */
4860 ret
= ctf_trace_class_update_meanings(ctx
->ctf_tc
);
4866 /* Update stream class configuration */
4867 ret
= ctf_trace_class_update_stream_class_config(ctx
->ctf_tc
);
4873 /* Update text arrays and sequences */
4874 ret
= ctf_trace_class_update_text_array_sequence(ctx
->ctf_tc
);
4880 /* Update structure/array/sequence alignments */
4881 ret
= ctf_trace_class_update_alignments(ctx
->ctf_tc
);
4887 /* Resolve sequence lengths and variant tags */
4888 ret
= ctf_trace_class_resolve_field_classes(ctx
->ctf_tc
, &ctx
->log_cfg
);
4894 if (ctx
->trace_class
) {
4896 * Update "in IR" for field classes.
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.
4902 ret
= ctf_trace_class_update_in_ir(ctx
->ctf_tc
);
4909 /* Update saved value indexes */
4910 ret
= ctf_trace_class_update_value_storing_indexes(ctx
->ctf_tc
);
4916 /* Validate what we have so far */
4917 ret
= ctf_trace_class_validate(ctx
->ctf_tc
, &ctx
->log_cfg
);
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.
4928 ctf_trace_class_warn_meaningless_header_fields(ctx
->ctf_tc
,
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
);