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