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