2 * ctf-visitor-generate-ir.c
4 * Common Trace Format metadata visitor (generates CTF IR objects).
6 * Based on older ctf-visitor-generate-io-struct.c.
8 * Copyright 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
9 * Copyright 2015-2018 - Philippe Proulx <philippe.proulx@efficios.com>
11 * Permission is hereby granted, free of charge, to any person obtaining a copy
12 * of this software and associated documentation files (the "Software"), to deal
13 * in the Software without restriction, including without limitation the rights
14 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 * copies of the Software, and to permit persons to whom the Software is
16 * furnished to do so, subject to the following conditions:
18 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 #define BT_COMP_LOG_SELF_COMP (ctx->log_cfg.self_comp)
31 #define BT_LOG_OUTPUT_LEVEL (ctx->log_cfg.log_level)
32 #define BT_LOG_TAG "PLUGIN/CTF/META/IR-VISITOR"
33 #include "plugins/comp-logging.h"
41 #include "common/assert.h"
45 #include "common/common.h"
46 #include "common/uuid.h"
47 #include "compat/endian.h"
48 #include <babeltrace2/babeltrace.h>
56 #include "ctf-meta-visitors.h"
58 /* Bit value (left shift) */
59 #define _BV(_val) (1 << (_val))
61 /* Bit is set in a set of bits */
62 #define _IS_SET(_set, _mask) (*(_set) & (_mask))
64 /* Set bit in a set of bits */
65 #define _SET(_set, _mask) (*(_set) |= (_mask))
67 /* Try to push scope, or go to the `error` label */
68 #define _TRY_PUSH_SCOPE_OR_GOTO_ERROR() \
70 ret = ctx_push_scope(ctx); \
72 BT_COMP_LOGE_STR("Cannot push scope."); \
77 /* Bits for verifying existing attributes in various declarations */
79 _CLOCK_NAME_SET
= _BV(0),
80 _CLOCK_UUID_SET
= _BV(1),
81 _CLOCK_FREQ_SET
= _BV(2),
82 _CLOCK_PRECISION_SET
= _BV(3),
83 _CLOCK_OFFSET_S_SET
= _BV(4),
84 _CLOCK_OFFSET_SET
= _BV(5),
85 _CLOCK_ABSOLUTE_SET
= _BV(6),
86 _CLOCK_DESCRIPTION_SET
= _BV(7),
90 _INTEGER_ALIGN_SET
= _BV(0),
91 _INTEGER_SIZE_SET
= _BV(1),
92 _INTEGER_BASE_SET
= _BV(2),
93 _INTEGER_ENCODING_SET
= _BV(3),
94 _INTEGER_BYTE_ORDER_SET
= _BV(4),
95 _INTEGER_SIGNED_SET
= _BV(5),
96 _INTEGER_MAP_SET
= _BV(6),
100 _FLOAT_ALIGN_SET
= _BV(0),
101 _FLOAT_MANT_DIG_SET
= _BV(1),
102 _FLOAT_EXP_DIG_SET
= _BV(2),
103 _FLOAT_BYTE_ORDER_SET
= _BV(3),
107 _STRING_ENCODING_SET
= _BV(0),
111 _TRACE_MINOR_SET
= _BV(0),
112 _TRACE_MAJOR_SET
= _BV(1),
113 _TRACE_BYTE_ORDER_SET
= _BV(2),
114 _TRACE_UUID_SET
= _BV(3),
115 _TRACE_PACKET_HEADER_SET
= _BV(4),
119 _STREAM_ID_SET
= _BV(0),
120 _STREAM_PACKET_CONTEXT_SET
= _BV(1),
121 _STREAM_EVENT_HEADER_SET
= _BV(2),
122 _STREAM_EVENT_CONTEXT_SET
= _BV(3),
126 _EVENT_NAME_SET
= _BV(0),
127 _EVENT_ID_SET
= _BV(1),
128 _EVENT_MODEL_EMF_URI_SET
= _BV(2),
129 _EVENT_STREAM_ID_SET
= _BV(3),
130 _EVENT_LOG_LEVEL_SET
= _BV(4),
131 _EVENT_CONTEXT_SET
= _BV(5),
132 _EVENT_FIELDS_SET
= _BV(6),
140 LOG_LEVEL_WARNING
= 4,
141 LOG_LEVEL_NOTICE
= 5,
143 LOG_LEVEL_DEBUG_SYSTEM
= 7,
144 LOG_LEVEL_DEBUG_PROGRAM
= 8,
145 LOG_LEVEL_DEBUG_PROCESS
= 9,
146 LOG_LEVEL_DEBUG_MODULE
= 10,
147 LOG_LEVEL_DEBUG_UNIT
= 11,
148 LOG_LEVEL_DEBUG_FUNCTION
= 12,
149 LOG_LEVEL_DEBUG_LINE
= 13,
150 LOG_LEVEL_DEBUG
= 14,
154 /* Prefixes of class aliases */
155 #define _PREFIX_ALIAS 'a'
156 #define _PREFIX_ENUM 'e'
157 #define _PREFIX_STRUCT 's'
158 #define _PREFIX_VARIANT 'v'
160 /* First entry in a BT list */
161 #define _BT_LIST_FIRST_ENTRY(_ptr, _class, _member) \
162 bt_list_entry((_ptr)->next, _class, _member)
164 #define _BT_COMP_LOGE_DUP_ATTR(_node, _attr, _entity) \
165 _BT_COMP_LOGE_LINENO((_node)->lineno, \
166 "Duplicate attribute in %s: attr-name=\"%s\"", \
169 #define _BT_COMP_LOGE_NODE(_node, _msg, args...) \
170 _BT_COMP_LOGE_LINENO((_node)->lineno, _msg, ## args)
172 #define _BT_COMP_LOGW_NODE(_node, _msg, args...) \
173 _BT_COMP_LOGW_LINENO((_node)->lineno, _msg, ## args)
175 #define _BT_COMP_LOGT_NODE(_node, _msg, args...) \
176 _BT_COMP_LOGT_LINENO((_node)->lineno, _msg, ## args)
179 * Declaration scope of a visitor context. This represents a TSDL
180 * lexical scope, so that aliases and named structures, variants,
181 * and enumerations may be registered and looked up hierarchically.
183 struct ctx_decl_scope
{
185 * Alias name to field class.
187 * GQuark -> struct ctf_field_class * (owned by this)
189 GHashTable
*decl_map
;
191 /* Parent scope; NULL if this is the root declaration scope */
192 struct ctx_decl_scope
*parent_scope
;
196 * Visitor context (private).
199 struct meta_log_config log_cfg
;
201 /* Trace IR trace class being filled (owned by this) */
202 bt_trace_class
*trace_class
;
204 /* CTF meta trace being filled (owned by this) */
205 struct ctf_trace_class
*ctf_tc
;
207 /* Current declaration scope (top of the stack) (owned by this) */
208 struct ctx_decl_scope
*current_scope
;
210 /* True if trace declaration is visited */
211 bool is_trace_visited
;
213 /* True if this is an LTTng trace */
216 /* Config passed by the user */
217 struct ctf_metadata_decoder_config decoder_config
;
223 struct ctf_visitor_generate_ir
;
226 * Creates a new declaration scope.
228 * @param par_scope Parent scope (NULL if creating a root scope)
229 * @returns New declaration scope, or NULL on error
232 struct ctx_decl_scope
*ctx_decl_scope_create(struct ctx
*ctx
,
233 struct ctx_decl_scope
*par_scope
)
235 struct ctx_decl_scope
*scope
;
237 scope
= g_new(struct ctx_decl_scope
, 1);
239 BT_COMP_LOGE_STR("Failed to allocate one declaration scope.");
243 scope
->decl_map
= g_hash_table_new_full(g_direct_hash
, g_direct_equal
,
244 NULL
, (GDestroyNotify
) ctf_field_class_destroy
);
245 scope
->parent_scope
= par_scope
;
252 * Destroys a declaration scope.
254 * This function does not destroy the parent scope.
256 * @param scope Scope to destroy
259 void ctx_decl_scope_destroy(struct ctx_decl_scope
*scope
)
265 g_hash_table_destroy(scope
->decl_map
);
273 * Returns the GQuark of a prefixed alias.
275 * @param prefix Prefix character
277 * @returns Associated GQuark, or 0 on error
280 GQuark
get_prefixed_named_quark(struct ctx
*ctx
, char prefix
, const char *name
)
286 /* Prefix character + original string + '\0' */
287 char *prname
= g_new(char, strlen(name
) + 2);
289 BT_COMP_LOGE_STR("Failed to allocate a string.");
293 sprintf(prname
, "%c%s", prefix
, name
);
294 qname
= g_quark_from_string(prname
);
302 * Looks up a prefixed class alias within a declaration scope.
304 * @param scope Declaration scope
305 * @param prefix Prefix character
306 * @param name Alias name
307 * @param levels Number of levels to dig into (-1 means infinite)
308 * @param copy True to return a copy
309 * @returns Declaration (owned by caller if \p copy is true),
310 * or NULL if not found
313 struct ctf_field_class
*ctx_decl_scope_lookup_prefix_alias(
314 struct ctx
*ctx
, struct ctx_decl_scope
*scope
, char prefix
,
315 const char *name
, int levels
, bool copy
)
319 struct ctf_field_class
*decl
= NULL
;
320 struct ctx_decl_scope
*cur_scope
= scope
;
324 qname
= get_prefixed_named_quark(ctx
, prefix
, name
);
333 while (cur_scope
&& cur_levels
< levels
) {
334 decl
= g_hash_table_lookup(cur_scope
->decl_map
,
335 (gconstpointer
) GUINT_TO_POINTER(qname
));
337 /* Caller's reference */
339 decl
= ctf_field_class_copy(decl
);
346 cur_scope
= cur_scope
->parent_scope
;
355 * Looks up a class alias within a declaration scope.
357 * @param scope Declaration scope
358 * @param name Alias name
359 * @param levels Number of levels to dig into (-1 means infinite)
360 * @param copy True to return a copy
361 * @returns Declaration (owned by caller if \p copy is true),
362 * or NULL if not found
365 struct ctf_field_class
*ctx_decl_scope_lookup_alias(struct ctx
*ctx
,
366 struct ctx_decl_scope
*scope
, const char *name
, int levels
,
369 return ctx_decl_scope_lookup_prefix_alias(ctx
, scope
, _PREFIX_ALIAS
,
374 * Looks up an enumeration within a declaration scope.
376 * @param scope Declaration scope
377 * @param name Enumeration name
378 * @param levels Number of levels to dig into (-1 means infinite)
379 * @param copy True to return a copy
380 * @returns Declaration (owned by caller if \p copy is true),
381 * or NULL if not found
384 struct ctf_field_class_enum
*ctx_decl_scope_lookup_enum(struct ctx
*ctx
,
385 struct ctx_decl_scope
*scope
, const char *name
, int levels
,
388 return (void *) ctx_decl_scope_lookup_prefix_alias(ctx
, scope
,
389 _PREFIX_ENUM
, name
, levels
, copy
);
393 * Looks up a structure within a declaration scope.
395 * @param scope Declaration scope
396 * @param name Structure name
397 * @param levels Number of levels to dig into (-1 means infinite)
398 * @param copy True to return a copy
399 * @returns Declaration (owned by caller if \p copy is true),
400 * or NULL if not found
403 struct ctf_field_class_struct
*ctx_decl_scope_lookup_struct(struct ctx
*ctx
,
404 struct ctx_decl_scope
*scope
, const char *name
, int levels
,
407 return (void *) ctx_decl_scope_lookup_prefix_alias(ctx
, scope
,
408 _PREFIX_STRUCT
, name
, levels
, copy
);
412 * Looks up a variant within a declaration scope.
414 * @param scope Declaration scope
415 * @param name Variant name
416 * @param levels Number of levels to dig into (-1 means infinite)
417 * @param copy True to return a copy
418 * @returns Declaration (owned by caller if \p copy is true),
419 * or NULL if not found
422 struct ctf_field_class_variant
*ctx_decl_scope_lookup_variant(struct ctx
*ctx
,
423 struct ctx_decl_scope
*scope
, const char *name
, int levels
,
426 return (void *) ctx_decl_scope_lookup_prefix_alias(ctx
, scope
,
427 _PREFIX_VARIANT
, name
, levels
, copy
);
431 * Registers a prefixed class alias within a declaration scope.
433 * @param scope Declaration scope
434 * @param prefix Prefix character
435 * @param name Alias name (non-NULL)
436 * @param decl Field class to register (copied)
437 * @returns 0 if registration went okay, negative value otherwise
440 int ctx_decl_scope_register_prefix_alias(struct ctx
*ctx
,
441 struct ctx_decl_scope
*scope
, char prefix
, const char *name
,
442 struct ctf_field_class
*decl
)
450 qname
= get_prefixed_named_quark(ctx
, prefix
, name
);
456 /* Make sure alias does not exist in local scope */
457 if (ctx_decl_scope_lookup_prefix_alias(ctx
, scope
, prefix
, name
, 1,
463 decl
= ctf_field_class_copy(decl
);
465 g_hash_table_insert(scope
->decl_map
, GUINT_TO_POINTER(qname
), decl
);
472 * Registers a class alias within a declaration scope.
474 * @param scope Declaration scope
475 * @param name Alias name (non-NULL)
476 * @param decl Field class to register (copied)
477 * @returns 0 if registration went okay, negative value otherwise
480 int ctx_decl_scope_register_alias(struct ctx
*ctx
, struct ctx_decl_scope
*scope
,
481 const char *name
, struct ctf_field_class
*decl
)
483 return ctx_decl_scope_register_prefix_alias(ctx
, scope
, _PREFIX_ALIAS
,
484 name
, (void *) decl
);
488 * Registers an enumeration declaration within a declaration scope.
490 * @param scope Declaration scope
491 * @param name Enumeration name (non-NULL)
492 * @param decl Enumeration field class to register (copied)
493 * @returns 0 if registration went okay, negative value otherwise
496 int ctx_decl_scope_register_enum(struct ctx
*ctx
, struct ctx_decl_scope
*scope
,
497 const char *name
, struct ctf_field_class_enum
*decl
)
499 return ctx_decl_scope_register_prefix_alias(ctx
, scope
, _PREFIX_ENUM
,
500 name
, (void *) decl
);
504 * Registers a structure declaration within a declaration scope.
506 * @param scope Declaration scope
507 * @param name Structure name (non-NULL)
508 * @param decl Structure field class to register (copied)
509 * @returns 0 if registration went okay, negative value otherwise
512 int ctx_decl_scope_register_struct(struct ctx
*ctx
,
513 struct ctx_decl_scope
*scope
, const char *name
,
514 struct ctf_field_class_struct
*decl
)
516 return ctx_decl_scope_register_prefix_alias(ctx
, scope
, _PREFIX_STRUCT
,
517 name
, (void *) decl
);
521 * Registers a variant declaration within a declaration scope.
523 * @param scope Declaration scope
524 * @param name Variant name (non-NULL)
525 * @param decl Variant field class to register
526 * @returns 0 if registration went okay, negative value otherwise
529 int ctx_decl_scope_register_variant(struct ctx
*ctx
,
530 struct ctx_decl_scope
*scope
, const char *name
,
531 struct ctf_field_class_variant
*decl
)
533 return ctx_decl_scope_register_prefix_alias(ctx
, scope
, _PREFIX_VARIANT
,
534 name
, (void *) decl
);
538 * Destroys a visitor context.
540 * @param ctx Visitor context to destroy
543 void ctx_destroy(struct ctx
*ctx
)
545 struct ctx_decl_scope
*scope
;
551 scope
= ctx
->current_scope
;
554 * Destroy all scopes, from current one to the root scope.
557 struct ctx_decl_scope
*parent_scope
= scope
->parent_scope
;
559 ctx_decl_scope_destroy(scope
);
560 scope
= parent_scope
;
563 bt_trace_class_put_ref(ctx
->trace_class
);
566 ctf_trace_class_destroy(ctx
->ctf_tc
);
576 * Creates a new visitor context.
578 * @param trace Associated trace
579 * @returns New visitor context, or NULL on error
582 struct ctx
*ctx_create(const struct ctf_metadata_decoder_config
*decoder_config
)
584 struct ctx
*ctx
= NULL
;
586 BT_ASSERT(decoder_config
);
588 ctx
= g_new0(struct ctx
, 1);
590 BT_COMP_LOG_CUR_LVL(BT_LOG_ERROR
, decoder_config
->log_level
,
591 decoder_config
->self_comp
,
592 "Failed to allocate one visitor context.");
596 ctx
->log_cfg
.log_level
= decoder_config
->log_level
;
597 ctx
->log_cfg
.self_comp
= decoder_config
->self_comp
;
599 if (decoder_config
->self_comp
) {
600 ctx
->trace_class
= bt_trace_class_create(
601 decoder_config
->self_comp
);
602 if (!ctx
->trace_class
) {
603 BT_COMP_LOGE_STR("Cannot create empty trace class.");
608 ctx
->ctf_tc
= ctf_trace_class_create();
610 BT_COMP_LOGE_STR("Cannot create CTF trace class.");
614 /* Root declaration scope */
615 ctx
->current_scope
= ctx_decl_scope_create(ctx
, NULL
);
616 if (!ctx
->current_scope
) {
617 BT_COMP_LOGE_STR("Cannot create declaration scope.");
621 ctx
->decoder_config
= *decoder_config
;
633 * Pushes a new declaration scope on top of a visitor context's
634 * declaration scope stack.
636 * @param ctx Visitor context
637 * @returns 0 on success, or a negative value on error
640 int ctx_push_scope(struct ctx
*ctx
)
643 struct ctx_decl_scope
*new_scope
;
646 new_scope
= ctx_decl_scope_create(ctx
, ctx
->current_scope
);
648 BT_COMP_LOGE_STR("Cannot create declaration scope.");
653 ctx
->current_scope
= new_scope
;
660 void ctx_pop_scope(struct ctx
*ctx
)
662 struct ctx_decl_scope
*parent_scope
= NULL
;
666 if (!ctx
->current_scope
) {
670 parent_scope
= ctx
->current_scope
->parent_scope
;
671 ctx_decl_scope_destroy(ctx
->current_scope
);
672 ctx
->current_scope
= parent_scope
;
679 int visit_field_class_specifier_list(struct ctx
*ctx
, struct ctf_node
*ts_list
,
680 struct ctf_field_class
**decl
);
683 char *remove_underscores_from_field_ref(struct ctx
*ctx
, const char *field_ref
)
689 UNDERSCORE_REMOVE_STATE_REMOVE_NEXT_UNDERSCORE
,
690 UNDERSCORE_REMOVE_STATE_DO_NOT_REMOVE_NEXT_UNDERSCORE
,
691 } state
= UNDERSCORE_REMOVE_STATE_REMOVE_NEXT_UNDERSCORE
;
693 BT_ASSERT(field_ref
);
694 ret
= calloc(strlen(field_ref
) + 1, 1);
696 BT_COMP_LOGE("Failed to allocate a string: size=%zu",
697 strlen(field_ref
) + 1);
704 while (*in_ch
!= '\0') {
708 /* Remove whitespace */
712 if (state
== UNDERSCORE_REMOVE_STATE_REMOVE_NEXT_UNDERSCORE
) {
714 state
= UNDERSCORE_REMOVE_STATE_DO_NOT_REMOVE_NEXT_UNDERSCORE
;
720 state
= UNDERSCORE_REMOVE_STATE_REMOVE_NEXT_UNDERSCORE
;
723 state
= UNDERSCORE_REMOVE_STATE_DO_NOT_REMOVE_NEXT_UNDERSCORE
;
738 int is_unary_string(struct bt_list_head
*head
)
741 struct ctf_node
*node
;
743 bt_list_for_each_entry(node
, head
, siblings
) {
744 if (node
->type
!= NODE_UNARY_EXPRESSION
) {
748 if (node
->u
.unary_expression
.type
!= UNARY_STRING
) {
757 char *concatenate_unary_strings(struct bt_list_head
*head
)
761 struct ctf_node
*node
;
763 str
= g_string_new(NULL
);
766 bt_list_for_each_entry(node
, head
, siblings
) {
770 node
->type
!= NODE_UNARY_EXPRESSION
||
771 node
->u
.unary_expression
.type
!= UNARY_STRING
||
774 node
->u
.unary_expression
.link
!=
782 switch (node
->u
.unary_expression
.link
) {
784 g_string_append(str
, ".");
786 case UNARY_ARROWLINK
:
787 g_string_append(str
, "->");
789 case UNARY_DOTDOTDOT
:
790 g_string_append(str
, "...");
796 src_string
= node
->u
.unary_expression
.u
.string
;
797 g_string_append(str
, src_string
);
801 /* Destroys the container, returns the underlying string */
802 return g_string_free(str
, FALSE
);
805 /* This always returns NULL */
806 return g_string_free(str
, TRUE
);
810 const char *get_map_clock_name_value(struct bt_list_head
*head
)
813 struct ctf_node
*node
;
814 const char *name
= NULL
;
816 bt_list_for_each_entry(node
, head
, siblings
) {
818 int uexpr_type
= node
->u
.unary_expression
.type
;
819 int uexpr_link
= node
->u
.unary_expression
.link
;
820 int cond
= node
->type
!= NODE_UNARY_EXPRESSION
||
821 uexpr_type
!= UNARY_STRING
||
822 !((uexpr_link
!= UNARY_LINK_UNKNOWN
) ^ (i
== 0));
827 /* Needs to be chained with . */
828 switch (node
->u
.unary_expression
.link
) {
831 case UNARY_ARROWLINK
:
832 case UNARY_DOTDOTDOT
:
838 src_string
= node
->u
.unary_expression
.u
.string
;
842 if (strcmp("clock", src_string
)) {
850 if (strcmp("value", src_string
)) {
855 /* Extra identifier, unknown */
869 int is_unary_unsigned(struct bt_list_head
*head
)
872 struct ctf_node
*node
;
874 bt_list_for_each_entry(node
, head
, siblings
) {
875 if (node
->type
!= NODE_UNARY_EXPRESSION
) {
879 if (node
->u
.unary_expression
.type
!= UNARY_UNSIGNED_CONSTANT
) {
888 int get_unary_unsigned(struct ctx
*ctx
, struct bt_list_head
*head
,
893 struct ctf_node
*node
;
897 if (bt_list_empty(head
)) {
902 bt_list_for_each_entry(node
, head
, siblings
) {
903 int uexpr_type
= node
->u
.unary_expression
.type
;
904 int uexpr_link
= node
->u
.unary_expression
.link
;
905 int cond
= node
->type
!= NODE_UNARY_EXPRESSION
||
906 uexpr_type
!= UNARY_UNSIGNED_CONSTANT
||
907 uexpr_link
!= UNARY_LINK_UNKNOWN
|| i
!= 0;
909 _BT_COMP_LOGE_NODE(node
, "Invalid constant unsigned integer.");
914 *value
= node
->u
.unary_expression
.u
.unsigned_constant
;
923 int is_unary_signed(struct bt_list_head
*head
)
926 struct ctf_node
*node
;
928 bt_list_for_each_entry(node
, head
, siblings
) {
929 if (node
->type
!= NODE_UNARY_EXPRESSION
) {
933 if (node
->u
.unary_expression
.type
!= UNARY_SIGNED_CONSTANT
) {
942 int get_unary_signed(struct bt_list_head
*head
, int64_t *value
)
946 struct ctf_node
*node
;
948 bt_list_for_each_entry(node
, head
, siblings
) {
949 int uexpr_type
= node
->u
.unary_expression
.type
;
950 int uexpr_link
= node
->u
.unary_expression
.link
;
951 int cond
= node
->type
!= NODE_UNARY_EXPRESSION
||
952 (uexpr_type
!= UNARY_UNSIGNED_CONSTANT
&&
953 uexpr_type
!= UNARY_SIGNED_CONSTANT
) ||
954 uexpr_link
!= UNARY_LINK_UNKNOWN
|| i
!= 0;
960 switch (uexpr_type
) {
961 case UNARY_UNSIGNED_CONSTANT
:
963 node
->u
.unary_expression
.u
.unsigned_constant
;
965 case UNARY_SIGNED_CONSTANT
:
966 *value
= node
->u
.unary_expression
.u
.signed_constant
;
981 int get_unary_uuid(struct ctx
*ctx
, struct bt_list_head
*head
,
986 struct ctf_node
*node
;
988 bt_list_for_each_entry(node
, head
, siblings
) {
989 int uexpr_type
= node
->u
.unary_expression
.type
;
990 int uexpr_link
= node
->u
.unary_expression
.link
;
991 const char *src_string
;
993 if (node
->type
!= NODE_UNARY_EXPRESSION
||
994 uexpr_type
!= UNARY_STRING
||
995 uexpr_link
!= UNARY_LINK_UNKNOWN
||
1001 src_string
= node
->u
.unary_expression
.u
.string
;
1002 ret
= bt_uuid_from_str(src_string
, uuid
);
1004 _BT_COMP_LOGE_NODE(node
,
1005 "Cannot parse UUID: uuid=\"%s\"", src_string
);
1015 int get_boolean(struct ctx
*ctx
, struct ctf_node
*unary_expr
)
1019 if (unary_expr
->type
!= NODE_UNARY_EXPRESSION
) {
1020 _BT_COMP_LOGE_NODE(unary_expr
,
1021 "Expecting unary expression: node-type=%d",
1027 switch (unary_expr
->u
.unary_expression
.type
) {
1028 case UNARY_UNSIGNED_CONSTANT
:
1029 ret
= (unary_expr
->u
.unary_expression
.u
.unsigned_constant
!= 0);
1031 case UNARY_SIGNED_CONSTANT
:
1032 ret
= (unary_expr
->u
.unary_expression
.u
.signed_constant
!= 0);
1036 const char *str
= unary_expr
->u
.unary_expression
.u
.string
;
1038 if (strcmp(str
, "true") == 0 || strcmp(str
, "TRUE") == 0) {
1040 } else if (strcmp(str
, "false") == 0 || strcmp(str
, "FALSE") == 0) {
1043 _BT_COMP_LOGE_NODE(unary_expr
,
1044 "Unexpected boolean value: value=\"%s\"", str
);
1051 _BT_COMP_LOGE_NODE(unary_expr
,
1052 "Unexpected unary expression type: node-type=%d",
1053 unary_expr
->u
.unary_expression
.type
);
1063 enum ctf_byte_order
byte_order_from_unary_expr(struct ctx
*ctx
,
1064 struct ctf_node
*unary_expr
)
1067 enum ctf_byte_order bo
= -1;
1069 if (unary_expr
->u
.unary_expression
.type
!= UNARY_STRING
) {
1070 _BT_COMP_LOGE_NODE(unary_expr
,
1071 "\"byte_order\" attribute: expecting `be`, `le`, `network`, or `native`.");
1075 str
= unary_expr
->u
.unary_expression
.u
.string
;
1077 if (strcmp(str
, "be") == 0 || strcmp(str
, "network") == 0) {
1078 bo
= CTF_BYTE_ORDER_BIG
;
1079 } else if (strcmp(str
, "le") == 0) {
1080 bo
= CTF_BYTE_ORDER_LITTLE
;
1081 } else if (strcmp(str
, "native") == 0) {
1082 bo
= CTF_BYTE_ORDER_DEFAULT
;
1084 _BT_COMP_LOGE_NODE(unary_expr
,
1085 "Unexpected \"byte_order\" attribute value: "
1086 "expecting `be`, `le`, `network`, or `native`: value=\"%s\"",
1096 enum ctf_byte_order
get_real_byte_order(struct ctx
*ctx
,
1097 struct ctf_node
*uexpr
)
1099 enum ctf_byte_order bo
= byte_order_from_unary_expr(ctx
, uexpr
);
1101 if (bo
== CTF_BYTE_ORDER_DEFAULT
) {
1102 bo
= ctx
->ctf_tc
->default_byte_order
;
1109 int is_align_valid(uint64_t align
)
1111 return (align
!= 0) && !(align
& (align
- UINT64_C(1)));
1115 int get_class_specifier_name(struct ctx
*ctx
, struct ctf_node
*cls_specifier
,
1120 if (cls_specifier
->type
!= NODE_TYPE_SPECIFIER
) {
1121 _BT_COMP_LOGE_NODE(cls_specifier
,
1122 "Unexpected node type: node-type=%d",
1123 cls_specifier
->type
);
1128 switch (cls_specifier
->u
.field_class_specifier
.type
) {
1130 g_string_append(str
, "void");
1133 g_string_append(str
, "char");
1135 case TYPESPEC_SHORT
:
1136 g_string_append(str
, "short");
1139 g_string_append(str
, "int");
1142 g_string_append(str
, "long");
1144 case TYPESPEC_FLOAT
:
1145 g_string_append(str
, "float");
1147 case TYPESPEC_DOUBLE
:
1148 g_string_append(str
, "double");
1150 case TYPESPEC_SIGNED
:
1151 g_string_append(str
, "signed");
1153 case TYPESPEC_UNSIGNED
:
1154 g_string_append(str
, "unsigned");
1157 g_string_append(str
, "bool");
1159 case TYPESPEC_COMPLEX
:
1160 g_string_append(str
, "_Complex");
1162 case TYPESPEC_IMAGINARY
:
1163 g_string_append(str
, "_Imaginary");
1165 case TYPESPEC_CONST
:
1166 g_string_append(str
, "const");
1168 case TYPESPEC_ID_TYPE
:
1169 if (cls_specifier
->u
.field_class_specifier
.id_type
) {
1170 g_string_append(str
,
1171 cls_specifier
->u
.field_class_specifier
.id_type
);
1174 case TYPESPEC_STRUCT
:
1176 struct ctf_node
*node
= cls_specifier
->u
.field_class_specifier
.node
;
1178 if (!node
->u
._struct
.name
) {
1179 _BT_COMP_LOGE_NODE(node
, "Unexpected empty structure field class name.");
1184 g_string_append(str
, "struct ");
1185 g_string_append(str
, node
->u
._struct
.name
);
1188 case TYPESPEC_VARIANT
:
1190 struct ctf_node
*node
= cls_specifier
->u
.field_class_specifier
.node
;
1192 if (!node
->u
.variant
.name
) {
1193 _BT_COMP_LOGE_NODE(node
, "Unexpected empty variant field class name.");
1198 g_string_append(str
, "variant ");
1199 g_string_append(str
, node
->u
.variant
.name
);
1204 struct ctf_node
*node
= cls_specifier
->u
.field_class_specifier
.node
;
1206 if (!node
->u
._enum
.enum_id
) {
1207 _BT_COMP_LOGE_NODE(node
,
1208 "Unexpected empty enumeration field class (`enum`) name.");
1213 g_string_append(str
, "enum ");
1214 g_string_append(str
, node
->u
._enum
.enum_id
);
1217 case TYPESPEC_FLOATING_POINT
:
1218 case TYPESPEC_INTEGER
:
1219 case TYPESPEC_STRING
:
1221 _BT_COMP_LOGE_NODE(cls_specifier
->u
.field_class_specifier
.node
,
1222 "Unexpected field class specifier type: %d",
1223 cls_specifier
->u
.field_class_specifier
.type
);
1233 int get_class_specifier_list_name(struct ctx
*ctx
,
1234 struct ctf_node
*cls_specifier_list
, GString
*str
)
1237 struct ctf_node
*iter
;
1238 int alias_item_nr
= 0;
1239 struct bt_list_head
*head
=
1240 &cls_specifier_list
->u
.field_class_specifier_list
.head
;
1242 bt_list_for_each_entry(iter
, head
, siblings
) {
1243 if (alias_item_nr
!= 0) {
1244 g_string_append(str
, " ");
1248 ret
= get_class_specifier_name(ctx
, iter
, str
);
1259 GQuark
create_class_alias_identifier(struct ctx
*ctx
,
1260 struct ctf_node
*cls_specifier_list
,
1261 struct ctf_node
*node_field_class_declarator
)
1267 struct ctf_node
*iter
;
1268 struct bt_list_head
*pointers
=
1269 &node_field_class_declarator
->u
.field_class_declarator
.pointers
;
1271 str
= g_string_new("");
1272 ret
= get_class_specifier_list_name(ctx
, cls_specifier_list
, str
);
1274 g_string_free(str
, TRUE
);
1278 bt_list_for_each_entry(iter
, pointers
, siblings
) {
1279 g_string_append(str
, " *");
1281 if (iter
->u
.pointer
.const_qualifier
) {
1282 g_string_append(str
, " const");
1286 str_c
= g_string_free(str
, FALSE
);
1287 qalias
= g_quark_from_string(str_c
);
1295 int visit_field_class_declarator(struct ctx
*ctx
,
1296 struct ctf_node
*cls_specifier_list
,
1297 GQuark
*field_name
, struct ctf_node
*node_field_class_declarator
,
1298 struct ctf_field_class
**field_decl
,
1299 struct ctf_field_class
*nested_decl
)
1302 * During this whole function, nested_decl is always OURS,
1303 * whereas field_decl is an output which we create, but
1304 * belongs to the caller (it is moved).
1309 /* Validate field class declarator node */
1310 if (node_field_class_declarator
) {
1311 if (node_field_class_declarator
->u
.field_class_declarator
.type
==
1313 _BT_COMP_LOGE_NODE(node_field_class_declarator
,
1314 "Unexpected field class declarator type: type=%d",
1315 node_field_class_declarator
->u
.field_class_declarator
.type
);
1320 /* TODO: GCC bitfields not supported yet */
1321 if (node_field_class_declarator
->u
.field_class_declarator
.bitfield_len
!=
1323 _BT_COMP_LOGE_NODE(node_field_class_declarator
,
1324 "GCC bitfields are not supported as of this version.");
1330 /* Find the right nested declaration if not provided */
1332 struct bt_list_head
*pointers
=
1333 &node_field_class_declarator
->u
.field_class_declarator
.pointers
;
1335 if (node_field_class_declarator
&& !bt_list_empty(pointers
)) {
1339 * If we have a pointer declarator, it HAS to
1340 * be present in the field class aliases (else
1343 qalias
= create_class_alias_identifier(ctx
,
1344 cls_specifier_list
, node_field_class_declarator
);
1346 ctx_decl_scope_lookup_alias(ctx
,
1348 g_quark_to_string(qalias
), -1, true);
1350 _BT_COMP_LOGE_NODE(node_field_class_declarator
,
1351 "Cannot find class alias: name=\"%s\"",
1352 g_quark_to_string(qalias
));
1357 if (nested_decl
->type
== CTF_FIELD_CLASS_TYPE_INT
) {
1358 /* Pointer: force integer's base to 16 */
1359 struct ctf_field_class_int
*int_fc
=
1360 (void *) nested_decl
;
1363 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
;
1366 ret
= visit_field_class_specifier_list(ctx
,
1367 cls_specifier_list
, &nested_decl
);
1369 BT_ASSERT(!nested_decl
);
1375 BT_ASSERT(nested_decl
);
1377 if (!node_field_class_declarator
) {
1378 *field_decl
= nested_decl
;
1383 if (node_field_class_declarator
->u
.field_class_declarator
.type
== TYPEDEC_ID
) {
1384 if (node_field_class_declarator
->u
.field_class_declarator
.u
.id
) {
1386 node_field_class_declarator
->u
.field_class_declarator
.u
.id
;
1392 *field_name
= g_quark_from_string(id
);
1397 *field_decl
= nested_decl
;
1401 struct ctf_node
*first
;
1402 struct ctf_field_class
*decl
= NULL
;
1403 struct ctf_field_class
*outer_field_decl
= NULL
;
1404 struct bt_list_head
*length
=
1405 &node_field_class_declarator
->
1406 u
.field_class_declarator
.u
.nested
.length
;
1408 /* Create array/sequence, pass nested_decl as child */
1409 if (bt_list_empty(length
)) {
1410 _BT_COMP_LOGE_NODE(node_field_class_declarator
,
1411 "Expecting length field reference or value.");
1416 first
= _BT_LIST_FIRST_ENTRY(length
, struct ctf_node
, siblings
);
1417 if (first
->type
!= NODE_UNARY_EXPRESSION
) {
1418 _BT_COMP_LOGE_NODE(first
,
1419 "Unexpected node type: node-type=%d",
1425 switch (first
->u
.unary_expression
.type
) {
1426 case UNARY_UNSIGNED_CONSTANT
:
1428 struct ctf_field_class_array
*array_decl
= NULL
;
1430 array_decl
= ctf_field_class_array_create();
1431 BT_ASSERT(array_decl
);
1432 array_decl
->length
=
1433 first
->u
.unary_expression
.u
.unsigned_constant
;
1434 array_decl
->base
.elem_fc
= nested_decl
;
1436 decl
= (void *) array_decl
;
1441 /* Lookup unsigned integer definition, create seq. */
1442 struct ctf_field_class_sequence
*seq_decl
= NULL
;
1443 char *length_name
= concatenate_unary_strings(length
);
1446 _BT_COMP_LOGE_NODE(node_field_class_declarator
,
1447 "Cannot concatenate unary strings.");
1452 if (strncmp(length_name
, "env.", 4) == 0) {
1453 /* This is, in fact, an array */
1454 const char *env_entry_name
= &length_name
[4];
1455 struct ctf_trace_class_env_entry
*env_entry
=
1456 ctf_trace_class_borrow_env_entry_by_name(
1457 ctx
->ctf_tc
, env_entry_name
);
1458 struct ctf_field_class_array
*array_decl
;
1461 _BT_COMP_LOGE_NODE(node_field_class_declarator
,
1462 "Cannot find environment entry: "
1463 "name=\"%s\"", env_entry_name
);
1468 if (env_entry
->type
!= CTF_TRACE_CLASS_ENV_ENTRY_TYPE_INT
) {
1469 _BT_COMP_LOGE_NODE(node_field_class_declarator
,
1470 "Wrong environment entry type "
1471 "(expecting integer): "
1472 "name=\"%s\"", env_entry_name
);
1477 if (env_entry
->value
.i
< 0) {
1478 _BT_COMP_LOGE_NODE(node_field_class_declarator
,
1479 "Invalid, negative array length: "
1480 "env-entry-name=\"%s\", "
1483 env_entry
->value
.i
);
1488 array_decl
= ctf_field_class_array_create();
1489 BT_ASSERT(array_decl
);
1490 array_decl
->length
=
1491 (uint64_t) env_entry
->value
.i
;
1492 array_decl
->base
.elem_fc
= nested_decl
;
1494 decl
= (void *) array_decl
;
1496 char *length_name_no_underscore
=
1497 remove_underscores_from_field_ref(ctx
,
1499 if (!length_name_no_underscore
) {
1501 * remove_underscores_from_field_ref()
1507 seq_decl
= ctf_field_class_sequence_create();
1508 BT_ASSERT(seq_decl
);
1509 seq_decl
->base
.elem_fc
= nested_decl
;
1511 g_string_assign(seq_decl
->length_ref
,
1512 length_name_no_underscore
);
1513 free(length_name_no_underscore
);
1514 decl
= (void *) seq_decl
;
1517 g_free(length_name
);
1525 BT_ASSERT(!nested_decl
);
1527 BT_ASSERT(!*field_decl
);
1530 * At this point, we found the next nested declaration.
1531 * We currently own this (and lost the ownership of
1532 * nested_decl in the meantime). Pass this next
1533 * nested declaration as the content of the outer
1534 * container, MOVING its ownership.
1536 ret
= visit_field_class_declarator(ctx
, cls_specifier_list
,
1538 node_field_class_declarator
->
1539 u
.field_class_declarator
.u
.nested
.field_class_declarator
,
1540 &outer_field_decl
, decl
);
1543 BT_ASSERT(!outer_field_decl
);
1548 BT_ASSERT(outer_field_decl
);
1549 *field_decl
= outer_field_decl
;
1550 outer_field_decl
= NULL
;
1553 BT_ASSERT(*field_decl
);
1557 ctf_field_class_destroy(*field_decl
);
1565 ctf_field_class_destroy(nested_decl
);
1571 int visit_struct_decl_field(struct ctx
*ctx
,
1572 struct ctf_field_class_struct
*struct_decl
,
1573 struct ctf_node
*cls_specifier_list
,
1574 struct bt_list_head
*field_class_declarators
)
1577 struct ctf_node
*iter
;
1578 struct ctf_field_class
*field_decl
= NULL
;
1580 bt_list_for_each_entry(iter
, field_class_declarators
, siblings
) {
1583 const char *field_name
;
1585 ret
= visit_field_class_declarator(ctx
, cls_specifier_list
,
1586 &qfield_name
, iter
, &field_decl
, NULL
);
1588 BT_ASSERT(!field_decl
);
1589 _BT_COMP_LOGE_NODE(cls_specifier_list
,
1590 "Cannot visit field class declarator: ret=%d", ret
);
1594 BT_ASSERT(field_decl
);
1595 field_name
= g_quark_to_string(qfield_name
);
1597 /* Check if field with same name already exists */
1598 if (ctf_field_class_struct_borrow_member_by_name(
1599 struct_decl
, field_name
)) {
1600 _BT_COMP_LOGE_NODE(cls_specifier_list
,
1601 "Duplicate field in structure field class: "
1602 "field-name=\"%s\"", field_name
);
1607 /* Add field to structure */
1608 ctf_field_class_struct_append_member(struct_decl
,
1609 field_name
, field_decl
);
1616 ctf_field_class_destroy(field_decl
);
1622 int visit_variant_decl_field(struct ctx
*ctx
,
1623 struct ctf_field_class_variant
*variant_decl
,
1624 struct ctf_node
*cls_specifier_list
,
1625 struct bt_list_head
*field_class_declarators
)
1628 struct ctf_node
*iter
;
1629 struct ctf_field_class
*field_decl
= NULL
;
1631 bt_list_for_each_entry(iter
, field_class_declarators
, siblings
) {
1634 const char *field_name
;
1636 ret
= visit_field_class_declarator(ctx
, cls_specifier_list
,
1637 &qfield_name
, iter
, &field_decl
, NULL
);
1639 BT_ASSERT(!field_decl
);
1640 _BT_COMP_LOGE_NODE(cls_specifier_list
,
1641 "Cannot visit field class declarator: ret=%d", ret
);
1645 BT_ASSERT(field_decl
);
1646 field_name
= g_quark_to_string(qfield_name
);
1648 /* Check if field with same name already exists */
1649 if (ctf_field_class_variant_borrow_option_by_name(
1650 variant_decl
, field_name
)) {
1651 _BT_COMP_LOGE_NODE(cls_specifier_list
,
1652 "Duplicate field in variant field class: "
1653 "field-name=\"%s\"", field_name
);
1658 /* Add field to structure */
1659 ctf_field_class_variant_append_option(variant_decl
,
1660 field_name
, field_decl
);
1667 ctf_field_class_destroy(field_decl
);
1673 int visit_field_class_def(struct ctx
*ctx
, struct ctf_node
*cls_specifier_list
,
1674 struct bt_list_head
*field_class_declarators
)
1678 struct ctf_node
*iter
;
1679 struct ctf_field_class
*class_decl
= NULL
;
1681 bt_list_for_each_entry(iter
, field_class_declarators
, siblings
) {
1682 ret
= visit_field_class_declarator(ctx
, cls_specifier_list
,
1683 &qidentifier
, iter
, &class_decl
, NULL
);
1685 _BT_COMP_LOGE_NODE(iter
,
1686 "Cannot visit field class declarator: ret=%d", ret
);
1691 /* Do not allow field class def and alias of untagged variants */
1692 if (class_decl
->type
== CTF_FIELD_CLASS_TYPE_VARIANT
) {
1693 struct ctf_field_class_variant
*var_fc
=
1694 (void *) class_decl
;
1696 if (var_fc
->tag_path
.path
->len
== 0) {
1697 _BT_COMP_LOGE_NODE(iter
,
1698 "Type definition of untagged variant field class is not allowed.");
1704 ret
= ctx_decl_scope_register_alias(ctx
, ctx
->current_scope
,
1705 g_quark_to_string(qidentifier
), class_decl
);
1707 _BT_COMP_LOGE_NODE(iter
,
1708 "Cannot register field class alias: name=\"%s\"",
1709 g_quark_to_string(qidentifier
));
1715 ctf_field_class_destroy(class_decl
);
1721 int visit_field_class_alias(struct ctx
*ctx
, struct ctf_node
*target
,
1722 struct ctf_node
*alias
)
1726 struct ctf_node
*node
;
1727 GQuark qdummy_field_name
;
1728 struct ctf_field_class
*class_decl
= NULL
;
1730 /* Create target field class */
1731 if (bt_list_empty(&target
->u
.field_class_alias_target
.field_class_declarators
)) {
1734 node
= _BT_LIST_FIRST_ENTRY(
1735 &target
->u
.field_class_alias_target
.field_class_declarators
,
1736 struct ctf_node
, siblings
);
1739 ret
= visit_field_class_declarator(ctx
,
1740 target
->u
.field_class_alias_target
.field_class_specifier_list
,
1741 &qdummy_field_name
, node
, &class_decl
, NULL
);
1743 BT_ASSERT(!class_decl
);
1744 _BT_COMP_LOGE_NODE(node
,
1745 "Cannot visit field class declarator: ret=%d", ret
);
1749 /* Do not allow field class def and alias of untagged variants */
1750 if (class_decl
->type
== CTF_FIELD_CLASS_TYPE_VARIANT
) {
1751 struct ctf_field_class_variant
*var_fc
= (void *) class_decl
;
1753 if (var_fc
->tag_path
.path
->len
== 0) {
1754 _BT_COMP_LOGE_NODE(target
,
1755 "Type definition of untagged variant field class is not allowed.");
1762 * The semantic validator does not check whether the target is
1763 * abstract or not (if it has an identifier). Check it here.
1765 if (qdummy_field_name
!= 0) {
1766 _BT_COMP_LOGE_NODE(target
,
1767 "Expecting empty identifier: id=\"%s\"",
1768 g_quark_to_string(qdummy_field_name
));
1773 /* Create alias identifier */
1774 node
= _BT_LIST_FIRST_ENTRY(&alias
->u
.field_class_alias_name
.field_class_declarators
,
1775 struct ctf_node
, siblings
);
1776 qalias
= create_class_alias_identifier(ctx
,
1777 alias
->u
.field_class_alias_name
.field_class_specifier_list
, node
);
1778 ret
= ctx_decl_scope_register_alias(ctx
, ctx
->current_scope
,
1779 g_quark_to_string(qalias
), class_decl
);
1781 _BT_COMP_LOGE_NODE(node
,
1782 "Cannot register class alias: name=\"%s\"",
1783 g_quark_to_string(qalias
));
1788 ctf_field_class_destroy(class_decl
);
1794 int visit_struct_decl_entry(struct ctx
*ctx
, struct ctf_node
*entry_node
,
1795 struct ctf_field_class_struct
*struct_decl
)
1799 switch (entry_node
->type
) {
1801 ret
= visit_field_class_def(ctx
,
1802 entry_node
->u
.field_class_def
.field_class_specifier_list
,
1803 &entry_node
->u
.field_class_def
.field_class_declarators
);
1805 _BT_COMP_LOGE_NODE(entry_node
,
1806 "Cannot add field class found in structure field class: ret=%d",
1811 case NODE_TYPEALIAS
:
1812 ret
= visit_field_class_alias(ctx
, entry_node
->u
.field_class_alias
.target
,
1813 entry_node
->u
.field_class_alias
.alias
);
1815 _BT_COMP_LOGE_NODE(entry_node
,
1816 "Cannot add field class alias found in structure field class: ret=%d",
1821 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
1823 ret
= visit_struct_decl_field(ctx
, struct_decl
,
1824 entry_node
->u
.struct_or_variant_declaration
.
1825 field_class_specifier_list
,
1826 &entry_node
->u
.struct_or_variant_declaration
.
1827 field_class_declarators
);
1833 _BT_COMP_LOGE_NODE(entry_node
,
1834 "Unexpected node type: node-type=%d", entry_node
->type
);
1844 int visit_variant_decl_entry(struct ctx
*ctx
, struct ctf_node
*entry_node
,
1845 struct ctf_field_class_variant
*variant_decl
)
1849 switch (entry_node
->type
) {
1851 ret
= visit_field_class_def(ctx
,
1852 entry_node
->u
.field_class_def
.field_class_specifier_list
,
1853 &entry_node
->u
.field_class_def
.field_class_declarators
);
1855 _BT_COMP_LOGE_NODE(entry_node
,
1856 "Cannot add field class found in variant field class: ret=%d",
1861 case NODE_TYPEALIAS
:
1862 ret
= visit_field_class_alias(ctx
, entry_node
->u
.field_class_alias
.target
,
1863 entry_node
->u
.field_class_alias
.alias
);
1865 _BT_COMP_LOGE_NODE(entry_node
,
1866 "Cannot add field class alias found in variant field class: ret=%d",
1871 case NODE_STRUCT_OR_VARIANT_DECLARATION
:
1873 ret
= visit_variant_decl_field(ctx
, variant_decl
,
1874 entry_node
->u
.struct_or_variant_declaration
.
1875 field_class_specifier_list
,
1876 &entry_node
->u
.struct_or_variant_declaration
.
1877 field_class_declarators
);
1883 _BT_COMP_LOGE_NODE(entry_node
,
1884 "Unexpected node type: node-type=%d",
1895 int visit_struct_decl(struct ctx
*ctx
, const char *name
,
1896 struct bt_list_head
*decl_list
, int has_body
,
1897 struct bt_list_head
*min_align
,
1898 struct ctf_field_class_struct
**struct_decl
)
1902 BT_ASSERT(struct_decl
);
1903 *struct_decl
= NULL
;
1905 /* For named struct (without body), lookup in declaration scope */
1908 BT_COMP_LOGE_STR("Bodyless structure field class: missing name.");
1913 *struct_decl
= ctx_decl_scope_lookup_struct(ctx
, ctx
->current_scope
,
1915 if (!*struct_decl
) {
1916 BT_COMP_LOGE("Cannot find structure field class: name=\"struct %s\"",
1922 struct ctf_node
*entry_node
;
1923 uint64_t min_align_value
= 0;
1926 if (ctx_decl_scope_lookup_struct(ctx
,
1927 ctx
->current_scope
, name
, 1, false)) {
1928 BT_COMP_LOGE("Structure field class already declared in local scope: "
1929 "name=\"struct %s\"", name
);
1935 if (!bt_list_empty(min_align
)) {
1936 ret
= get_unary_unsigned(ctx
, min_align
,
1939 BT_COMP_LOGE("Unexpected unary expression for structure field class's `align` attribute: "
1945 *struct_decl
= ctf_field_class_struct_create();
1946 BT_ASSERT(*struct_decl
);
1948 if (min_align_value
!= 0) {
1949 (*struct_decl
)->base
.alignment
= min_align_value
;
1952 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
1954 bt_list_for_each_entry(entry_node
, decl_list
, siblings
) {
1955 ret
= visit_struct_decl_entry(ctx
, entry_node
,
1958 _BT_COMP_LOGE_NODE(entry_node
,
1959 "Cannot visit structure field class entry: "
1969 ret
= ctx_decl_scope_register_struct(ctx
,
1970 ctx
->current_scope
, name
, *struct_decl
);
1972 BT_COMP_LOGE("Cannot register structure field class in declaration scope: "
1973 "name=\"struct %s\", ret=%d", name
, ret
);
1982 ctf_field_class_destroy((void *) *struct_decl
);
1983 *struct_decl
= NULL
;
1988 int visit_variant_decl(struct ctx
*ctx
, const char *name
,
1989 const char *tag
, struct bt_list_head
*decl_list
,
1990 int has_body
, struct ctf_field_class_variant
**variant_decl
)
1993 struct ctf_field_class_variant
*untagged_variant_decl
= NULL
;
1995 BT_ASSERT(variant_decl
);
1996 *variant_decl
= NULL
;
1998 /* For named variant (without body), lookup in declaration scope */
2001 BT_COMP_LOGE_STR("Bodyless variant field class: missing name.");
2006 untagged_variant_decl
=
2007 ctx_decl_scope_lookup_variant(ctx
, ctx
->current_scope
,
2009 if (!untagged_variant_decl
) {
2010 BT_COMP_LOGE("Cannot find variant field class: name=\"variant %s\"",
2016 struct ctf_node
*entry_node
;
2019 if (ctx_decl_scope_lookup_variant(ctx
,
2020 ctx
->current_scope
, name
, 1, false)) {
2021 BT_COMP_LOGE("Variant field class already declared in local scope: "
2022 "name=\"variant %s\"", name
);
2028 untagged_variant_decl
= ctf_field_class_variant_create();
2029 BT_ASSERT(untagged_variant_decl
);
2030 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
2032 bt_list_for_each_entry(entry_node
, decl_list
, siblings
) {
2033 ret
= visit_variant_decl_entry(ctx
, entry_node
,
2034 untagged_variant_decl
);
2036 _BT_COMP_LOGE_NODE(entry_node
,
2037 "Cannot visit variant field class entry: "
2047 ret
= ctx_decl_scope_register_variant(ctx
,
2048 ctx
->current_scope
, name
,
2049 untagged_variant_decl
);
2051 BT_COMP_LOGE("Cannot register variant field class in declaration scope: "
2052 "name=\"variant %s\", ret=%d", name
, ret
);
2059 * If tagged, create tagged variant and return; otherwise
2060 * return untagged variant.
2063 *variant_decl
= untagged_variant_decl
;
2064 untagged_variant_decl
= NULL
;
2067 * At this point, we have a fresh untagged variant; nobody
2068 * else owns it. Set its tag now.
2070 char *tag_no_underscore
=
2071 remove_underscores_from_field_ref(ctx
, tag
);
2073 if (!tag_no_underscore
) {
2074 /* remove_underscores_from_field_ref() logs errors */
2078 g_string_assign(untagged_variant_decl
->tag_ref
,
2080 free(tag_no_underscore
);
2081 *variant_decl
= untagged_variant_decl
;
2082 untagged_variant_decl
= NULL
;
2085 BT_ASSERT(!untagged_variant_decl
);
2086 BT_ASSERT(*variant_decl
);
2090 ctf_field_class_destroy((void *) untagged_variant_decl
);
2091 untagged_variant_decl
= NULL
;
2092 ctf_field_class_destroy((void *) *variant_decl
);
2093 *variant_decl
= NULL
;
2106 int visit_enum_decl_entry(struct ctx
*ctx
, struct ctf_node
*enumerator
,
2107 struct ctf_field_class_enum
*enum_decl
, struct uori
*last
)
2111 struct ctf_node
*iter
;
2112 struct uori start
= {
2120 const char *label
= enumerator
->u
.enumerator
.id
;
2121 const char *effective_label
= label
;
2122 struct bt_list_head
*values
= &enumerator
->u
.enumerator
.values
;
2124 bt_list_for_each_entry(iter
, values
, siblings
) {
2125 struct uori
*target
;
2127 if (iter
->type
!= NODE_UNARY_EXPRESSION
) {
2128 _BT_COMP_LOGE_NODE(iter
,
2129 "Wrong expression for enumeration field class label: "
2130 "node-type=%d, label=\"%s\"", iter
->type
,
2142 switch (iter
->u
.unary_expression
.type
) {
2143 case UNARY_SIGNED_CONSTANT
:
2144 target
->is_signed
= true;
2146 iter
->u
.unary_expression
.u
.signed_constant
;
2148 case UNARY_UNSIGNED_CONSTANT
:
2149 target
->is_signed
= false;
2151 iter
->u
.unary_expression
.u
.unsigned_constant
;
2154 _BT_COMP_LOGE_NODE(iter
,
2155 "Invalid enumeration field class entry: "
2156 "expecting constant signed or unsigned integer: "
2157 "node-type=%d, label=\"%s\"",
2158 iter
->u
.unary_expression
.type
, label
);
2164 _BT_COMP_LOGE_NODE(iter
,
2165 "Invalid enumeration field class entry: label=\"%s\"",
2182 if (end
.is_signed
) {
2183 last
->value
.i
= end
.value
.i
+ 1;
2185 last
->value
.u
= end
.value
.u
+ 1;
2188 if (label
[0] == '_') {
2190 * Strip the first underscore of any enumeration field
2191 * class's label in case this enumeration FC is used as
2192 * a variant FC tag later. The variant FC choice names
2193 * could also start with `_`, in which case the prefix
2194 * is removed, and it the resulting choice name needs to
2197 effective_label
= &label
[1];
2200 ctf_field_class_enum_append_mapping(enum_decl
, effective_label
,
2201 start
.value
.u
, end
.value
.u
);
2209 int visit_enum_decl(struct ctx
*ctx
, const char *name
,
2210 struct ctf_node
*container_cls
,
2211 struct bt_list_head
*enumerator_list
,
2212 int has_body
, struct ctf_field_class_enum
**enum_decl
)
2216 struct ctf_field_class_int
*integer_decl
= NULL
;
2218 BT_ASSERT(enum_decl
);
2221 /* For named enum (without body), lookup in declaration scope */
2224 BT_COMP_LOGE_STR("Bodyless enumeration field class: missing name.");
2229 *enum_decl
= ctx_decl_scope_lookup_enum(ctx
, ctx
->current_scope
,
2232 BT_COMP_LOGE("Cannot find enumeration field class: "
2233 "name=\"enum %s\"", name
);
2238 struct ctf_node
*iter
;
2239 struct uori last_value
= {
2245 if (ctx_decl_scope_lookup_enum(ctx
, ctx
->current_scope
,
2247 BT_COMP_LOGE("Enumeration field class already declared in local scope: "
2248 "name=\"enum %s\"", name
);
2254 if (!container_cls
) {
2255 integer_decl
= (void *) ctx_decl_scope_lookup_alias(ctx
,
2256 ctx
->current_scope
, "int", -1, true);
2257 if (!integer_decl
) {
2258 BT_COMP_LOGE_STR("Cannot find implicit `int` field class alias for enumeration field class.");
2263 ret
= visit_field_class_declarator(ctx
, container_cls
,
2264 &qdummy_id
, NULL
, (void *) &integer_decl
,
2267 BT_ASSERT(!integer_decl
);
2273 BT_ASSERT(integer_decl
);
2275 if (integer_decl
->base
.base
.type
!= CTF_FIELD_CLASS_TYPE_INT
) {
2276 BT_COMP_LOGE("Container field class for enumeration field class is not an integer field class: "
2277 "fc-type=%d", integer_decl
->base
.base
.type
);
2282 *enum_decl
= ctf_field_class_enum_create();
2283 BT_ASSERT(*enum_decl
);
2284 (*enum_decl
)->base
.base
.base
.alignment
=
2285 integer_decl
->base
.base
.alignment
;
2286 ctf_field_class_int_copy_content((void *) *enum_decl
,
2287 (void *) integer_decl
);
2288 last_value
.is_signed
= (*enum_decl
)->base
.is_signed
;
2290 bt_list_for_each_entry(iter
, enumerator_list
, siblings
) {
2291 ret
= visit_enum_decl_entry(ctx
, iter
, *enum_decl
,
2294 _BT_COMP_LOGE_NODE(iter
,
2295 "Cannot visit enumeration field class entry: "
2302 ret
= ctx_decl_scope_register_enum(ctx
,
2303 ctx
->current_scope
, name
, *enum_decl
);
2305 BT_COMP_LOGE("Cannot register enumeration field class in declaration scope: "
2315 ctf_field_class_destroy((void *) *enum_decl
);
2319 ctf_field_class_destroy((void *) integer_decl
);
2320 integer_decl
= NULL
;
2325 int visit_field_class_specifier(struct ctx
*ctx
,
2326 struct ctf_node
*cls_specifier_list
,
2327 struct ctf_field_class
**decl
)
2330 GString
*str
= NULL
;
2333 str
= g_string_new("");
2334 ret
= get_class_specifier_list_name(ctx
, cls_specifier_list
, str
);
2336 _BT_COMP_LOGE_NODE(cls_specifier_list
,
2337 "Cannot get field class specifier list's name: ret=%d", ret
);
2341 *decl
= ctx_decl_scope_lookup_alias(ctx
, ctx
->current_scope
, str
->str
,
2344 _BT_COMP_LOGE_NODE(cls_specifier_list
,
2345 "Cannot find field class alias: name=\"%s\"", str
->str
);
2353 ctf_field_class_destroy(*decl
);
2358 g_string_free(str
, TRUE
);
2365 int visit_integer_decl(struct ctx
*ctx
,
2366 struct bt_list_head
*expressions
,
2367 struct ctf_field_class_int
**integer_decl
)
2372 struct ctf_node
*expression
;
2373 uint64_t alignment
= 0, size
= 0;
2374 struct ctf_clock_class
*mapped_clock_class
= NULL
;
2375 enum ctf_encoding encoding
= CTF_ENCODING_NONE
;
2376 bt_field_class_integer_preferred_display_base base
=
2377 BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
;
2378 enum ctf_byte_order byte_order
= ctx
->ctf_tc
->default_byte_order
;
2380 *integer_decl
= NULL
;
2382 bt_list_for_each_entry(expression
, expressions
, siblings
) {
2383 struct ctf_node
*left
, *right
;
2385 left
= _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.left
,
2386 struct ctf_node
, siblings
);
2387 right
= _BT_LIST_FIRST_ENTRY(
2388 &expression
->u
.ctf_expression
.right
, struct ctf_node
,
2391 if (left
->u
.unary_expression
.type
!= UNARY_STRING
) {
2392 _BT_COMP_LOGE_NODE(left
,
2393 "Unexpected unary expression type: type=%d",
2394 left
->u
.unary_expression
.type
);
2399 if (strcmp(left
->u
.unary_expression
.u
.string
, "signed") == 0) {
2400 if (_IS_SET(&set
, _INTEGER_SIGNED_SET
)) {
2401 _BT_COMP_LOGE_DUP_ATTR(left
, "signed",
2402 "integer field class");
2407 signedness
= get_boolean(ctx
, right
);
2408 if (signedness
< 0) {
2409 _BT_COMP_LOGE_NODE(right
,
2410 "Invalid boolean value for integer field class's `signed` attribute: "
2416 _SET(&set
, _INTEGER_SIGNED_SET
);
2417 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "byte_order") == 0) {
2418 if (_IS_SET(&set
, _INTEGER_BYTE_ORDER_SET
)) {
2419 _BT_COMP_LOGE_DUP_ATTR(left
, "byte_order",
2420 "integer field class");
2425 byte_order
= get_real_byte_order(ctx
, right
);
2426 if (byte_order
== -1) {
2427 _BT_COMP_LOGE_NODE(right
,
2428 "Invalid `byte_order` attribute in integer field class: "
2434 _SET(&set
, _INTEGER_BYTE_ORDER_SET
);
2435 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "size") == 0) {
2436 if (_IS_SET(&set
, _INTEGER_SIZE_SET
)) {
2437 _BT_COMP_LOGE_DUP_ATTR(left
, "size",
2438 "integer field class");
2443 if (right
->u
.unary_expression
.type
!=
2444 UNARY_UNSIGNED_CONSTANT
) {
2445 _BT_COMP_LOGE_NODE(right
,
2446 "Invalid `size` attribute in integer field class: "
2447 "expecting unsigned constant integer: "
2449 right
->u
.unary_expression
.type
);
2454 size
= right
->u
.unary_expression
.u
.unsigned_constant
;
2456 _BT_COMP_LOGE_NODE(right
,
2457 "Invalid `size` attribute in integer field class: "
2458 "expecting positive constant integer: "
2459 "size=%" PRIu64
, size
);
2462 } else if (size
> 64) {
2463 _BT_COMP_LOGE_NODE(right
,
2464 "Invalid `size` attribute in integer field class: "
2465 "integer fields over 64 bits are not supported as of this version: "
2466 "size=%" PRIu64
, size
);
2471 _SET(&set
, _INTEGER_SIZE_SET
);
2472 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "align") == 0) {
2473 if (_IS_SET(&set
, _INTEGER_ALIGN_SET
)) {
2474 _BT_COMP_LOGE_DUP_ATTR(left
, "align",
2475 "integer field class");
2480 if (right
->u
.unary_expression
.type
!=
2481 UNARY_UNSIGNED_CONSTANT
) {
2482 _BT_COMP_LOGE_NODE(right
,
2483 "Invalid `align` attribute in integer field class: "
2484 "expecting unsigned constant integer: "
2486 right
->u
.unary_expression
.type
);
2492 right
->u
.unary_expression
.u
.unsigned_constant
;
2493 if (!is_align_valid(alignment
)) {
2494 _BT_COMP_LOGE_NODE(right
,
2495 "Invalid `align` attribute in integer field class: "
2496 "expecting power of two: "
2497 "align=%" PRIu64
, alignment
);
2502 _SET(&set
, _INTEGER_ALIGN_SET
);
2503 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "base") == 0) {
2504 if (_IS_SET(&set
, _INTEGER_BASE_SET
)) {
2505 _BT_COMP_LOGE_DUP_ATTR(left
, "base",
2506 "integer field class");
2511 switch (right
->u
.unary_expression
.type
) {
2512 case UNARY_UNSIGNED_CONSTANT
:
2514 uint64_t constant
= right
->u
.unary_expression
.
2515 u
.unsigned_constant
;
2519 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY
;
2522 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL
;
2525 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
;
2528 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
;
2531 _BT_COMP_LOGE_NODE(right
,
2532 "Invalid `base` attribute in integer field class: "
2534 right
->u
.unary_expression
.u
.unsigned_constant
);
2542 char *s_right
= concatenate_unary_strings(
2543 &expression
->u
.ctf_expression
.right
);
2545 _BT_COMP_LOGE_NODE(right
,
2546 "Unexpected unary expression for integer field class's `base` attribute.");
2551 if (strcmp(s_right
, "decimal") == 0 ||
2552 strcmp(s_right
, "dec") == 0 ||
2553 strcmp(s_right
, "d") == 0 ||
2554 strcmp(s_right
, "i") == 0 ||
2555 strcmp(s_right
, "u") == 0) {
2556 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
;
2557 } else if (strcmp(s_right
, "hexadecimal") == 0 ||
2558 strcmp(s_right
, "hex") == 0 ||
2559 strcmp(s_right
, "x") == 0 ||
2560 strcmp(s_right
, "X") == 0 ||
2561 strcmp(s_right
, "p") == 0) {
2562 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
;
2563 } else if (strcmp(s_right
, "octal") == 0 ||
2564 strcmp(s_right
, "oct") == 0 ||
2565 strcmp(s_right
, "o") == 0) {
2566 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL
;
2567 } else if (strcmp(s_right
, "binary") == 0 ||
2568 strcmp(s_right
, "b") == 0) {
2569 base
= BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY
;
2571 _BT_COMP_LOGE_NODE(right
,
2572 "Unexpected unary expression for integer field class's `base` attribute: "
2573 "base=\"%s\"", s_right
);
2583 _BT_COMP_LOGE_NODE(right
,
2584 "Invalid `base` attribute in integer field class: "
2585 "expecting unsigned constant integer or unary string.");
2590 _SET(&set
, _INTEGER_BASE_SET
);
2591 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "encoding") == 0) {
2594 if (_IS_SET(&set
, _INTEGER_ENCODING_SET
)) {
2595 _BT_COMP_LOGE_DUP_ATTR(left
, "encoding",
2596 "integer field class");
2601 if (right
->u
.unary_expression
.type
!= UNARY_STRING
) {
2602 _BT_COMP_LOGE_NODE(right
,
2603 "Invalid `encoding` attribute in integer field class: "
2604 "expecting unary string.");
2609 s_right
= concatenate_unary_strings(
2610 &expression
->u
.ctf_expression
.right
);
2612 _BT_COMP_LOGE_NODE(right
,
2613 "Unexpected unary expression for integer field class's `encoding` attribute.");
2618 if (strcmp(s_right
, "UTF8") == 0 ||
2619 strcmp(s_right
, "utf8") == 0 ||
2620 strcmp(s_right
, "utf-8") == 0 ||
2621 strcmp(s_right
, "UTF-8") == 0 ||
2622 strcmp(s_right
, "ASCII") == 0 ||
2623 strcmp(s_right
, "ascii") == 0) {
2624 encoding
= CTF_ENCODING_UTF8
;
2625 } else if (strcmp(s_right
, "none") == 0) {
2626 encoding
= CTF_ENCODING_NONE
;
2628 _BT_COMP_LOGE_NODE(right
,
2629 "Invalid `encoding` attribute in integer field class: "
2630 "unknown encoding: encoding=\"%s\"",
2638 _SET(&set
, _INTEGER_ENCODING_SET
);
2639 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "map") == 0) {
2640 const char *clock_name
;
2642 if (_IS_SET(&set
, _INTEGER_MAP_SET
)) {
2643 _BT_COMP_LOGE_DUP_ATTR(left
, "map",
2644 "integer field class");
2649 if (right
->u
.unary_expression
.type
!= UNARY_STRING
) {
2650 _BT_COMP_LOGE_NODE(right
,
2651 "Invalid `map` attribute in integer field class: "
2652 "expecting unary string.");
2658 get_map_clock_name_value(
2659 &expression
->u
.ctf_expression
.right
);
2661 char *s_right
= concatenate_unary_strings(
2662 &expression
->u
.ctf_expression
.right
);
2665 _BT_COMP_LOGE_NODE(right
,
2666 "Unexpected unary expression for integer field class's `map` attribute.");
2671 _BT_COMP_LOGE_NODE(right
,
2672 "Invalid `map` attribute in integer field class: "
2673 "cannot find clock class at this point: name=\"%s\"",
2675 _SET(&set
, _INTEGER_MAP_SET
);
2680 mapped_clock_class
=
2681 ctf_trace_class_borrow_clock_class_by_name(
2682 ctx
->ctf_tc
, clock_name
);
2683 if (!mapped_clock_class
) {
2684 _BT_COMP_LOGE_NODE(right
,
2685 "Invalid `map` attribute in integer field class: "
2686 "cannot find clock class at this point: name=\"%s\"",
2692 _SET(&set
, _INTEGER_MAP_SET
);
2694 _BT_COMP_LOGW_NODE(left
,
2695 "Unknown attribute in integer field class: "
2697 left
->u
.unary_expression
.u
.string
);
2701 if (!_IS_SET(&set
, _INTEGER_SIZE_SET
)) {
2702 BT_COMP_LOGE_STR("Missing `size` attribute in integer field class.");
2707 if (!_IS_SET(&set
, _INTEGER_ALIGN_SET
)) {
2708 if (size
% CHAR_BIT
) {
2709 /* Bit-packed alignment */
2712 /* Byte-packed alignment */
2713 alignment
= CHAR_BIT
;
2717 *integer_decl
= ctf_field_class_int_create();
2718 BT_ASSERT(*integer_decl
);
2719 (*integer_decl
)->base
.base
.alignment
= alignment
;
2720 (*integer_decl
)->base
.byte_order
= byte_order
;
2721 (*integer_decl
)->base
.size
= size
;
2722 (*integer_decl
)->is_signed
= (signedness
> 0);
2723 (*integer_decl
)->disp_base
= base
;
2724 (*integer_decl
)->encoding
= encoding
;
2725 (*integer_decl
)->mapped_clock_class
= mapped_clock_class
;
2729 ctf_field_class_destroy((void *) *integer_decl
);
2730 *integer_decl
= NULL
;
2735 int visit_floating_point_number_decl(struct ctx
*ctx
,
2736 struct bt_list_head
*expressions
,
2737 struct ctf_field_class_float
**float_decl
)
2741 struct ctf_node
*expression
;
2742 uint64_t alignment
= 1, exp_dig
= 0, mant_dig
= 0;
2743 enum ctf_byte_order byte_order
= ctx
->ctf_tc
->default_byte_order
;
2747 bt_list_for_each_entry(expression
, expressions
, siblings
) {
2748 struct ctf_node
*left
, *right
;
2750 left
= _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.left
,
2751 struct ctf_node
, siblings
);
2752 right
= _BT_LIST_FIRST_ENTRY(
2753 &expression
->u
.ctf_expression
.right
, struct ctf_node
,
2756 if (left
->u
.unary_expression
.type
!= UNARY_STRING
) {
2757 _BT_COMP_LOGE_NODE(left
,
2758 "Unexpected unary expression type: type=%d",
2759 left
->u
.unary_expression
.type
);
2764 if (strcmp(left
->u
.unary_expression
.u
.string
, "byte_order") == 0) {
2765 if (_IS_SET(&set
, _FLOAT_BYTE_ORDER_SET
)) {
2766 _BT_COMP_LOGE_DUP_ATTR(left
, "byte_order",
2767 "floating point number field class");
2772 byte_order
= get_real_byte_order(ctx
, right
);
2773 if (byte_order
== -1) {
2774 _BT_COMP_LOGE_NODE(right
,
2775 "Invalid `byte_order` attribute in floating point number field class: "
2781 _SET(&set
, _FLOAT_BYTE_ORDER_SET
);
2782 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "exp_dig") == 0) {
2783 if (_IS_SET(&set
, _FLOAT_EXP_DIG_SET
)) {
2784 _BT_COMP_LOGE_DUP_ATTR(left
, "exp_dig",
2785 "floating point number field class");
2790 if (right
->u
.unary_expression
.type
!=
2791 UNARY_UNSIGNED_CONSTANT
) {
2792 _BT_COMP_LOGE_NODE(right
,
2793 "Invalid `exp_dig` attribute in floating point number field class: "
2794 "expecting unsigned constant integer: "
2796 right
->u
.unary_expression
.type
);
2801 exp_dig
= right
->u
.unary_expression
.u
.unsigned_constant
;
2802 _SET(&set
, _FLOAT_EXP_DIG_SET
);
2803 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "mant_dig") == 0) {
2804 if (_IS_SET(&set
, _FLOAT_MANT_DIG_SET
)) {
2805 _BT_COMP_LOGE_DUP_ATTR(left
, "mant_dig",
2806 "floating point number field class");
2811 if (right
->u
.unary_expression
.type
!=
2812 UNARY_UNSIGNED_CONSTANT
) {
2813 _BT_COMP_LOGE_NODE(right
,
2814 "Invalid `mant_dig` attribute in floating point number field class: "
2815 "expecting unsigned constant integer: "
2817 right
->u
.unary_expression
.type
);
2822 mant_dig
= right
->u
.unary_expression
.u
.
2824 _SET(&set
, _FLOAT_MANT_DIG_SET
);
2825 } else if (strcmp(left
->u
.unary_expression
.u
.string
, "align") == 0) {
2826 if (_IS_SET(&set
, _FLOAT_ALIGN_SET
)) {
2827 _BT_COMP_LOGE_DUP_ATTR(left
, "align",
2828 "floating point number field class");
2833 if (right
->u
.unary_expression
.type
!=
2834 UNARY_UNSIGNED_CONSTANT
) {
2835 _BT_COMP_LOGE_NODE(right
,
2836 "Invalid `align` attribute in floating point number field class: "
2837 "expecting unsigned constant integer: "
2839 right
->u
.unary_expression
.type
);
2844 alignment
= right
->u
.unary_expression
.u
.
2847 if (!is_align_valid(alignment
)) {
2848 _BT_COMP_LOGE_NODE(right
,
2849 "Invalid `align` attribute in floating point number field class: "
2850 "expecting power of two: "
2851 "align=%" PRIu64
, alignment
);
2856 _SET(&set
, _FLOAT_ALIGN_SET
);
2858 _BT_COMP_LOGW_NODE(left
,
2859 "Unknown attribute in floating point number field class: "
2861 left
->u
.unary_expression
.u
.string
);
2865 if (!_IS_SET(&set
, _FLOAT_MANT_DIG_SET
)) {
2866 BT_COMP_LOGE_STR("Missing `mant_dig` attribute in floating point number field class.");
2871 if (!_IS_SET(&set
, _FLOAT_EXP_DIG_SET
)) {
2872 BT_COMP_LOGE_STR("Missing `exp_dig` attribute in floating point number field class.");
2877 if (mant_dig
!= 24 && mant_dig
!= 53) {
2878 BT_COMP_LOGE_STR("`mant_dig` attribute: expecting 24 or 53.");
2883 if (mant_dig
== 24 && exp_dig
!= 8) {
2884 BT_COMP_LOGE_STR("`exp_dig` attribute: expecting 8 because `mant_dig` is 24.");
2889 if (mant_dig
== 53 && exp_dig
!= 11) {
2890 BT_COMP_LOGE_STR("`exp_dig` attribute: expecting 11 because `mant_dig` is 53.");
2895 if (!_IS_SET(&set
, _INTEGER_ALIGN_SET
)) {
2896 if ((mant_dig
+ exp_dig
) % CHAR_BIT
) {
2897 /* Bit-packed alignment */
2900 /* Byte-packed alignment */
2901 alignment
= CHAR_BIT
;
2905 *float_decl
= ctf_field_class_float_create();
2906 BT_ASSERT(*float_decl
);
2907 (*float_decl
)->base
.base
.alignment
= alignment
;
2908 (*float_decl
)->base
.byte_order
= byte_order
;
2909 (*float_decl
)->base
.size
= mant_dig
+ exp_dig
;
2913 ctf_field_class_destroy((void *) *float_decl
);
2919 int visit_string_decl(struct ctx
*ctx
,
2920 struct bt_list_head
*expressions
,
2921 struct ctf_field_class_string
**string_decl
)
2925 struct ctf_node
*expression
;
2926 enum ctf_encoding encoding
= CTF_ENCODING_UTF8
;
2928 *string_decl
= NULL
;
2930 bt_list_for_each_entry(expression
, expressions
, siblings
) {
2931 struct ctf_node
*left
, *right
;
2933 left
= _BT_LIST_FIRST_ENTRY(&expression
->u
.ctf_expression
.left
,
2934 struct ctf_node
, siblings
);
2935 right
= _BT_LIST_FIRST_ENTRY(
2936 &expression
->u
.ctf_expression
.right
, struct ctf_node
,
2939 if (left
->u
.unary_expression
.type
!= UNARY_STRING
) {
2940 _BT_COMP_LOGE_NODE(left
,
2941 "Unexpected unary expression type: type=%d",
2942 left
->u
.unary_expression
.type
);
2947 if (strcmp(left
->u
.unary_expression
.u
.string
, "encoding") == 0) {
2950 if (_IS_SET(&set
, _STRING_ENCODING_SET
)) {
2951 _BT_COMP_LOGE_DUP_ATTR(left
, "encoding",
2952 "string field class");
2957 if (right
->u
.unary_expression
.type
!= UNARY_STRING
) {
2958 _BT_COMP_LOGE_NODE(right
,
2959 "Invalid `encoding` attribute in string field class: "
2960 "expecting unary string.");
2965 s_right
= concatenate_unary_strings(
2966 &expression
->u
.ctf_expression
.right
);
2968 _BT_COMP_LOGE_NODE(right
,
2969 "Unexpected unary expression for string field class's `encoding` attribute.");
2974 if (strcmp(s_right
, "UTF8") == 0 ||
2975 strcmp(s_right
, "utf8") == 0 ||
2976 strcmp(s_right
, "utf-8") == 0 ||
2977 strcmp(s_right
, "UTF-8") == 0 ||
2978 strcmp(s_right
, "ASCII") == 0 ||
2979 strcmp(s_right
, "ascii") == 0) {
2980 encoding
= CTF_ENCODING_UTF8
;
2981 } else if (strcmp(s_right
, "none") == 0) {
2982 encoding
= CTF_ENCODING_NONE
;
2984 _BT_COMP_LOGE_NODE(right
,
2985 "Invalid `encoding` attribute in string field class: "
2986 "unknown encoding: encoding=\"%s\"",
2994 _SET(&set
, _STRING_ENCODING_SET
);
2996 _BT_COMP_LOGW_NODE(left
,
2997 "Unknown attribute in string field class: "
2999 left
->u
.unary_expression
.u
.string
);
3003 *string_decl
= ctf_field_class_string_create();
3004 BT_ASSERT(*string_decl
);
3005 (*string_decl
)->encoding
= encoding
;
3009 ctf_field_class_destroy((void *) *string_decl
);
3010 *string_decl
= NULL
;
3015 int visit_field_class_specifier_list(struct ctx
*ctx
,
3016 struct ctf_node
*ts_list
, struct ctf_field_class
**decl
)
3019 struct ctf_node
*first
, *node
;
3023 if (ts_list
->type
!= NODE_TYPE_SPECIFIER_LIST
) {
3024 _BT_COMP_LOGE_NODE(ts_list
,
3025 "Unexpected node type: node-type=%d", ts_list
->type
);
3030 first
= _BT_LIST_FIRST_ENTRY(&ts_list
->u
.field_class_specifier_list
.head
,
3031 struct ctf_node
, siblings
);
3032 if (first
->type
!= NODE_TYPE_SPECIFIER
) {
3033 _BT_COMP_LOGE_NODE(first
,
3034 "Unexpected node type: node-type=%d", first
->type
);
3039 node
= first
->u
.field_class_specifier
.node
;
3041 switch (first
->u
.field_class_specifier
.type
) {
3042 case TYPESPEC_INTEGER
:
3043 ret
= visit_integer_decl(ctx
, &node
->u
.integer
.expressions
,
3050 case TYPESPEC_FLOATING_POINT
:
3051 ret
= visit_floating_point_number_decl(ctx
,
3052 &node
->u
.floating_point
.expressions
, (void *) decl
);
3058 case TYPESPEC_STRING
:
3059 ret
= visit_string_decl(ctx
,
3060 &node
->u
.string
.expressions
, (void *) decl
);
3066 case TYPESPEC_STRUCT
:
3067 ret
= visit_struct_decl(ctx
, node
->u
._struct
.name
,
3068 &node
->u
._struct
.declaration_list
,
3069 node
->u
._struct
.has_body
,
3070 &node
->u
._struct
.min_align
, (void *) decl
);
3076 case TYPESPEC_VARIANT
:
3077 ret
= visit_variant_decl(ctx
, node
->u
.variant
.name
,
3078 node
->u
.variant
.choice
,
3079 &node
->u
.variant
.declaration_list
,
3080 node
->u
.variant
.has_body
, (void *) decl
);
3087 ret
= visit_enum_decl(ctx
, node
->u
._enum
.enum_id
,
3088 node
->u
._enum
.container_field_class
,
3089 &node
->u
._enum
.enumerator_list
,
3090 node
->u
._enum
.has_body
, (void *) decl
);
3098 case TYPESPEC_SHORT
:
3101 case TYPESPEC_FLOAT
:
3102 case TYPESPEC_DOUBLE
:
3103 case TYPESPEC_SIGNED
:
3104 case TYPESPEC_UNSIGNED
:
3106 case TYPESPEC_COMPLEX
:
3107 case TYPESPEC_IMAGINARY
:
3108 case TYPESPEC_CONST
:
3109 case TYPESPEC_ID_TYPE
:
3110 ret
= visit_field_class_specifier(ctx
, ts_list
, decl
);
3112 _BT_COMP_LOGE_NODE(first
,
3113 "Cannot visit field class specifier: ret=%d",
3120 _BT_COMP_LOGE_NODE(first
,
3121 "Unexpected field class specifier type: node-type=%d",
3122 first
->u
.field_class_specifier
.type
);
3131 ctf_field_class_destroy((void *) *decl
);
3137 int visit_event_decl_entry(struct ctx
*ctx
, struct ctf_node
*node
,
3138 struct ctf_event_class
*event_class
, uint64_t *stream_id
,
3144 switch (node
->type
) {
3146 ret
= visit_field_class_def(ctx
, node
->u
.field_class_def
.field_class_specifier_list
,
3147 &node
->u
.field_class_def
.field_class_declarators
);
3149 _BT_COMP_LOGE_NODE(node
,
3150 "Cannot add field class found in event class.");
3154 case NODE_TYPEALIAS
:
3155 ret
= visit_field_class_alias(ctx
, node
->u
.field_class_alias
.target
,
3156 node
->u
.field_class_alias
.alias
);
3158 _BT_COMP_LOGE_NODE(node
,
3159 "Cannot add field class alias found in event class.");
3163 case NODE_CTF_EXPRESSION
:
3165 left
= concatenate_unary_strings(&node
->u
.ctf_expression
.left
);
3167 _BT_COMP_LOGE_NODE(node
, "Cannot concatenate unary strings.");
3172 if (strcmp(left
, "name") == 0) {
3173 /* This is already known at this stage */
3174 if (_IS_SET(set
, _EVENT_NAME_SET
)) {
3175 _BT_COMP_LOGE_DUP_ATTR(node
, "name", "event class");
3180 _SET(set
, _EVENT_NAME_SET
);
3181 } else if (strcmp(left
, "id") == 0) {
3184 if (_IS_SET(set
, _EVENT_ID_SET
)) {
3185 _BT_COMP_LOGE_DUP_ATTR(node
, "id", "event class");
3190 ret
= get_unary_unsigned(ctx
,
3191 &node
->u
.ctf_expression
.right
,
3193 /* Only read "id" if get_unary_unsigned() succeeded. */
3194 if (ret
|| (!ret
&& id
< 0)) {
3195 _BT_COMP_LOGE_NODE(node
,
3196 "Unexpected unary expression for event class's `id` attribute.");
3201 event_class
->id
= id
;
3202 _SET(set
, _EVENT_ID_SET
);
3203 } else if (strcmp(left
, "stream_id") == 0) {
3204 if (_IS_SET(set
, _EVENT_STREAM_ID_SET
)) {
3205 _BT_COMP_LOGE_DUP_ATTR(node
, "stream_id",
3211 ret
= get_unary_unsigned(ctx
,
3212 &node
->u
.ctf_expression
.right
, stream_id
);
3215 * Only read "stream_id" if get_unary_unsigned()
3219 _BT_COMP_LOGE_NODE(node
,
3220 "Unexpected unary expression for event class's `stream_id` attribute.");
3225 _SET(set
, _EVENT_STREAM_ID_SET
);
3226 } else if (strcmp(left
, "context") == 0) {
3227 if (_IS_SET(set
, _EVENT_CONTEXT_SET
)) {
3228 _BT_COMP_LOGE_NODE(node
,
3229 "Duplicate `context` entry in event class.");
3234 ret
= visit_field_class_specifier_list(ctx
,
3235 _BT_LIST_FIRST_ENTRY(
3236 &node
->u
.ctf_expression
.right
,
3237 struct ctf_node
, siblings
),
3238 &event_class
->spec_context_fc
);
3240 _BT_COMP_LOGE_NODE(node
,
3241 "Cannot create event class's context field class.");
3245 BT_ASSERT(event_class
->spec_context_fc
);
3246 _SET(set
, _EVENT_CONTEXT_SET
);
3247 } else if (strcmp(left
, "fields") == 0) {
3248 if (_IS_SET(set
, _EVENT_FIELDS_SET
)) {
3249 _BT_COMP_LOGE_NODE(node
,
3250 "Duplicate `fields` entry in event class.");
3255 ret
= visit_field_class_specifier_list(ctx
,
3256 _BT_LIST_FIRST_ENTRY(
3257 &node
->u
.ctf_expression
.right
,
3258 struct ctf_node
, siblings
),
3259 &event_class
->payload_fc
);
3261 _BT_COMP_LOGE_NODE(node
,
3262 "Cannot create event class's payload field class.");
3266 BT_ASSERT(event_class
->payload_fc
);
3267 _SET(set
, _EVENT_FIELDS_SET
);
3268 } else if (strcmp(left
, "loglevel") == 0) {
3269 uint64_t loglevel_value
;
3270 bt_event_class_log_level log_level
= -1;
3272 if (_IS_SET(set
, _EVENT_LOG_LEVEL_SET
)) {
3273 _BT_COMP_LOGE_DUP_ATTR(node
, "loglevel",
3279 ret
= get_unary_unsigned(ctx
,
3280 &node
->u
.ctf_expression
.right
, &loglevel_value
);
3282 _BT_COMP_LOGE_NODE(node
,
3283 "Unexpected unary expression for event class's `loglevel` attribute.");
3288 switch (loglevel_value
) {
3290 log_level
= BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY
;
3293 log_level
= BT_EVENT_CLASS_LOG_LEVEL_ALERT
;
3296 log_level
= BT_EVENT_CLASS_LOG_LEVEL_CRITICAL
;
3299 log_level
= BT_EVENT_CLASS_LOG_LEVEL_ERROR
;
3302 log_level
= BT_EVENT_CLASS_LOG_LEVEL_WARNING
;
3305 log_level
= BT_EVENT_CLASS_LOG_LEVEL_NOTICE
;
3308 log_level
= BT_EVENT_CLASS_LOG_LEVEL_INFO
;
3311 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM
;
3314 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM
;
3317 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS
;
3320 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE
;
3323 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT
;
3326 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION
;
3329 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE
;
3332 log_level
= BT_EVENT_CLASS_LOG_LEVEL_DEBUG
;
3335 _BT_COMP_LOGW_NODE(node
, "Not setting event class's log level because its value is unknown: "
3336 "log-level=%" PRIu64
, loglevel_value
);
3339 if (log_level
!= -1) {
3340 event_class
->log_level
= log_level
;
3343 _SET(set
, _EVENT_LOG_LEVEL_SET
);
3344 } else if (strcmp(left
, "model.emf.uri") == 0) {
3347 if (_IS_SET(set
, _EVENT_MODEL_EMF_URI_SET
)) {
3348 _BT_COMP_LOGE_DUP_ATTR(node
, "model.emf.uri",
3354 right
= concatenate_unary_strings(
3355 &node
->u
.ctf_expression
.right
);
3357 _BT_COMP_LOGE_NODE(node
,
3358 "Unexpected unary expression for event class's `model.emf.uri` attribute.");
3363 if (strlen(right
) == 0) {
3364 _BT_COMP_LOGW_NODE(node
,
3365 "Not setting event class's EMF URI because it's empty.");
3367 g_string_assign(event_class
->emf_uri
,
3372 _SET(set
, _EVENT_MODEL_EMF_URI_SET
);
3374 _BT_COMP_LOGW_NODE(node
,
3375 "Unknown attribute in event class: "
3376 "attr-name=\"%s\"", left
);
3398 char *get_event_decl_name(struct ctx
*ctx
, struct ctf_node
*node
)
3402 struct ctf_node
*iter
;
3403 struct bt_list_head
*decl_list
= &node
->u
.event
.declaration_list
;
3405 bt_list_for_each_entry(iter
, decl_list
, siblings
) {
3406 if (iter
->type
!= NODE_CTF_EXPRESSION
) {
3410 left
= concatenate_unary_strings(&iter
->u
.ctf_expression
.left
);
3412 _BT_COMP_LOGE_NODE(iter
,
3413 "Cannot concatenate unary strings.");
3417 if (strcmp(left
, "name") == 0) {
3418 name
= concatenate_unary_strings(
3419 &iter
->u
.ctf_expression
.right
);
3421 _BT_COMP_LOGE_NODE(iter
,
3422 "Unexpected unary expression for event class's `name` attribute.");
3443 int visit_event_decl(struct ctx
*ctx
, struct ctf_node
*node
)
3447 struct ctf_node
*iter
;
3448 uint64_t stream_id
= 0;
3449 char *event_name
= NULL
;
3450 struct ctf_event_class
*event_class
= NULL
;
3451 struct ctf_stream_class
*stream_class
= NULL
;
3452 struct bt_list_head
*decl_list
= &node
->u
.event
.declaration_list
;
3453 bool pop_scope
= false;
3455 if (node
->visited
) {
3459 node
->visited
= TRUE
;
3460 event_name
= get_event_decl_name(ctx
, node
);
3462 _BT_COMP_LOGE_NODE(node
,
3463 "Missing `name` attribute in event class.");
3468 event_class
= ctf_event_class_create();
3469 BT_ASSERT(event_class
);
3470 g_string_assign(event_class
->name
, event_name
);
3471 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
3474 bt_list_for_each_entry(iter
, decl_list
, siblings
) {
3475 ret
= visit_event_decl_entry(ctx
, iter
, event_class
,
3478 _BT_COMP_LOGE_NODE(iter
, "Cannot visit event class's entry: "
3484 if (!_IS_SET(&set
, _EVENT_STREAM_ID_SET
)) {
3486 * Allow missing stream_id if there is only a single
3489 switch (ctx
->ctf_tc
->stream_classes
->len
) {
3491 /* Create implicit stream class if there's none */
3493 stream_class
= ctf_stream_class_create();
3494 BT_ASSERT(stream_class
);
3495 stream_class
->id
= stream_id
;
3496 g_ptr_array_add(ctx
->ctf_tc
->stream_classes
,
3500 /* Single stream class: get its ID */
3501 stream_class
= ctx
->ctf_tc
->stream_classes
->pdata
[0];
3502 stream_id
= stream_class
->id
;
3505 _BT_COMP_LOGE_NODE(node
,
3506 "Missing `stream_id` attribute in event class.");
3512 /* We have the stream ID now; get the stream class if found */
3513 if (!stream_class
) {
3514 stream_class
= ctf_trace_class_borrow_stream_class_by_id(
3515 ctx
->ctf_tc
, stream_id
);
3516 if (!stream_class
) {
3517 _BT_COMP_LOGE_NODE(node
,
3518 "Cannot find stream class at this point: "
3519 "id=%" PRId64
, stream_id
);
3525 BT_ASSERT(stream_class
);
3527 if (!_IS_SET(&set
, _EVENT_ID_SET
)) {
3528 /* Allow only one event without ID per stream */
3529 if (stream_class
->event_classes
->len
!= 0) {
3530 _BT_COMP_LOGE_NODE(node
,
3531 "Missing `id` attribute in event class.");
3537 event_class
->id
= 0;
3540 if (ctf_stream_class_borrow_event_class_by_id(stream_class
,
3542 _BT_COMP_LOGE_NODE(node
,
3543 "Duplicate event class (same ID) in the same stream class: "
3544 "id=%" PRId64
, event_class
->id
);
3549 ctf_stream_class_append_event_class(stream_class
, event_class
);
3554 ctf_event_class_destroy(event_class
);
3572 int auto_map_field_to_trace_clock_class(struct ctx
*ctx
,
3573 struct ctf_field_class
*fc
)
3575 struct ctf_clock_class
*clock_class_to_map_to
= NULL
;
3576 struct ctf_field_class_int
*int_fc
= (void *) fc
;
3578 uint64_t clock_class_count
;
3584 if (fc
->type
!= CTF_FIELD_CLASS_TYPE_INT
&&
3585 fc
->type
!= CTF_FIELD_CLASS_TYPE_ENUM
) {
3589 if (int_fc
->mapped_clock_class
) {
3590 /* Already mapped */
3594 clock_class_count
= ctx
->ctf_tc
->clock_classes
->len
;
3596 switch (clock_class_count
) {
3599 * No clock class exists in the trace at this point. Create an
3600 * implicit one at 1 GHz, named `default`, and use this clock
3603 clock_class_to_map_to
= ctf_clock_class_create();
3604 BT_ASSERT(clock_class_to_map_to
);
3605 clock_class_to_map_to
->frequency
= UINT64_C(1000000000);
3606 g_string_assign(clock_class_to_map_to
->name
, "default");
3607 BT_ASSERT(ret
== 0);
3608 g_ptr_array_add(ctx
->ctf_tc
->clock_classes
,
3609 clock_class_to_map_to
);
3613 * Only one clock class exists in the trace at this point: use
3616 clock_class_to_map_to
= ctx
->ctf_tc
->clock_classes
->pdata
[0];
3620 * Timestamp field not mapped to a clock class and there's more
3621 * than one clock class in the trace: this is an error.
3623 BT_COMP_LOGE_STR("Timestamp field found with no mapped clock class, "
3624 "but there's more than one clock class in the trace at this point.");
3629 BT_ASSERT(clock_class_to_map_to
);
3630 int_fc
->mapped_clock_class
= clock_class_to_map_to
;
3637 int auto_map_fields_to_trace_clock_class(struct ctx
*ctx
,
3638 struct ctf_field_class
*root_fc
, const char *field_name
)
3642 struct ctf_field_class_struct
*struct_fc
= (void *) root_fc
;
3643 struct ctf_field_class_variant
*var_fc
= (void *) root_fc
;
3649 if (root_fc
->type
!= CTF_FIELD_CLASS_TYPE_STRUCT
&&
3650 root_fc
->type
!= CTF_FIELD_CLASS_TYPE_VARIANT
) {
3654 if (root_fc
->type
== CTF_FIELD_CLASS_TYPE_STRUCT
) {
3655 count
= struct_fc
->members
->len
;
3657 count
= var_fc
->options
->len
;
3660 for (i
= 0; i
< count
; i
++) {
3661 struct ctf_named_field_class
*named_fc
= NULL
;
3663 if (root_fc
->type
== CTF_FIELD_CLASS_TYPE_STRUCT
) {
3664 named_fc
= ctf_field_class_struct_borrow_member_by_index(
3666 } else if (root_fc
->type
== CTF_FIELD_CLASS_TYPE_VARIANT
) {
3667 named_fc
= ctf_field_class_variant_borrow_option_by_index(
3671 if (strcmp(named_fc
->name
->str
, field_name
) == 0) {
3672 ret
= auto_map_field_to_trace_clock_class(ctx
,
3675 BT_COMP_LOGE("Cannot automatically map field to trace's clock class: "
3676 "field-name=\"%s\"", field_name
);
3681 ret
= auto_map_fields_to_trace_clock_class(ctx
, named_fc
->fc
,
3684 BT_COMP_LOGE("Cannot automatically map structure or variant field class's fields to trace's clock class: "
3685 "field-name=\"%s\", root-field-name=\"%s\"",
3686 field_name
, named_fc
->name
->str
);
3696 int visit_stream_decl_entry(struct ctx
*ctx
, struct ctf_node
*node
,
3697 struct ctf_stream_class
*stream_class
, int *set
)
3702 switch (node
->type
) {
3704 ret
= visit_field_class_def(ctx
, node
->u
.field_class_def
.field_class_specifier_list
,
3705 &node
->u
.field_class_def
.field_class_declarators
);
3707 _BT_COMP_LOGE_NODE(node
,
3708 "Cannot add field class found in stream class.");
3712 case NODE_TYPEALIAS
:
3713 ret
= visit_field_class_alias(ctx
, node
->u
.field_class_alias
.target
,
3714 node
->u
.field_class_alias
.alias
);
3716 _BT_COMP_LOGE_NODE(node
,
3717 "Cannot add field class alias found in stream class.");
3721 case NODE_CTF_EXPRESSION
:
3723 left
= concatenate_unary_strings(&node
->u
.ctf_expression
.left
);
3725 _BT_COMP_LOGE_NODE(node
, "Cannot concatenate unary strings.");
3730 if (strcmp(left
, "id") == 0) {
3733 if (_IS_SET(set
, _STREAM_ID_SET
)) {
3734 _BT_COMP_LOGE_DUP_ATTR(node
, "id",
3735 "stream declaration");
3740 ret
= get_unary_unsigned(ctx
,
3741 &node
->u
.ctf_expression
.right
,
3744 /* Only read "id" if get_unary_unsigned() succeeded. */
3745 if (ret
|| (!ret
&& id
< 0)) {
3746 _BT_COMP_LOGE_NODE(node
,
3747 "Unexpected unary expression for stream class's `id` attribute.");
3752 if (ctf_trace_class_borrow_stream_class_by_id(
3754 _BT_COMP_LOGE_NODE(node
,
3755 "Duplicate stream class (same ID): id=%" PRId64
,
3761 stream_class
->id
= id
;
3762 _SET(set
, _STREAM_ID_SET
);
3763 } else if (strcmp(left
, "event.header") == 0) {
3764 if (_IS_SET(set
, _STREAM_EVENT_HEADER_SET
)) {
3765 _BT_COMP_LOGE_NODE(node
,
3766 "Duplicate `event.header` entry in stream class.");
3771 ret
= visit_field_class_specifier_list(ctx
,
3772 _BT_LIST_FIRST_ENTRY(
3773 &node
->u
.ctf_expression
.right
,
3774 struct ctf_node
, siblings
),
3775 &stream_class
->event_header_fc
);
3777 _BT_COMP_LOGE_NODE(node
,
3778 "Cannot create stream class's event header field class.");
3782 BT_ASSERT(stream_class
->event_header_fc
);
3783 ret
= auto_map_fields_to_trace_clock_class(ctx
,
3784 stream_class
->event_header_fc
, "timestamp");
3786 _BT_COMP_LOGE_NODE(node
,
3787 "Cannot automatically map specific event header field class fields named `timestamp` to trace's clock class.");
3791 _SET(set
, _STREAM_EVENT_HEADER_SET
);
3792 } else if (strcmp(left
, "event.context") == 0) {
3793 if (_IS_SET(set
, _STREAM_EVENT_CONTEXT_SET
)) {
3794 _BT_COMP_LOGE_NODE(node
,
3795 "Duplicate `event.context` entry in stream class.");
3800 ret
= visit_field_class_specifier_list(ctx
,
3801 _BT_LIST_FIRST_ENTRY(
3802 &node
->u
.ctf_expression
.right
,
3803 struct ctf_node
, siblings
),
3804 &stream_class
->event_common_context_fc
);
3806 _BT_COMP_LOGE_NODE(node
,
3807 "Cannot create stream class's event context field class.");
3811 BT_ASSERT(stream_class
->event_common_context_fc
);
3812 _SET(set
, _STREAM_EVENT_CONTEXT_SET
);
3813 } else if (strcmp(left
, "packet.context") == 0) {
3814 if (_IS_SET(set
, _STREAM_PACKET_CONTEXT_SET
)) {
3815 _BT_COMP_LOGE_NODE(node
,
3816 "Duplicate `packet.context` entry in stream class.");
3821 ret
= visit_field_class_specifier_list(ctx
,
3822 _BT_LIST_FIRST_ENTRY(
3823 &node
->u
.ctf_expression
.right
,
3824 struct ctf_node
, siblings
),
3825 &stream_class
->packet_context_fc
);
3827 _BT_COMP_LOGE_NODE(node
,
3828 "Cannot create stream class's packet context field class.");
3832 BT_ASSERT(stream_class
->packet_context_fc
);
3833 ret
= auto_map_fields_to_trace_clock_class(ctx
,
3834 stream_class
->packet_context_fc
,
3837 _BT_COMP_LOGE_NODE(node
,
3838 "Cannot automatically map specific packet context field class fields named `timestamp_begin` to trace's clock class.");
3842 ret
= auto_map_fields_to_trace_clock_class(ctx
,
3843 stream_class
->packet_context_fc
,
3846 _BT_COMP_LOGE_NODE(node
,
3847 "Cannot automatically map specific packet context field class fields named `timestamp_end` to trace's clock class.");
3851 _SET(set
, _STREAM_PACKET_CONTEXT_SET
);
3853 _BT_COMP_LOGW_NODE(node
,
3854 "Unknown attribute in stream class: "
3855 "attr-name=\"%s\"", left
);
3876 int visit_stream_decl(struct ctx
*ctx
, struct ctf_node
*node
)
3880 struct ctf_node
*iter
;
3881 struct ctf_stream_class
*stream_class
= NULL
;
3882 struct bt_list_head
*decl_list
= &node
->u
.stream
.declaration_list
;
3884 if (node
->visited
) {
3888 node
->visited
= TRUE
;
3889 stream_class
= ctf_stream_class_create();
3890 BT_ASSERT(stream_class
);
3891 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
3893 bt_list_for_each_entry(iter
, decl_list
, siblings
) {
3894 ret
= visit_stream_decl_entry(ctx
, iter
, stream_class
, &set
);
3896 _BT_COMP_LOGE_NODE(iter
,
3897 "Cannot visit stream class's entry: "
3906 if (_IS_SET(&set
, _STREAM_ID_SET
)) {
3907 /* Check that packet header has `stream_id` field */
3908 struct ctf_named_field_class
*named_fc
= NULL
;
3910 if (!ctx
->ctf_tc
->packet_header_fc
) {
3911 _BT_COMP_LOGE_NODE(node
,
3912 "Stream class has a `id` attribute, "
3913 "but trace has no packet header field class.");
3917 named_fc
= ctf_field_class_struct_borrow_member_by_name(
3918 (void *) ctx
->ctf_tc
->packet_header_fc
, "stream_id");
3920 _BT_COMP_LOGE_NODE(node
,
3921 "Stream class has a `id` attribute, "
3922 "but trace's packet header field class has no `stream_id` field.");
3926 if (named_fc
->fc
->type
!= CTF_FIELD_CLASS_TYPE_INT
&&
3927 named_fc
->fc
->type
!= CTF_FIELD_CLASS_TYPE_ENUM
) {
3928 _BT_COMP_LOGE_NODE(node
,
3929 "Stream class has a `id` attribute, "
3930 "but trace's packet header field class's `stream_id` field is not an integer field class.");
3934 /* Allow only _one_ ID-less stream */
3935 if (ctx
->ctf_tc
->stream_classes
->len
!= 0) {
3936 _BT_COMP_LOGE_NODE(node
,
3937 "Missing `id` attribute in stream class as there's more than one stream class in the trace.");
3942 /* Automatic ID: 0 */
3943 stream_class
->id
= 0;
3947 * Make sure that this stream class's ID is currently unique in
3950 if (ctf_trace_class_borrow_stream_class_by_id(ctx
->ctf_tc
,
3951 stream_class
->id
)) {
3952 _BT_COMP_LOGE_NODE(node
,
3953 "Duplicate stream class (same ID): id=%" PRId64
,
3959 g_ptr_array_add(ctx
->ctf_tc
->stream_classes
, stream_class
);
3960 stream_class
= NULL
;
3964 ctf_stream_class_destroy(stream_class
);
3965 stream_class
= NULL
;
3972 int visit_trace_decl_entry(struct ctx
*ctx
, struct ctf_node
*node
, int *set
)
3978 switch (node
->type
) {
3980 ret
= visit_field_class_def(ctx
, node
->u
.field_class_def
.field_class_specifier_list
,
3981 &node
->u
.field_class_def
.field_class_declarators
);
3983 _BT_COMP_LOGE_NODE(node
,
3984 "Cannot add field class found in trace (`trace` block).");
3988 case NODE_TYPEALIAS
:
3989 ret
= visit_field_class_alias(ctx
, node
->u
.field_class_alias
.target
,
3990 node
->u
.field_class_alias
.alias
);
3992 _BT_COMP_LOGE_NODE(node
,
3993 "Cannot add field class alias found in trace (`trace` block).");
3997 case NODE_CTF_EXPRESSION
:
3999 left
= concatenate_unary_strings(&node
->u
.ctf_expression
.left
);
4001 _BT_COMP_LOGE_NODE(node
, "Cannot concatenate unary strings.");
4006 if (strcmp(left
, "major") == 0) {
4007 if (_IS_SET(set
, _TRACE_MAJOR_SET
)) {
4008 _BT_COMP_LOGE_DUP_ATTR(node
, "major", "trace");
4013 ret
= get_unary_unsigned(ctx
,
4014 &node
->u
.ctf_expression
.right
, &val
);
4016 _BT_COMP_LOGE_NODE(node
,
4017 "Unexpected unary expression for trace's `major` attribute.");
4023 _BT_COMP_LOGE_NODE(node
,
4024 "Invalid trace's `minor` attribute: expecting 1.");
4028 ctx
->ctf_tc
->major
= val
;
4029 _SET(set
, _TRACE_MAJOR_SET
);
4030 } else if (strcmp(left
, "minor") == 0) {
4031 if (_IS_SET(set
, _TRACE_MINOR_SET
)) {
4032 _BT_COMP_LOGE_DUP_ATTR(node
, "minor", "trace");
4037 ret
= get_unary_unsigned(ctx
,
4038 &node
->u
.ctf_expression
.right
, &val
);
4040 _BT_COMP_LOGE_NODE(node
,
4041 "Unexpected unary expression for trace's `minor` attribute.");
4047 _BT_COMP_LOGE_NODE(node
,
4048 "Invalid trace's `minor` attribute: expecting 8.");
4052 ctx
->ctf_tc
->minor
= val
;
4053 _SET(set
, _TRACE_MINOR_SET
);
4054 } else if (strcmp(left
, "uuid") == 0) {
4055 if (_IS_SET(set
, _TRACE_UUID_SET
)) {
4056 _BT_COMP_LOGE_DUP_ATTR(node
, "uuid", "trace");
4061 ret
= get_unary_uuid(ctx
,
4062 &node
->u
.ctf_expression
.right
,
4065 _BT_COMP_LOGE_NODE(node
,
4066 "Invalid trace's `uuid` attribute.");
4070 ctx
->ctf_tc
->is_uuid_set
= true;
4071 _SET(set
, _TRACE_UUID_SET
);
4072 } else if (strcmp(left
, "byte_order") == 0) {
4073 /* Default byte order is already known at this stage */
4074 if (_IS_SET(set
, _TRACE_BYTE_ORDER_SET
)) {
4075 _BT_COMP_LOGE_DUP_ATTR(node
, "byte_order",
4081 BT_ASSERT(ctx
->ctf_tc
->default_byte_order
!= -1);
4082 _SET(set
, _TRACE_BYTE_ORDER_SET
);
4083 } else if (strcmp(left
, "packet.header") == 0) {
4084 if (_IS_SET(set
, _TRACE_PACKET_HEADER_SET
)) {
4085 _BT_COMP_LOGE_NODE(node
,
4086 "Duplicate `packet.header` entry in trace.");
4091 ret
= visit_field_class_specifier_list(ctx
,
4092 _BT_LIST_FIRST_ENTRY(
4093 &node
->u
.ctf_expression
.right
,
4094 struct ctf_node
, siblings
),
4095 &ctx
->ctf_tc
->packet_header_fc
);
4097 _BT_COMP_LOGE_NODE(node
,
4098 "Cannot create trace's packet header field class.");
4102 BT_ASSERT(ctx
->ctf_tc
->packet_header_fc
);
4103 _SET(set
, _TRACE_PACKET_HEADER_SET
);
4105 _BT_COMP_LOGW_NODE(node
,
4106 "Unknown attribute in stream class: "
4107 "attr-name=\"%s\"", left
);
4115 _BT_COMP_LOGE_NODE(node
, "Unknown expression in trace.");
4128 int visit_trace_decl(struct ctx
*ctx
, struct ctf_node
*node
)
4132 struct ctf_node
*iter
;
4133 struct bt_list_head
*decl_list
= &node
->u
.trace
.declaration_list
;
4135 if (node
->visited
) {
4139 node
->visited
= TRUE
;
4141 if (ctx
->is_trace_visited
) {
4142 _BT_COMP_LOGE_NODE(node
, "Duplicate trace (`trace` block).");
4147 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
4149 bt_list_for_each_entry(iter
, decl_list
, siblings
) {
4150 ret
= visit_trace_decl_entry(ctx
, iter
, &set
);
4152 _BT_COMP_LOGE_NODE(iter
, "Cannot visit trace's entry (`trace` block): "
4161 if (!_IS_SET(&set
, _TRACE_MAJOR_SET
)) {
4162 _BT_COMP_LOGE_NODE(node
,
4163 "Missing `major` attribute in trace (`trace` block).");
4168 if (!_IS_SET(&set
, _TRACE_MINOR_SET
)) {
4169 _BT_COMP_LOGE_NODE(node
,
4170 "Missing `minor` attribute in trace (`trace` block).");
4175 if (!_IS_SET(&set
, _TRACE_BYTE_ORDER_SET
)) {
4176 _BT_COMP_LOGE_NODE(node
,
4177 "Missing `byte_order` attribute in trace (`trace` block).");
4182 ctx
->is_trace_visited
= true;
4192 int visit_env(struct ctx
*ctx
, struct ctf_node
*node
)
4196 struct ctf_node
*entry_node
;
4197 struct bt_list_head
*decl_list
= &node
->u
.env
.declaration_list
;
4199 if (node
->visited
) {
4203 node
->visited
= TRUE
;
4205 bt_list_for_each_entry(entry_node
, decl_list
, siblings
) {
4206 struct bt_list_head
*right_head
=
4207 &entry_node
->u
.ctf_expression
.right
;
4209 if (entry_node
->type
!= NODE_CTF_EXPRESSION
) {
4210 _BT_COMP_LOGE_NODE(entry_node
,
4211 "Wrong expression in environment entry: "
4212 "node-type=%d", entry_node
->type
);
4217 left
= concatenate_unary_strings(
4218 &entry_node
->u
.ctf_expression
.left
);
4220 _BT_COMP_LOGE_NODE(entry_node
,
4221 "Cannot get environment entry's name.");
4226 if (is_unary_string(right_head
)) {
4227 char *right
= concatenate_unary_strings(right_head
);
4230 _BT_COMP_LOGE_NODE(entry_node
,
4231 "Unexpected unary expression for environment entry's value: "
4232 "name=\"%s\"", left
);
4237 if (strcmp(left
, "tracer_name") == 0) {
4238 if (strncmp(right
, "lttng", 5) == 0) {
4239 BT_COMP_LOGI("Detected LTTng trace from `%s` environment value: "
4240 "tracer-name=\"%s\"",
4242 ctx
->is_lttng
= true;
4246 ctf_trace_class_append_env_entry(ctx
->ctf_tc
,
4247 left
, CTF_TRACE_CLASS_ENV_ENTRY_TYPE_STR
,
4250 } else if (is_unary_unsigned(right_head
) ||
4251 is_unary_signed(right_head
)) {
4254 if (is_unary_unsigned(right_head
)) {
4255 ret
= get_unary_unsigned(ctx
, right_head
,
4258 ret
= get_unary_signed(right_head
, &v
);
4261 _BT_COMP_LOGE_NODE(entry_node
,
4262 "Unexpected unary expression for environment entry's value: "
4263 "name=\"%s\"", left
);
4268 ctf_trace_class_append_env_entry(ctx
->ctf_tc
,
4269 left
, CTF_TRACE_CLASS_ENV_ENTRY_TYPE_INT
,
4272 _BT_COMP_LOGW_NODE(entry_node
,
4273 "Environment entry has unknown type: "
4274 "name=\"%s\"", left
);
4290 int set_trace_byte_order(struct ctx
*ctx
, struct ctf_node
*trace_node
)
4295 struct ctf_node
*node
;
4296 struct bt_list_head
*decl_list
= &trace_node
->u
.trace
.declaration_list
;
4298 bt_list_for_each_entry(node
, decl_list
, siblings
) {
4299 if (node
->type
== NODE_CTF_EXPRESSION
) {
4300 struct ctf_node
*right_node
;
4302 left
= concatenate_unary_strings(
4303 &node
->u
.ctf_expression
.left
);
4305 _BT_COMP_LOGE_NODE(node
,
4306 "Cannot concatenate unary strings.");
4311 if (strcmp(left
, "byte_order") == 0) {
4312 enum ctf_byte_order bo
;
4314 if (_IS_SET(&set
, _TRACE_BYTE_ORDER_SET
)) {
4315 _BT_COMP_LOGE_DUP_ATTR(node
, "byte_order",
4321 _SET(&set
, _TRACE_BYTE_ORDER_SET
);
4322 right_node
= _BT_LIST_FIRST_ENTRY(
4323 &node
->u
.ctf_expression
.right
,
4324 struct ctf_node
, siblings
);
4325 bo
= byte_order_from_unary_expr(ctx
,
4328 _BT_COMP_LOGE_NODE(node
,
4329 "Invalid `byte_order` attribute in trace (`trace` block): "
4330 "expecting `le`, `be`, or `network`.");
4333 } else if (bo
== CTF_BYTE_ORDER_DEFAULT
) {
4334 _BT_COMP_LOGE_NODE(node
,
4335 "Invalid `byte_order` attribute in trace (`trace` block): "
4336 "cannot be set to `native` here.");
4341 ctx
->ctf_tc
->default_byte_order
= bo
;
4349 if (!_IS_SET(&set
, _TRACE_BYTE_ORDER_SET
)) {
4350 _BT_COMP_LOGE_NODE(trace_node
,
4351 "Missing `byte_order` attribute in trace (`trace` block).");
4364 int visit_clock_decl_entry(struct ctx
*ctx
, struct ctf_node
*entry_node
,
4365 struct ctf_clock_class
*clock
, int *set
, int64_t *offset_seconds
,
4366 uint64_t *offset_cycles
)
4371 if (entry_node
->type
!= NODE_CTF_EXPRESSION
) {
4372 _BT_COMP_LOGE_NODE(entry_node
,
4373 "Unexpected node type: node-type=%d",
4379 left
= concatenate_unary_strings(&entry_node
->u
.ctf_expression
.left
);
4381 _BT_COMP_LOGE_NODE(entry_node
, "Cannot concatenate unary strings.");
4386 if (strcmp(left
, "name") == 0) {
4389 if (_IS_SET(set
, _CLOCK_NAME_SET
)) {
4390 _BT_COMP_LOGE_DUP_ATTR(entry_node
, "name", "clock class");
4395 right
= concatenate_unary_strings(
4396 &entry_node
->u
.ctf_expression
.right
);
4398 _BT_COMP_LOGE_NODE(entry_node
,
4399 "Unexpected unary expression for clock class's `name` attribute.");
4404 g_string_assign(clock
->name
, right
);
4406 _SET(set
, _CLOCK_NAME_SET
);
4407 } else if (strcmp(left
, "uuid") == 0) {
4410 if (_IS_SET(set
, _CLOCK_UUID_SET
)) {
4411 _BT_COMP_LOGE_DUP_ATTR(entry_node
, "uuid", "clock class");
4416 ret
= get_unary_uuid(ctx
, &entry_node
->u
.ctf_expression
.right
,
4419 _BT_COMP_LOGE_NODE(entry_node
,
4420 "Invalid clock class's `uuid` attribute.");
4424 clock
->has_uuid
= true;
4425 bt_uuid_copy(clock
->uuid
, uuid
);
4426 _SET(set
, _CLOCK_UUID_SET
);
4427 } else if (strcmp(left
, "description") == 0) {
4430 if (_IS_SET(set
, _CLOCK_DESCRIPTION_SET
)) {
4431 _BT_COMP_LOGE_DUP_ATTR(entry_node
, "description",
4437 right
= concatenate_unary_strings(
4438 &entry_node
->u
.ctf_expression
.right
);
4440 _BT_COMP_LOGE_NODE(entry_node
,
4441 "Unexpected unary expression for clock class's `description` attribute.");
4446 g_string_assign(clock
->description
, right
);
4448 _SET(set
, _CLOCK_DESCRIPTION_SET
);
4449 } else if (strcmp(left
, "freq") == 0) {
4450 uint64_t freq
= UINT64_C(-1);
4452 if (_IS_SET(set
, _CLOCK_FREQ_SET
)) {
4453 _BT_COMP_LOGE_DUP_ATTR(entry_node
, "freq", "clock class");
4458 ret
= get_unary_unsigned(ctx
,
4459 &entry_node
->u
.ctf_expression
.right
, &freq
);
4461 _BT_COMP_LOGE_NODE(entry_node
,
4462 "Unexpected unary expression for clock class's `freq` attribute.");
4467 if (freq
== UINT64_C(-1) || freq
== 0) {
4468 _BT_COMP_LOGE_NODE(entry_node
,
4469 "Invalid clock class frequency: freq=%" PRIu64
,
4475 clock
->frequency
= freq
;
4476 _SET(set
, _CLOCK_FREQ_SET
);
4477 } else if (strcmp(left
, "precision") == 0) {
4480 if (_IS_SET(set
, _CLOCK_PRECISION_SET
)) {
4481 _BT_COMP_LOGE_DUP_ATTR(entry_node
, "precision",
4487 ret
= get_unary_unsigned(ctx
,
4488 &entry_node
->u
.ctf_expression
.right
, &precision
);
4490 _BT_COMP_LOGE_NODE(entry_node
,
4491 "Unexpected unary expression for clock class's `precision` attribute.");
4496 clock
->precision
= precision
;
4497 _SET(set
, _CLOCK_PRECISION_SET
);
4498 } else if (strcmp(left
, "offset_s") == 0) {
4499 if (_IS_SET(set
, _CLOCK_OFFSET_S_SET
)) {
4500 _BT_COMP_LOGE_DUP_ATTR(entry_node
, "offset_s",
4506 ret
= get_unary_signed(
4507 &entry_node
->u
.ctf_expression
.right
, offset_seconds
);
4509 _BT_COMP_LOGE_NODE(entry_node
,
4510 "Unexpected unary expression for clock class's `offset_s` attribute.");
4515 _SET(set
, _CLOCK_OFFSET_S_SET
);
4516 } else if (strcmp(left
, "offset") == 0) {
4517 if (_IS_SET(set
, _CLOCK_OFFSET_SET
)) {
4518 _BT_COMP_LOGE_DUP_ATTR(entry_node
, "offset", "clock class");
4523 ret
= get_unary_unsigned(ctx
,
4524 &entry_node
->u
.ctf_expression
.right
, offset_cycles
);
4526 _BT_COMP_LOGE_NODE(entry_node
,
4527 "Unexpected unary expression for clock class's `offset` attribute.");
4532 _SET(set
, _CLOCK_OFFSET_SET
);
4533 } else if (strcmp(left
, "absolute") == 0) {
4534 struct ctf_node
*right
;
4536 if (_IS_SET(set
, _CLOCK_ABSOLUTE_SET
)) {
4537 _BT_COMP_LOGE_DUP_ATTR(entry_node
, "absolute",
4543 right
= _BT_LIST_FIRST_ENTRY(
4544 &entry_node
->u
.ctf_expression
.right
,
4545 struct ctf_node
, siblings
);
4546 ret
= get_boolean(ctx
, right
);
4548 _BT_COMP_LOGE_NODE(entry_node
,
4549 "Unexpected unary expression for clock class's `absolute` attribute.");
4554 clock
->is_absolute
= ret
;
4555 _SET(set
, _CLOCK_ABSOLUTE_SET
);
4557 _BT_COMP_LOGW_NODE(entry_node
,
4558 "Unknown attribute in clock class: attr-name=\"%s\"",
4572 uint64_t cycles_from_ns(uint64_t frequency
, uint64_t ns
)
4577 if (frequency
== UINT64_C(1000000000)) {
4580 cycles
= (uint64_t) (((double) ns
* (double) frequency
) / 1e9
);
4587 void calibrate_clock_class_offsets(int64_t *offset_seconds
,
4588 uint64_t *offset_cycles
, uint64_t freq
)
4590 if (*offset_cycles
>= freq
) {
4591 const uint64_t s_in_offset_cycles
= *offset_cycles
/ freq
;
4593 *offset_seconds
+= (int64_t) s_in_offset_cycles
;
4594 *offset_cycles
-= (s_in_offset_cycles
* freq
);
4599 void apply_clock_class_offset(struct ctx
*ctx
,
4600 struct ctf_clock_class
*clock
)
4603 int64_t offset_s_to_apply
= ctx
->decoder_config
.clock_class_offset_s
;
4604 uint64_t offset_ns_to_apply
;
4605 int64_t cur_offset_s
;
4606 uint64_t cur_offset_cycles
;
4608 if (ctx
->decoder_config
.clock_class_offset_s
== 0 &&
4609 ctx
->decoder_config
.clock_class_offset_ns
== 0) {
4613 /* Transfer nanoseconds to seconds as much as possible */
4614 if (ctx
->decoder_config
.clock_class_offset_ns
< 0) {
4615 const int64_t abs_ns
= -ctx
->decoder_config
.clock_class_offset_ns
;
4616 const int64_t abs_extra_s
= abs_ns
/ INT64_C(1000000000) + 1;
4617 const int64_t extra_s
= -abs_extra_s
;
4618 const int64_t offset_ns
= ctx
->decoder_config
.clock_class_offset_ns
-
4619 (extra_s
* INT64_C(1000000000));
4621 BT_ASSERT(offset_ns
> 0);
4622 offset_ns_to_apply
= (uint64_t) offset_ns
;
4623 offset_s_to_apply
+= extra_s
;
4625 const int64_t extra_s
= ctx
->decoder_config
.clock_class_offset_ns
/
4626 INT64_C(1000000000);
4627 const int64_t offset_ns
= ctx
->decoder_config
.clock_class_offset_ns
-
4628 (extra_s
* INT64_C(1000000000));
4630 BT_ASSERT(offset_ns
>= 0);
4631 offset_ns_to_apply
= (uint64_t) offset_ns
;
4632 offset_s_to_apply
+= extra_s
;
4635 freq
= clock
->frequency
;
4636 cur_offset_s
= clock
->offset_seconds
;
4637 cur_offset_cycles
= clock
->offset_cycles
;
4640 cur_offset_s
+= offset_s_to_apply
;
4641 cur_offset_cycles
+= cycles_from_ns(freq
, offset_ns_to_apply
);
4644 * Recalibrate offsets because the part in cycles can be greater
4645 * than the frequency at this point.
4647 calibrate_clock_class_offsets(&cur_offset_s
, &cur_offset_cycles
, freq
);
4649 /* Set final offsets */
4650 clock
->offset_seconds
= cur_offset_s
;
4651 clock
->offset_cycles
= cur_offset_cycles
;
4658 int visit_clock_decl(struct ctx
*ctx
, struct ctf_node
*clock_node
)
4662 struct ctf_clock_class
*clock
;
4663 struct ctf_node
*entry_node
;
4664 struct bt_list_head
*decl_list
= &clock_node
->u
.clock
.declaration_list
;
4665 const char *clock_class_name
;
4666 int64_t offset_seconds
= 0;
4667 uint64_t offset_cycles
= 0;
4670 if (clock_node
->visited
) {
4674 clock_node
->visited
= TRUE
;
4676 /* CTF 1.8's default frequency for a clock class is 1 GHz */
4677 clock
= ctf_clock_class_create();
4679 _BT_COMP_LOGE_NODE(clock_node
,
4680 "Cannot create default clock class.");
4685 bt_list_for_each_entry(entry_node
, decl_list
, siblings
) {
4686 ret
= visit_clock_decl_entry(ctx
, entry_node
, clock
, &set
,
4687 &offset_seconds
, &offset_cycles
);
4689 _BT_COMP_LOGE_NODE(entry_node
,
4690 "Cannot visit clock class's entry: ret=%d",
4696 if (!_IS_SET(&set
, _CLOCK_NAME_SET
)) {
4697 _BT_COMP_LOGE_NODE(clock_node
,
4698 "Missing `name` attribute in clock class.");
4703 clock_class_name
= clock
->name
->str
;
4704 BT_ASSERT(clock_class_name
);
4705 if (ctx
->is_lttng
&& strcmp(clock_class_name
, "monotonic") == 0) {
4707 * Old versions of LTTng forgot to set its clock class
4708 * as absolute, even if it is. This is important because
4709 * it's a condition to be able to sort messages
4710 * from different sources.
4712 clock
->is_absolute
= true;
4716 * Adjust offsets so that the part in cycles is less than the
4717 * frequency (move to the part in seconds).
4719 freq
= clock
->frequency
;
4720 calibrate_clock_class_offsets(&offset_seconds
, &offset_cycles
, freq
);
4721 BT_ASSERT(offset_cycles
< clock
->frequency
);
4722 clock
->offset_seconds
= offset_seconds
;
4723 clock
->offset_cycles
= offset_cycles
;
4724 apply_clock_class_offset(ctx
, clock
);
4725 g_ptr_array_add(ctx
->ctf_tc
->clock_classes
, clock
);
4730 ctf_clock_class_destroy(clock
);
4737 int visit_root_decl(struct ctx
*ctx
, struct ctf_node
*root_decl_node
)
4741 if (root_decl_node
->visited
) {
4745 root_decl_node
->visited
= TRUE
;
4747 switch (root_decl_node
->type
) {
4749 ret
= visit_field_class_def(ctx
,
4750 root_decl_node
->u
.field_class_def
.field_class_specifier_list
,
4751 &root_decl_node
->u
.field_class_def
.field_class_declarators
);
4753 _BT_COMP_LOGE_NODE(root_decl_node
,
4754 "Cannot add field class found in root scope.");
4758 case NODE_TYPEALIAS
:
4759 ret
= visit_field_class_alias(ctx
, root_decl_node
->u
.field_class_alias
.target
,
4760 root_decl_node
->u
.field_class_alias
.alias
);
4762 _BT_COMP_LOGE_NODE(root_decl_node
,
4763 "Cannot add field class alias found in root scope.");
4767 case NODE_TYPE_SPECIFIER_LIST
:
4769 struct ctf_field_class
*decl
= NULL
;
4772 * Just add the field class specifier to the root
4773 * declaration scope. Put local reference.
4775 ret
= visit_field_class_specifier_list(ctx
, root_decl_node
, &decl
);
4777 _BT_COMP_LOGE_NODE(root_decl_node
,
4778 "Cannot visit root scope's field class: "
4784 ctf_field_class_destroy(decl
);
4789 _BT_COMP_LOGE_NODE(root_decl_node
,
4790 "Unexpected node type: node-type=%d",
4791 root_decl_node
->type
);
4801 struct ctf_visitor_generate_ir
*ctf_visitor_generate_ir_create(
4802 const struct ctf_metadata_decoder_config
*decoder_config
)
4804 struct ctx
*ctx
= NULL
;
4806 /* Create visitor's context */
4807 ctx
= ctx_create(decoder_config
);
4809 BT_COMP_LOGE_STR("Cannot create visitor's context.");
4820 return (void *) ctx
;
4824 void ctf_visitor_generate_ir_destroy(struct ctf_visitor_generate_ir
*visitor
)
4826 ctx_destroy((void *) visitor
);
4830 bt_trace_class
*ctf_visitor_generate_ir_get_ir_trace_class(
4831 struct ctf_visitor_generate_ir
*visitor
)
4833 struct ctx
*ctx
= (void *) visitor
;
4837 if (ctx
->trace_class
) {
4838 bt_trace_class_get_ref(ctx
->trace_class
);
4841 return ctx
->trace_class
;
4845 struct ctf_trace_class
*ctf_visitor_generate_ir_borrow_ctf_trace_class(
4846 struct ctf_visitor_generate_ir
*visitor
)
4848 struct ctx
*ctx
= (void *) visitor
;
4851 BT_ASSERT(ctx
->ctf_tc
);
4856 int ctf_visitor_generate_ir_visit_node(struct ctf_visitor_generate_ir
*visitor
,
4857 struct ctf_node
*node
)
4860 struct ctx
*ctx
= (void *) visitor
;
4862 BT_COMP_LOGI_STR("Visiting metadata's AST to generate CTF IR objects.");
4864 switch (node
->type
) {
4867 struct ctf_node
*iter
;
4868 bool got_trace_decl
= false;
4871 * The first thing we need is the native byte order of
4872 * the trace block, because early class aliases can have
4873 * a `byte_order` attribute set to `native`. If we don't
4874 * have the native byte order yet, and we don't have any
4875 * trace block yet, then fail with EINCOMPLETE.
4877 if (ctx
->ctf_tc
->default_byte_order
== -1) {
4878 bt_list_for_each_entry(iter
, &node
->u
.root
.trace
, siblings
) {
4879 if (got_trace_decl
) {
4880 _BT_COMP_LOGE_NODE(node
,
4881 "Duplicate trace (`trace` block).");
4886 ret
= set_trace_byte_order(ctx
, iter
);
4888 _BT_COMP_LOGE_NODE(node
,
4889 "Cannot set trace's native byte order: "
4894 got_trace_decl
= true;
4897 if (!got_trace_decl
) {
4898 BT_COMP_LOGD_STR("Incomplete AST: need trace (`trace` block).");
4904 BT_ASSERT(ctx
->ctf_tc
->default_byte_order
== CTF_BYTE_ORDER_LITTLE
||
4905 ctx
->ctf_tc
->default_byte_order
== CTF_BYTE_ORDER_BIG
);
4906 BT_ASSERT(ctx
->current_scope
&&
4907 ctx
->current_scope
->parent_scope
== NULL
);
4910 bt_list_for_each_entry(iter
, &node
->u
.root
.env
, siblings
) {
4911 ret
= visit_env(ctx
, iter
);
4913 _BT_COMP_LOGE_NODE(iter
,
4914 "Cannot visit trace's environment (`env` block) entry: "
4920 BT_ASSERT(ctx
->current_scope
&&
4921 ctx
->current_scope
->parent_scope
== NULL
);
4924 * Visit clock blocks.
4926 bt_list_for_each_entry(iter
, &node
->u
.root
.clock
, siblings
) {
4927 ret
= visit_clock_decl(ctx
, iter
);
4929 _BT_COMP_LOGE_NODE(iter
,
4930 "Cannot visit clock class: ret=%d",
4936 BT_ASSERT(ctx
->current_scope
&&
4937 ctx
->current_scope
->parent_scope
== NULL
);
4940 * Visit root declarations next, as they can be used by any
4943 bt_list_for_each_entry(iter
, &node
->u
.root
.declaration_list
,
4945 ret
= visit_root_decl(ctx
, iter
);
4947 _BT_COMP_LOGE_NODE(iter
,
4948 "Cannot visit root entry: ret=%d",
4954 BT_ASSERT(ctx
->current_scope
&&
4955 ctx
->current_scope
->parent_scope
== NULL
);
4957 /* Callsite blocks are not supported */
4958 bt_list_for_each_entry(iter
, &node
->u
.root
.callsite
, siblings
) {
4959 _BT_COMP_LOGW_NODE(iter
,
4960 "\"callsite\" blocks are not supported as of this version.");
4963 BT_ASSERT(ctx
->current_scope
&&
4964 ctx
->current_scope
->parent_scope
== NULL
);
4967 bt_list_for_each_entry(iter
, &node
->u
.root
.trace
, siblings
) {
4968 ret
= visit_trace_decl(ctx
, iter
);
4970 _BT_COMP_LOGE_NODE(iter
,
4971 "Cannot visit trace (`trace` block): "
4977 BT_ASSERT(ctx
->current_scope
&&
4978 ctx
->current_scope
->parent_scope
== NULL
);
4981 bt_list_for_each_entry(iter
, &node
->u
.root
.stream
, siblings
) {
4982 ret
= visit_stream_decl(ctx
, iter
);
4984 _BT_COMP_LOGE_NODE(iter
,
4985 "Cannot visit stream class: ret=%d",
4991 BT_ASSERT(ctx
->current_scope
&&
4992 ctx
->current_scope
->parent_scope
== NULL
);
4995 bt_list_for_each_entry(iter
, &node
->u
.root
.event
, siblings
) {
4996 ret
= visit_event_decl(ctx
, iter
);
4998 _BT_COMP_LOGE_NODE(iter
,
4999 "Cannot visit event class: ret=%d",
5005 BT_ASSERT(ctx
->current_scope
&&
5006 ctx
->current_scope
->parent_scope
== NULL
);
5010 _BT_COMP_LOGE_NODE(node
,
5011 "Unexpected node type: node-type=%d",
5017 /* Update default clock classes */
5018 ret
= ctf_trace_class_update_default_clock_classes(ctx
->ctf_tc
,
5025 /* Update trace class meanings */
5026 ret
= ctf_trace_class_update_meanings(ctx
->ctf_tc
);
5032 /* Update stream class configuration */
5033 ret
= ctf_trace_class_update_stream_class_config(ctx
->ctf_tc
);
5039 /* Update text arrays and sequences */
5040 ret
= ctf_trace_class_update_text_array_sequence(ctx
->ctf_tc
);
5046 /* Resolve sequence lengths and variant tags */
5047 ret
= ctf_trace_class_resolve_field_classes(ctx
->ctf_tc
, &ctx
->log_cfg
);
5053 if (ctx
->trace_class
) {
5055 * Update "in IR" for field classes.
5057 * If we have no IR trace class, then we'll have no way
5058 * to create IR fields anyway, so we leave all the
5059 * `in_ir` members false.
5061 ret
= ctf_trace_class_update_in_ir(ctx
->ctf_tc
);
5068 /* Update saved value indexes */
5069 ret
= ctf_trace_class_update_value_storing_indexes(ctx
->ctf_tc
);
5075 /* Validate what we have so far */
5076 ret
= ctf_trace_class_validate(ctx
->ctf_tc
, &ctx
->log_cfg
);
5083 * If there are fields which are not related to the CTF format
5084 * itself in the packet header and in event header field
5085 * classes, warn about it because they are never translated.
5087 ctf_trace_class_warn_meaningless_header_fields(ctx
->ctf_tc
,
5090 if (ctx
->trace_class
) {
5091 /* Copy new CTF metadata -> new IR metadata */
5092 ret
= ctf_trace_class_translate(ctx
->log_cfg
.self_comp
,
5093 ctx
->trace_class
, ctx
->ctf_tc
);