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