lib: return `void` when setting a simple value with no side effects
[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_private_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_private_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_private_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 = bt_object_get_ref(mapped_clock_class);
2723 return 0;
2724
2725 error:
2726 ctf_field_class_destroy((void *) *integer_decl);
2727 *integer_decl = NULL;
2728 return ret;
2729 }
2730
2731 static
2732 int visit_floating_point_number_decl(struct ctx *ctx,
2733 struct bt_list_head *expressions,
2734 struct ctf_field_class_float **float_decl)
2735 {
2736 int set = 0;
2737 int ret = 0;
2738 struct ctf_node *expression;
2739 uint64_t alignment = 1, exp_dig = 0, mant_dig = 0;
2740 enum ctf_byte_order byte_order = ctx->ctf_tc->default_byte_order;
2741
2742 *float_decl = NULL;
2743
2744 bt_list_for_each_entry(expression, expressions, siblings) {
2745 struct ctf_node *left, *right;
2746
2747 left = _BT_LIST_FIRST_ENTRY(&expression->u.ctf_expression.left,
2748 struct ctf_node, siblings);
2749 right = _BT_LIST_FIRST_ENTRY(
2750 &expression->u.ctf_expression.right, struct ctf_node,
2751 siblings);
2752
2753 if (left->u.unary_expression.type != UNARY_STRING) {
2754 _BT_LOGE_NODE(left,
2755 "Unexpected unary expression type: type=%d",
2756 left->u.unary_expression.type);
2757 ret = -EINVAL;
2758 goto error;
2759 }
2760
2761 if (!strcmp(left->u.unary_expression.u.string, "byte_order")) {
2762 if (_IS_SET(&set, _FLOAT_BYTE_ORDER_SET)) {
2763 _BT_LOGE_DUP_ATTR(left, "byte_order",
2764 "floating point number field class");
2765 ret = -EPERM;
2766 goto error;
2767 }
2768
2769 byte_order = get_real_byte_order(ctx, right);
2770 if (byte_order == -1) {
2771 _BT_LOGE_NODE(right,
2772 "Invalid `byte_order` attribute in floating point number field class: "
2773 "ret=%d", ret);
2774 ret = -EINVAL;
2775 goto error;
2776 }
2777
2778 _SET(&set, _FLOAT_BYTE_ORDER_SET);
2779 } else if (!strcmp(left->u.unary_expression.u.string,
2780 "exp_dig")) {
2781 if (_IS_SET(&set, _FLOAT_EXP_DIG_SET)) {
2782 _BT_LOGE_DUP_ATTR(left, "exp_dig",
2783 "floating point number field class");
2784 ret = -EPERM;
2785 goto error;
2786 }
2787
2788 if (right->u.unary_expression.type !=
2789 UNARY_UNSIGNED_CONSTANT) {
2790 _BT_LOGE_NODE(right,
2791 "Invalid `exp_dig` attribute in floating point number field class: "
2792 "expecting unsigned constant integer: "
2793 "node-type=%d",
2794 right->u.unary_expression.type);
2795 ret = -EINVAL;
2796 goto error;
2797 }
2798
2799 exp_dig = right->u.unary_expression.u.unsigned_constant;
2800 _SET(&set, _FLOAT_EXP_DIG_SET);
2801 } else if (!strcmp(left->u.unary_expression.u.string,
2802 "mant_dig")) {
2803 if (_IS_SET(&set, _FLOAT_MANT_DIG_SET)) {
2804 _BT_LOGE_DUP_ATTR(left, "mant_dig",
2805 "floating point number field class");
2806 ret = -EPERM;
2807 goto error;
2808 }
2809
2810 if (right->u.unary_expression.type !=
2811 UNARY_UNSIGNED_CONSTANT) {
2812 _BT_LOGE_NODE(right,
2813 "Invalid `mant_dig` attribute in floating point number field class: "
2814 "expecting unsigned constant integer: "
2815 "node-type=%d",
2816 right->u.unary_expression.type);
2817 ret = -EINVAL;
2818 goto error;
2819 }
2820
2821 mant_dig = right->u.unary_expression.u.
2822 unsigned_constant;
2823 _SET(&set, _FLOAT_MANT_DIG_SET);
2824 } else if (!strcmp(left->u.unary_expression.u.string,
2825 "align")) {
2826 if (_IS_SET(&set, _FLOAT_ALIGN_SET)) {
2827 _BT_LOGE_DUP_ATTR(left, "align",
2828 "floating point number field class");
2829 ret = -EPERM;
2830 goto error;
2831 }
2832
2833 if (right->u.unary_expression.type !=
2834 UNARY_UNSIGNED_CONSTANT) {
2835 _BT_LOGE_NODE(right,
2836 "Invalid `align` attribute in floating point number field class: "
2837 "expecting unsigned constant integer: "
2838 "node-type=%d",
2839 right->u.unary_expression.type);
2840 ret = -EINVAL;
2841 goto error;
2842 }
2843
2844 alignment = right->u.unary_expression.u.
2845 unsigned_constant;
2846
2847 if (!is_align_valid(alignment)) {
2848 _BT_LOGE_NODE(right,
2849 "Invalid `align` attribute in floating point number field class: "
2850 "expecting power of two: "
2851 "align=%" PRIu64, alignment);
2852 ret = -EINVAL;
2853 goto error;
2854 }
2855
2856 _SET(&set, _FLOAT_ALIGN_SET);
2857 } else {
2858 _BT_LOGW_NODE(left,
2859 "Unknown attribute in floating point number field class: "
2860 "attr-name=\"%s\"",
2861 left->u.unary_expression.u.string);
2862 }
2863 }
2864
2865 if (!_IS_SET(&set, _FLOAT_MANT_DIG_SET)) {
2866 BT_LOGE_STR("Missing `mant_dig` attribute in floating point number field class.");
2867 ret = -EPERM;
2868 goto error;
2869 }
2870
2871 if (!_IS_SET(&set, _FLOAT_EXP_DIG_SET)) {
2872 BT_LOGE_STR("Missing `exp_dig` attribute in floating point number field class.");
2873 ret = -EPERM;
2874 goto error;
2875 }
2876
2877 if (mant_dig != 24 && mant_dig != 53) {
2878 BT_LOGE_STR("`mant_dig` attribute: expecting 24 or 53.");
2879 ret = -EPERM;
2880 goto error;
2881 }
2882
2883 if (mant_dig == 24 && exp_dig != 8) {
2884 BT_LOGE_STR("`exp_dig` attribute: expecting 8 because `mant_dig` is 24.");
2885 ret = -EPERM;
2886 goto error;
2887 }
2888
2889 if (mant_dig == 53 && exp_dig != 11) {
2890 BT_LOGE_STR("`exp_dig` attribute: expecting 11 because `mant_dig` is 53.");
2891 ret = -EPERM;
2892 goto error;
2893 }
2894
2895 if (!_IS_SET(&set, _INTEGER_ALIGN_SET)) {
2896 if ((mant_dig + exp_dig) % CHAR_BIT) {
2897 /* Bit-packed alignment */
2898 alignment = 1;
2899 } else {
2900 /* Byte-packed alignment */
2901 alignment = CHAR_BIT;
2902 }
2903 }
2904
2905 *float_decl = ctf_field_class_float_create();
2906 BT_ASSERT(*float_decl);
2907 (*float_decl)->base.base.alignment = alignment;
2908 (*float_decl)->base.byte_order = byte_order;
2909 (*float_decl)->base.size = mant_dig + exp_dig;
2910 return 0;
2911
2912 error:
2913 ctf_field_class_destroy((void *) *float_decl);
2914 *float_decl = NULL;
2915 return ret;
2916 }
2917
2918 static
2919 int visit_string_decl(struct ctx *ctx,
2920 struct bt_list_head *expressions,
2921 struct ctf_field_class_string **string_decl)
2922 {
2923 int set = 0;
2924 int ret = 0;
2925 struct ctf_node *expression;
2926 enum ctf_encoding encoding = CTF_ENCODING_UTF8;
2927
2928 *string_decl = NULL;
2929
2930 bt_list_for_each_entry(expression, expressions, siblings) {
2931 struct ctf_node *left, *right;
2932
2933 left = _BT_LIST_FIRST_ENTRY(&expression->u.ctf_expression.left,
2934 struct ctf_node, siblings);
2935 right = _BT_LIST_FIRST_ENTRY(
2936 &expression->u.ctf_expression.right, struct ctf_node,
2937 siblings);
2938
2939 if (left->u.unary_expression.type != UNARY_STRING) {
2940 _BT_LOGE_NODE(left,
2941 "Unexpected unary expression type: type=%d",
2942 left->u.unary_expression.type);
2943 ret = -EINVAL;
2944 goto error;
2945 }
2946
2947 if (!strcmp(left->u.unary_expression.u.string, "encoding")) {
2948 char *s_right;
2949
2950 if (_IS_SET(&set, _STRING_ENCODING_SET)) {
2951 _BT_LOGE_DUP_ATTR(left, "encoding",
2952 "string field class");
2953 ret = -EPERM;
2954 goto error;
2955 }
2956
2957 if (right->u.unary_expression.type != UNARY_STRING) {
2958 _BT_LOGE_NODE(right,
2959 "Invalid `encoding` attribute in string field class: "
2960 "expecting unary string.");
2961 ret = -EINVAL;
2962 goto error;
2963 }
2964
2965 s_right = concatenate_unary_strings(
2966 &expression->u.ctf_expression.right);
2967 if (!s_right) {
2968 _BT_LOGE_NODE(right,
2969 "Unexpected unary expression for string field class's `encoding` attribute.");
2970 ret = -EINVAL;
2971 goto error;
2972 }
2973
2974 if (!strcmp(s_right, "UTF8") ||
2975 !strcmp(s_right, "utf8") ||
2976 !strcmp(s_right, "utf-8") ||
2977 !strcmp(s_right, "UTF-8") ||
2978 !strcmp(s_right, "ASCII") ||
2979 !strcmp(s_right, "ascii")) {
2980 encoding = CTF_ENCODING_UTF8;
2981 } else if (!strcmp(s_right, "none")) {
2982 encoding = CTF_ENCODING_NONE;
2983 } else {
2984 _BT_LOGE_NODE(right,
2985 "Invalid `encoding` attribute in string field class: "
2986 "unknown encoding: encoding=\"%s\"",
2987 s_right);
2988 g_free(s_right);
2989 ret = -EINVAL;
2990 goto error;
2991 }
2992
2993 g_free(s_right);
2994 _SET(&set, _STRING_ENCODING_SET);
2995 } else {
2996 _BT_LOGW_NODE(left,
2997 "Unknown attribute in string field class: "
2998 "attr-name=\"%s\"",
2999 left->u.unary_expression.u.string);
3000 }
3001 }
3002
3003 *string_decl = ctf_field_class_string_create();
3004 BT_ASSERT(*string_decl);
3005 (*string_decl)->encoding = encoding;
3006 return 0;
3007
3008 error:
3009 ctf_field_class_destroy((void *) *string_decl);
3010 *string_decl = NULL;
3011 return ret;
3012 }
3013
3014 static
3015 int visit_field_class_specifier_list(struct ctx *ctx,
3016 struct ctf_node *ts_list, struct ctf_field_class **decl)
3017 {
3018 int ret = 0;
3019 struct ctf_node *first, *node;
3020
3021 *decl = NULL;
3022
3023 if (ts_list->type != NODE_TYPE_SPECIFIER_LIST) {
3024 _BT_LOGE_NODE(ts_list,
3025 "Unexpected node type: node-type=%d", ts_list->type);
3026 ret = -EINVAL;
3027 goto error;
3028 }
3029
3030 first = _BT_LIST_FIRST_ENTRY(&ts_list->u.field_class_specifier_list.head,
3031 struct ctf_node, siblings);
3032 if (first->type != NODE_TYPE_SPECIFIER) {
3033 _BT_LOGE_NODE(first,
3034 "Unexpected node type: node-type=%d", first->type);
3035 ret = -EINVAL;
3036 goto error;
3037 }
3038
3039 node = first->u.field_class_specifier.node;
3040
3041 switch (first->u.field_class_specifier.type) {
3042 case TYPESPEC_INTEGER:
3043 ret = visit_integer_decl(ctx, &node->u.integer.expressions,
3044 (void *) decl);
3045 if (ret) {
3046 BT_ASSERT(!*decl);
3047 goto error;
3048 }
3049 break;
3050 case TYPESPEC_FLOATING_POINT:
3051 ret = visit_floating_point_number_decl(ctx,
3052 &node->u.floating_point.expressions, (void *) decl);
3053 if (ret) {
3054 BT_ASSERT(!*decl);
3055 goto error;
3056 }
3057 break;
3058 case TYPESPEC_STRING:
3059 ret = visit_string_decl(ctx,
3060 &node->u.string.expressions, (void *) decl);
3061 if (ret) {
3062 BT_ASSERT(!*decl);
3063 goto error;
3064 }
3065 break;
3066 case TYPESPEC_STRUCT:
3067 ret = visit_struct_decl(ctx, node->u._struct.name,
3068 &node->u._struct.declaration_list,
3069 node->u._struct.has_body,
3070 &node->u._struct.min_align, (void *) decl);
3071 if (ret) {
3072 BT_ASSERT(!*decl);
3073 goto error;
3074 }
3075 break;
3076 case TYPESPEC_VARIANT:
3077 ret = visit_variant_decl(ctx, node->u.variant.name,
3078 node->u.variant.choice,
3079 &node->u.variant.declaration_list,
3080 node->u.variant.has_body, (void *) decl);
3081 if (ret) {
3082 BT_ASSERT(!*decl);
3083 goto error;
3084 }
3085 break;
3086 case TYPESPEC_ENUM:
3087 ret = visit_enum_decl(ctx, node->u._enum.enum_id,
3088 node->u._enum.container_field_class,
3089 &node->u._enum.enumerator_list,
3090 node->u._enum.has_body, (void *) decl);
3091 if (ret) {
3092 BT_ASSERT(!*decl);
3093 goto error;
3094 }
3095 break;
3096 case TYPESPEC_VOID:
3097 case TYPESPEC_CHAR:
3098 case TYPESPEC_SHORT:
3099 case TYPESPEC_INT:
3100 case TYPESPEC_LONG:
3101 case TYPESPEC_FLOAT:
3102 case TYPESPEC_DOUBLE:
3103 case TYPESPEC_SIGNED:
3104 case TYPESPEC_UNSIGNED:
3105 case TYPESPEC_BOOL:
3106 case TYPESPEC_COMPLEX:
3107 case TYPESPEC_IMAGINARY:
3108 case TYPESPEC_CONST:
3109 case TYPESPEC_ID_TYPE:
3110 ret = visit_field_class_specifier(ctx, ts_list, decl);
3111 if (ret) {
3112 _BT_LOGE_NODE(first,
3113 "Cannot visit field class specifier: ret=%d",
3114 ret);
3115 BT_ASSERT(!*decl);
3116 goto error;
3117 }
3118 break;
3119 default:
3120 _BT_LOGE_NODE(first,
3121 "Unexpected field class specifier type: node-type=%d",
3122 first->u.field_class_specifier.type);
3123 ret = -EINVAL;
3124 goto error;
3125 }
3126
3127 BT_ASSERT(*decl);
3128 return 0;
3129
3130 error:
3131 ctf_field_class_destroy((void *) *decl);
3132 *decl = NULL;
3133 return ret;
3134 }
3135
3136 static
3137 int visit_event_decl_entry(struct ctx *ctx, struct ctf_node *node,
3138 struct ctf_event_class *event_class, uint64_t *stream_id,
3139 int *set)
3140 {
3141 int ret = 0;
3142 char *left = NULL;
3143
3144 switch (node->type) {
3145 case NODE_TYPEDEF:
3146 ret = visit_field_class_def(ctx, node->u.field_class_def.field_class_specifier_list,
3147 &node->u.field_class_def.field_class_declarators);
3148 if (ret) {
3149 _BT_LOGE_NODE(node,
3150 "Cannot add field class found in event class.");
3151 goto error;
3152 }
3153 break;
3154 case NODE_TYPEALIAS:
3155 ret = visit_field_class_alias(ctx, node->u.field_class_alias.target,
3156 node->u.field_class_alias.alias);
3157 if (ret) {
3158 _BT_LOGE_NODE(node,
3159 "Cannot add field class alias found in event class.");
3160 goto error;
3161 }
3162 break;
3163 case NODE_CTF_EXPRESSION:
3164 {
3165 left = concatenate_unary_strings(&node->u.ctf_expression.left);
3166 if (!left) {
3167 _BT_LOGE_NODE(node, "Cannot concatenate unary strings.");
3168 ret = -EINVAL;
3169 goto error;
3170 }
3171
3172 if (!strcmp(left, "name")) {
3173 /* This is already known at this stage */
3174 if (_IS_SET(set, _EVENT_NAME_SET)) {
3175 _BT_LOGE_DUP_ATTR(node, "name", "event class");
3176 ret = -EPERM;
3177 goto error;
3178 }
3179
3180 _SET(set, _EVENT_NAME_SET);
3181 } else if (!strcmp(left, "id")) {
3182 int64_t id = -1;
3183
3184 if (_IS_SET(set, _EVENT_ID_SET)) {
3185 _BT_LOGE_DUP_ATTR(node, "id", "event class");
3186 ret = -EPERM;
3187 goto error;
3188 }
3189
3190 ret = get_unary_unsigned(&node->u.ctf_expression.right,
3191 (uint64_t *) &id);
3192 /* Only read "id" if get_unary_unsigned() succeeded. */
3193 if (ret || (!ret && id < 0)) {
3194 _BT_LOGE_NODE(node,
3195 "Unexpected unary expression for event class's `id` attribute.");
3196 ret = -EINVAL;
3197 goto error;
3198 }
3199
3200 event_class->id = id;
3201 _SET(set, _EVENT_ID_SET);
3202 } else if (!strcmp(left, "stream_id")) {
3203 if (_IS_SET(set, _EVENT_STREAM_ID_SET)) {
3204 _BT_LOGE_DUP_ATTR(node, "stream_id",
3205 "event class");
3206 ret = -EPERM;
3207 goto error;
3208 }
3209
3210 ret = get_unary_unsigned(&node->u.ctf_expression.right,
3211 stream_id);
3212
3213 /*
3214 * Only read "stream_id" if get_unary_unsigned()
3215 * succeeded.
3216 */
3217 if (ret || (!ret && *stream_id < 0)) {
3218 _BT_LOGE_NODE(node,
3219 "Unexpected unary expression for event class's `stream_id` attribute.");
3220 ret = -EINVAL;
3221 goto error;
3222 }
3223
3224 _SET(set, _EVENT_STREAM_ID_SET);
3225 } else if (!strcmp(left, "context")) {
3226 if (_IS_SET(set, _EVENT_CONTEXT_SET)) {
3227 _BT_LOGE_NODE(node,
3228 "Duplicate `context` entry in event class.");
3229 ret = -EPERM;
3230 goto error;
3231 }
3232
3233 ret = visit_field_class_specifier_list(ctx,
3234 _BT_LIST_FIRST_ENTRY(
3235 &node->u.ctf_expression.right,
3236 struct ctf_node, siblings),
3237 &event_class->spec_context_fc);
3238 if (ret) {
3239 _BT_LOGE_NODE(node,
3240 "Cannot create event class's context field class.");
3241 goto error;
3242 }
3243
3244 BT_ASSERT(event_class->spec_context_fc);
3245 _SET(set, _EVENT_CONTEXT_SET);
3246 } else if (!strcmp(left, "fields")) {
3247 if (_IS_SET(set, _EVENT_FIELDS_SET)) {
3248 _BT_LOGE_NODE(node,
3249 "Duplicate `fields` entry in event class.");
3250 ret = -EPERM;
3251 goto error;
3252 }
3253
3254 ret = visit_field_class_specifier_list(ctx,
3255 _BT_LIST_FIRST_ENTRY(
3256 &node->u.ctf_expression.right,
3257 struct ctf_node, siblings),
3258 &event_class->payload_fc);
3259 if (ret) {
3260 _BT_LOGE_NODE(node,
3261 "Cannot create event class's payload field class.");
3262 goto error;
3263 }
3264
3265 BT_ASSERT(event_class->payload_fc);
3266 _SET(set, _EVENT_FIELDS_SET);
3267 } else if (!strcmp(left, "loglevel")) {
3268 uint64_t loglevel_value;
3269 enum bt_event_class_log_level log_level = -1;
3270
3271 if (_IS_SET(set, _EVENT_LOG_LEVEL_SET)) {
3272 _BT_LOGE_DUP_ATTR(node, "loglevel",
3273 "event class");
3274 ret = -EPERM;
3275 goto error;
3276 }
3277
3278 ret = get_unary_unsigned(&node->u.ctf_expression.right,
3279 &loglevel_value);
3280 if (ret) {
3281 _BT_LOGE_NODE(node,
3282 "Unexpected unary expression for event class's `loglevel` attribute.");
3283 ret = -EINVAL;
3284 goto error;
3285 }
3286
3287 switch (loglevel_value) {
3288 case 0:
3289 log_level = BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY;
3290 break;
3291 case 1:
3292 log_level = BT_EVENT_CLASS_LOG_LEVEL_ALERT;
3293 break;
3294 case 2:
3295 log_level = BT_EVENT_CLASS_LOG_LEVEL_CRITICAL;
3296 break;
3297 case 3:
3298 log_level = BT_EVENT_CLASS_LOG_LEVEL_ERROR;
3299 break;
3300 case 4:
3301 log_level = BT_EVENT_CLASS_LOG_LEVEL_WARNING;
3302 break;
3303 case 5:
3304 log_level = BT_EVENT_CLASS_LOG_LEVEL_NOTICE;
3305 break;
3306 case 6:
3307 log_level = BT_EVENT_CLASS_LOG_LEVEL_INFO;
3308 break;
3309 case 7:
3310 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM;
3311 break;
3312 case 8:
3313 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM;
3314 break;
3315 case 9:
3316 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS;
3317 break;
3318 case 10:
3319 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE;
3320 break;
3321 case 11:
3322 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT;
3323 break;
3324 case 12:
3325 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION;
3326 break;
3327 case 13:
3328 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE;
3329 break;
3330 case 14:
3331 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG;
3332 break;
3333 default:
3334 _BT_LOGW_NODE(node, "Not setting event class's log level because its value is unknown: "
3335 "log-level=%" PRIu64, loglevel_value);
3336 }
3337
3338 if (log_level != -1) {
3339 event_class->log_level = log_level;
3340 }
3341
3342 _SET(set, _EVENT_LOG_LEVEL_SET);
3343 } else if (!strcmp(left, "model.emf.uri")) {
3344 char *right;
3345
3346 if (_IS_SET(set, _EVENT_MODEL_EMF_URI_SET)) {
3347 _BT_LOGE_DUP_ATTR(node, "model.emf.uri",
3348 "event class");
3349 ret = -EPERM;
3350 goto error;
3351 }
3352
3353 right = concatenate_unary_strings(
3354 &node->u.ctf_expression.right);
3355 if (!right) {
3356 _BT_LOGE_NODE(node,
3357 "Unexpected unary expression for event class's `model.emf.uri` attribute.");
3358 ret = -EINVAL;
3359 goto error;
3360 }
3361
3362 if (strlen(right) == 0) {
3363 _BT_LOGW_NODE(node,
3364 "Not setting event class's EMF URI because it's empty.");
3365 } else {
3366 g_string_assign(event_class->emf_uri,
3367 right);
3368 }
3369
3370 g_free(right);
3371 _SET(set, _EVENT_MODEL_EMF_URI_SET);
3372 } else {
3373 _BT_LOGW_NODE(node,
3374 "Unknown attribute in event class: "
3375 "attr-name=\"%s\"", left);
3376 }
3377
3378 g_free(left);
3379 left = NULL;
3380 break;
3381 }
3382 default:
3383 ret = -EPERM;
3384 goto error;
3385 }
3386
3387 goto end;
3388
3389 error:
3390 if (left) {
3391 g_free(left);
3392 }
3393
3394 end:
3395 return ret;
3396 }
3397
3398 static
3399 char *get_event_decl_name(struct ctx *ctx, struct ctf_node *node)
3400 {
3401 char *left = NULL;
3402 char *name = NULL;
3403 struct ctf_node *iter;
3404 struct bt_list_head *decl_list = &node->u.event.declaration_list;
3405
3406 bt_list_for_each_entry(iter, decl_list, siblings) {
3407 if (iter->type != NODE_CTF_EXPRESSION) {
3408 continue;
3409 }
3410
3411 left = concatenate_unary_strings(&iter->u.ctf_expression.left);
3412 if (!left) {
3413 _BT_LOGE_NODE(iter,
3414 "Cannot concatenate unary strings.");
3415 goto error;
3416 }
3417
3418 if (!strcmp(left, "name")) {
3419 name = concatenate_unary_strings(
3420 &iter->u.ctf_expression.right);
3421 if (!name) {
3422 _BT_LOGE_NODE(iter,
3423 "Unexpected unary expression for event class's `name` attribute.");
3424 goto error;
3425 }
3426 }
3427
3428 g_free(left);
3429 left = NULL;
3430
3431 if (name) {
3432 break;
3433 }
3434 }
3435
3436 return name;
3437
3438 error:
3439 g_free(left);
3440 return NULL;
3441 }
3442
3443 static
3444 int visit_event_decl(struct ctx *ctx, struct ctf_node *node)
3445 {
3446 int ret = 0;
3447 int set = 0;
3448 struct ctf_node *iter;
3449 uint64_t stream_id = 0;
3450 char *event_name = NULL;
3451 struct ctf_event_class *event_class = NULL;
3452 struct ctf_stream_class *stream_class = NULL;
3453 struct bt_list_head *decl_list = &node->u.event.declaration_list;
3454 bool pop_scope = false;
3455
3456 if (node->visited) {
3457 goto end;
3458 }
3459
3460 node->visited = TRUE;
3461 event_name = get_event_decl_name(ctx, node);
3462 if (!event_name) {
3463 _BT_LOGE_NODE(node,
3464 "Missing `name` attribute in event class.");
3465 ret = -EPERM;
3466 goto error;
3467 }
3468
3469 event_class = ctf_event_class_create();
3470 BT_ASSERT(event_class);
3471 g_string_assign(event_class->name, event_name);
3472 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
3473 pop_scope = true;
3474
3475 bt_list_for_each_entry(iter, decl_list, siblings) {
3476 ret = visit_event_decl_entry(ctx, iter, event_class,
3477 &stream_id, &set);
3478 if (ret) {
3479 _BT_LOGE_NODE(iter, "Cannot visit event class's entry: "
3480 "ret=%d", ret);
3481 goto error;
3482 }
3483 }
3484
3485 if (!_IS_SET(&set, _EVENT_STREAM_ID_SET)) {
3486 /*
3487 * Allow missing stream_id if there is only a single
3488 * stream class.
3489 */
3490 switch (ctx->ctf_tc->stream_classes->len) {
3491 case 0:
3492 /* Create implicit stream class if there's none */
3493 stream_id = 0;
3494 stream_class = ctf_stream_class_create();
3495 BT_ASSERT(stream_class);
3496 stream_class->id = stream_id;
3497 g_ptr_array_add(ctx->ctf_tc->stream_classes,
3498 stream_class);
3499 stream_class = stream_class;
3500 break;
3501 case 1:
3502 /* Single stream class: get its ID */
3503 stream_class = ctx->ctf_tc->stream_classes->pdata[0];
3504 stream_id = stream_class->id;
3505 break;
3506 default:
3507 _BT_LOGE_NODE(node,
3508 "Missing `stream_id` attribute in event class.");
3509 ret = -EPERM;
3510 goto error;
3511 }
3512 }
3513
3514 /* We have the stream ID now; get the stream class if found */
3515 if (!stream_class) {
3516 stream_class = ctf_trace_class_borrow_stream_class_by_id(
3517 ctx->ctf_tc, stream_id);
3518 if (!stream_class) {
3519 _BT_LOGE_NODE(node,
3520 "Cannot find stream class at this point: "
3521 "id=%" PRId64, stream_id);
3522 ret = -EINVAL;
3523 goto error;
3524 }
3525 }
3526
3527 BT_ASSERT(stream_class);
3528
3529 if (!_IS_SET(&set, _EVENT_ID_SET)) {
3530 /* Allow only one event without ID per stream */
3531 if (stream_class->event_classes->len != 0) {
3532 _BT_LOGE_NODE(node,
3533 "Missing `id` attribute in event class.");
3534 ret = -EPERM;
3535 goto error;
3536 }
3537
3538 /* Automatic ID */
3539 event_class->id = 0;
3540 }
3541
3542 if (ctf_stream_class_borrow_event_class_by_id(stream_class,
3543 event_class->id)) {
3544 _BT_LOGE_NODE(node,
3545 "Duplicate event class (same ID) in the same stream class: "
3546 "id=%" PRId64, event_class->id);
3547 ret = -EEXIST;
3548 goto error;
3549 }
3550
3551 ctf_stream_class_append_event_class(stream_class, event_class);
3552 event_class = NULL;
3553 goto end;
3554
3555 error:
3556 ctf_event_class_destroy(event_class);
3557 event_class = NULL;
3558
3559 if (ret >= 0) {
3560 ret = -1;
3561 }
3562
3563 end:
3564 if (pop_scope) {
3565 ctx_pop_scope(ctx);
3566 }
3567
3568 if (event_name) {
3569 g_free(event_name);
3570 }
3571
3572 return ret;
3573 }
3574
3575 static
3576 int auto_map_field_to_trace_clock_class(struct ctx *ctx,
3577 struct ctf_field_class *fc)
3578 {
3579 struct bt_private_clock_class *clock_class_to_map_to = NULL;
3580 struct ctf_field_class_int *int_fc = (void *) fc;
3581 int ret = 0;
3582 uint64_t clock_class_count;
3583
3584 if (!fc) {
3585 goto end;
3586 }
3587
3588 if (fc->type != CTF_FIELD_CLASS_TYPE_INT &&
3589 fc->type != CTF_FIELD_CLASS_TYPE_ENUM) {
3590 goto end;
3591 }
3592
3593 if (int_fc->mapped_clock_class) {
3594 /* Already mapped */
3595 goto end;
3596 }
3597
3598 clock_class_count = ctx->ctf_tc->clock_classes->len;
3599
3600 switch (clock_class_count) {
3601 case 0:
3602 /*
3603 * No clock class exists in the trace at this point. Create an
3604 * implicit one at 1 GHz, named `default`, and use this clock
3605 * class.
3606 */
3607 clock_class_to_map_to = bt_private_clock_class_create();
3608 BT_ASSERT(clock_class_to_map_to);
3609 bt_private_clock_class_set_frequency(clock_class_to_map_to,
3610 UINT64_C(1000000000));
3611 ret = bt_private_clock_class_set_name(clock_class_to_map_to,
3612 "default");
3613 BT_ASSERT(ret == 0);
3614 g_ptr_array_add(ctx->ctf_tc->clock_classes,
3615 bt_object_get_ref(clock_class_to_map_to));
3616 break;
3617 case 1:
3618 /*
3619 * Only one clock class exists in the trace at this point: use
3620 * this one.
3621 */
3622 clock_class_to_map_to =
3623 bt_object_get_ref(ctx->ctf_tc->clock_classes->pdata[0]);
3624 break;
3625 default:
3626 /*
3627 * Timestamp field not mapped to a clock class and there's more
3628 * than one clock class in the trace: this is an error.
3629 */
3630 BT_LOGE_STR("Timestamp field found with no mapped clock class, "
3631 "but there's more than one clock class in the trace at this point.");
3632 ret = -1;
3633 goto end;
3634 }
3635
3636 BT_ASSERT(clock_class_to_map_to);
3637 int_fc->mapped_clock_class = bt_object_get_ref(clock_class_to_map_to);
3638
3639 end:
3640 bt_object_put_ref(clock_class_to_map_to);
3641 return ret;
3642 }
3643
3644 static
3645 int auto_map_fields_to_trace_clock_class(struct ctx *ctx,
3646 struct ctf_field_class *root_fc, const char *field_name)
3647 {
3648 int ret = 0;
3649 uint64_t i, count;
3650 struct ctf_field_class_struct *struct_fc = (void *) root_fc;
3651 struct ctf_field_class_variant *var_fc = (void *) root_fc;
3652
3653 if (!root_fc) {
3654 goto end;
3655 }
3656
3657 if (root_fc->type != CTF_FIELD_CLASS_TYPE_STRUCT &&
3658 root_fc->type != CTF_FIELD_CLASS_TYPE_VARIANT) {
3659 goto end;
3660 }
3661
3662 if (root_fc->type == CTF_FIELD_CLASS_TYPE_STRUCT) {
3663 count = struct_fc->members->len;
3664 } else {
3665 count = var_fc->options->len;
3666 }
3667
3668 for (i = 0; i < count; i++) {
3669 struct ctf_named_field_class *named_fc = NULL;
3670
3671 if (root_fc->type == CTF_FIELD_CLASS_TYPE_STRUCT) {
3672 named_fc = ctf_field_class_struct_borrow_member_by_index(
3673 struct_fc, i);
3674 } else if (root_fc->type == CTF_FIELD_CLASS_TYPE_VARIANT) {
3675 named_fc = ctf_field_class_variant_borrow_option_by_index(
3676 var_fc, i);
3677 }
3678
3679 if (strcmp(named_fc->name->str, field_name) == 0) {
3680 ret = auto_map_field_to_trace_clock_class(ctx,
3681 named_fc->fc);
3682 if (ret) {
3683 BT_LOGE("Cannot automatically map field to trace's clock class: "
3684 "field-name=\"%s\"", field_name);
3685 goto end;
3686 }
3687 }
3688
3689 ret = auto_map_fields_to_trace_clock_class(ctx, named_fc->fc,
3690 field_name);
3691 if (ret) {
3692 BT_LOGE("Cannot automatically map structure or variant field class's fields to trace's clock class: "
3693 "field-name=\"%s\", root-field-name=\"%s\"",
3694 field_name, named_fc->name->str);
3695 goto end;
3696 }
3697 }
3698
3699 end:
3700 return ret;
3701 }
3702
3703 static
3704 int visit_stream_decl_entry(struct ctx *ctx, struct ctf_node *node,
3705 struct ctf_stream_class *stream_class, int *set)
3706 {
3707 int ret = 0;
3708 char *left = NULL;
3709
3710 switch (node->type) {
3711 case NODE_TYPEDEF:
3712 ret = visit_field_class_def(ctx, node->u.field_class_def.field_class_specifier_list,
3713 &node->u.field_class_def.field_class_declarators);
3714 if (ret) {
3715 _BT_LOGE_NODE(node,
3716 "Cannot add field class found in stream class.");
3717 goto error;
3718 }
3719 break;
3720 case NODE_TYPEALIAS:
3721 ret = visit_field_class_alias(ctx, node->u.field_class_alias.target,
3722 node->u.field_class_alias.alias);
3723 if (ret) {
3724 _BT_LOGE_NODE(node,
3725 "Cannot add field class alias found in stream class.");
3726 goto error;
3727 }
3728 break;
3729 case NODE_CTF_EXPRESSION:
3730 {
3731 left = concatenate_unary_strings(&node->u.ctf_expression.left);
3732 if (!left) {
3733 _BT_LOGE_NODE(node, "Cannot concatenate unary strings.");
3734 ret = -EINVAL;
3735 goto error;
3736 }
3737
3738 if (!strcmp(left, "id")) {
3739 int64_t id;
3740
3741 if (_IS_SET(set, _STREAM_ID_SET)) {
3742 _BT_LOGE_DUP_ATTR(node, "id",
3743 "stream declaration");
3744 ret = -EPERM;
3745 goto error;
3746 }
3747
3748 ret = get_unary_unsigned(&node->u.ctf_expression.right,
3749 (uint64_t *) &id);
3750
3751 /* Only read "id" if get_unary_unsigned() succeeded. */
3752 if (ret || (!ret && id < 0)) {
3753 _BT_LOGE_NODE(node,
3754 "Unexpected unary expression for stream class's `id` attribute.");
3755 ret = -EINVAL;
3756 goto error;
3757 }
3758
3759 if (ctf_trace_class_borrow_stream_class_by_id(
3760 ctx->ctf_tc, id)) {
3761 _BT_LOGE_NODE(node,
3762 "Duplicate stream class (same ID): id=%" PRId64,
3763 id);
3764 ret = -EEXIST;
3765 goto error;
3766 }
3767
3768 stream_class->id = id;
3769 _SET(set, _STREAM_ID_SET);
3770 } else if (!strcmp(left, "event.header")) {
3771 if (_IS_SET(set, _STREAM_EVENT_HEADER_SET)) {
3772 _BT_LOGE_NODE(node,
3773 "Duplicate `event.header` entry in stream class.");
3774 ret = -EPERM;
3775 goto error;
3776 }
3777
3778 ret = visit_field_class_specifier_list(ctx,
3779 _BT_LIST_FIRST_ENTRY(
3780 &node->u.ctf_expression.right,
3781 struct ctf_node, siblings),
3782 &stream_class->event_header_fc);
3783 if (ret) {
3784 _BT_LOGE_NODE(node,
3785 "Cannot create stream class's event header field class.");
3786 goto error;
3787 }
3788
3789 BT_ASSERT(stream_class->event_header_fc);
3790 ret = auto_map_fields_to_trace_clock_class(ctx,
3791 stream_class->event_header_fc, "timestamp");
3792 if (ret) {
3793 _BT_LOGE_NODE(node,
3794 "Cannot automatically map specific event header field class fields named `timestamp` to trace's clock class.");
3795 goto error;
3796 }
3797
3798 _SET(set, _STREAM_EVENT_HEADER_SET);
3799 } else if (!strcmp(left, "event.context")) {
3800 if (_IS_SET(set, _STREAM_EVENT_CONTEXT_SET)) {
3801 _BT_LOGE_NODE(node,
3802 "Duplicate `event.context` entry in stream class.");
3803 ret = -EPERM;
3804 goto error;
3805 }
3806
3807 ret = visit_field_class_specifier_list(ctx,
3808 _BT_LIST_FIRST_ENTRY(
3809 &node->u.ctf_expression.right,
3810 struct ctf_node, siblings),
3811 &stream_class->event_common_context_fc);
3812 if (ret) {
3813 _BT_LOGE_NODE(node,
3814 "Cannot create stream class's event context field class.");
3815 goto error;
3816 }
3817
3818 BT_ASSERT(stream_class->event_common_context_fc);
3819 _SET(set, _STREAM_EVENT_CONTEXT_SET);
3820 } else if (!strcmp(left, "packet.context")) {
3821 if (_IS_SET(set, _STREAM_PACKET_CONTEXT_SET)) {
3822 _BT_LOGE_NODE(node,
3823 "Duplicate `packet.context` entry in stream class.");
3824 ret = -EPERM;
3825 goto error;
3826 }
3827
3828 ret = visit_field_class_specifier_list(ctx,
3829 _BT_LIST_FIRST_ENTRY(
3830 &node->u.ctf_expression.right,
3831 struct ctf_node, siblings),
3832 &stream_class->packet_context_fc);
3833 if (ret) {
3834 _BT_LOGE_NODE(node,
3835 "Cannot create stream class's packet context field class.");
3836 goto error;
3837 }
3838
3839 BT_ASSERT(stream_class->packet_context_fc);
3840 ret = auto_map_fields_to_trace_clock_class(ctx,
3841 stream_class->packet_context_fc,
3842 "timestamp_begin");
3843 if (ret) {
3844 _BT_LOGE_NODE(node,
3845 "Cannot automatically map specific packet context field class fields named `timestamp_begin` to trace's clock class.");
3846 goto error;
3847 }
3848
3849 ret = auto_map_fields_to_trace_clock_class(ctx,
3850 stream_class->packet_context_fc,
3851 "timestamp_end");
3852 if (ret) {
3853 _BT_LOGE_NODE(node,
3854 "Cannot automatically map specific packet context field class fields named `timestamp_end` to trace's clock class.");
3855 goto error;
3856 }
3857
3858 _SET(set, _STREAM_PACKET_CONTEXT_SET);
3859 } else {
3860 _BT_LOGW_NODE(node,
3861 "Unknown attribute in stream class: "
3862 "attr-name=\"%s\"", left);
3863 }
3864
3865 g_free(left);
3866 left = NULL;
3867 break;
3868 }
3869
3870 default:
3871 ret = -EPERM;
3872 goto error;
3873 }
3874
3875 return 0;
3876
3877 error:
3878 g_free(left);
3879 return ret;
3880 }
3881
3882 static
3883 int visit_stream_decl(struct ctx *ctx, struct ctf_node *node)
3884 {
3885 int set = 0;
3886 int ret = 0;
3887 struct ctf_node *iter;
3888 struct ctf_stream_class *stream_class = NULL;
3889 struct bt_list_head *decl_list = &node->u.stream.declaration_list;
3890
3891 if (node->visited) {
3892 goto end;
3893 }
3894
3895 node->visited = TRUE;
3896 stream_class = ctf_stream_class_create();
3897 BT_ASSERT(stream_class);
3898 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
3899
3900 bt_list_for_each_entry(iter, decl_list, siblings) {
3901 ret = visit_stream_decl_entry(ctx, iter, stream_class, &set);
3902 if (ret) {
3903 _BT_LOGE_NODE(iter,
3904 "Cannot visit stream class's entry: "
3905 "ret=%d", ret);
3906 ctx_pop_scope(ctx);
3907 goto error;
3908 }
3909 }
3910
3911 ctx_pop_scope(ctx);
3912
3913 if (_IS_SET(&set, _STREAM_ID_SET)) {
3914 /* Check that packet header has `stream_id` field */
3915 struct ctf_named_field_class *named_fc = NULL;
3916
3917 if (!ctx->ctf_tc->packet_header_fc) {
3918 _BT_LOGE_NODE(node,
3919 "Stream class has a `id` attribute, "
3920 "but trace has no packet header field class.");
3921 goto error;
3922 }
3923
3924 named_fc = ctf_field_class_struct_borrow_member_by_name(
3925 (void *) ctx->ctf_tc->packet_header_fc, "stream_id");
3926 if (!named_fc) {
3927 _BT_LOGE_NODE(node,
3928 "Stream class has a `id` attribute, "
3929 "but trace's packet header field class has no `stream_id` field.");
3930 goto error;
3931 }
3932
3933 if (named_fc->fc->type != CTF_FIELD_CLASS_TYPE_INT &&
3934 named_fc->fc->type != CTF_FIELD_CLASS_TYPE_ENUM) {
3935 _BT_LOGE_NODE(node,
3936 "Stream class has a `id` attribute, "
3937 "but trace's packet header field class's `stream_id` field is not an integer field class.");
3938 goto error;
3939 }
3940 } else {
3941 /* Allow only _one_ ID-less stream */
3942 if (ctx->ctf_tc->stream_classes->len != 0) {
3943 _BT_LOGE_NODE(node,
3944 "Missing `id` attribute in stream class as there's more than one stream class in the trace.");
3945 ret = -EPERM;
3946 goto error;
3947 }
3948
3949 /* Automatic ID: 0 */
3950 stream_class->id = 0;
3951 }
3952
3953 /*
3954 * Make sure that this stream class's ID is currently unique in
3955 * the trace.
3956 */
3957 if (ctf_trace_class_borrow_stream_class_by_id(ctx->ctf_tc,
3958 stream_class->id)) {
3959 _BT_LOGE_NODE(node,
3960 "Duplicate stream class (same ID): id=%" PRId64,
3961 stream_class->id);
3962 ret = -EINVAL;
3963 goto error;
3964 }
3965
3966 g_ptr_array_add(ctx->ctf_tc->stream_classes, stream_class);
3967 stream_class = NULL;
3968 goto end;
3969
3970 error:
3971 ctf_stream_class_destroy(stream_class);
3972 stream_class = NULL;
3973
3974 end:
3975 return ret;
3976 }
3977
3978 static
3979 int visit_trace_decl_entry(struct ctx *ctx, struct ctf_node *node, int *set)
3980 {
3981 int ret = 0;
3982 char *left = NULL;
3983 uint64_t val;
3984
3985 switch (node->type) {
3986 case NODE_TYPEDEF:
3987 ret = visit_field_class_def(ctx, node->u.field_class_def.field_class_specifier_list,
3988 &node->u.field_class_def.field_class_declarators);
3989 if (ret) {
3990 _BT_LOGE_NODE(node,
3991 "Cannot add field class found in trace (`trace` block).");
3992 goto error;
3993 }
3994 break;
3995 case NODE_TYPEALIAS:
3996 ret = visit_field_class_alias(ctx, node->u.field_class_alias.target,
3997 node->u.field_class_alias.alias);
3998 if (ret) {
3999 _BT_LOGE_NODE(node,
4000 "Cannot add field class alias found in trace (`trace` block).");
4001 goto error;
4002 }
4003 break;
4004 case NODE_CTF_EXPRESSION:
4005 {
4006 left = concatenate_unary_strings(&node->u.ctf_expression.left);
4007 if (!left) {
4008 _BT_LOGE_NODE(node, "Cannot concatenate unary strings.");
4009 ret = -EINVAL;
4010 goto error;
4011 }
4012
4013 if (!strcmp(left, "major")) {
4014 if (_IS_SET(set, _TRACE_MAJOR_SET)) {
4015 _BT_LOGE_DUP_ATTR(node, "major", "trace");
4016 ret = -EPERM;
4017 goto error;
4018 }
4019
4020 ret = get_unary_unsigned(&node->u.ctf_expression.right,
4021 &val);
4022 if (ret) {
4023 _BT_LOGE_NODE(node,
4024 "Unexpected unary expression for trace's `major` attribute.");
4025 ret = -EINVAL;
4026 goto error;
4027 }
4028
4029 if (val != 1) {
4030 _BT_LOGE_NODE(node,
4031 "Invalid trace's `minor` attribute: expecting 1.");
4032 goto error;
4033 }
4034
4035 ctx->ctf_tc->major = val;
4036 _SET(set, _TRACE_MAJOR_SET);
4037 } else if (!strcmp(left, "minor")) {
4038 if (_IS_SET(set, _TRACE_MINOR_SET)) {
4039 _BT_LOGE_DUP_ATTR(node, "minor", "trace");
4040 ret = -EPERM;
4041 goto error;
4042 }
4043
4044 ret = get_unary_unsigned(&node->u.ctf_expression.right,
4045 &val);
4046 if (ret) {
4047 _BT_LOGE_NODE(node,
4048 "Unexpected unary expression for trace's `minor` attribute.");
4049 ret = -EINVAL;
4050 goto error;
4051 }
4052
4053 if (val != 8) {
4054 _BT_LOGE_NODE(node,
4055 "Invalid trace's `minor` attribute: expecting 8.");
4056 goto error;
4057 }
4058
4059 ctx->ctf_tc->minor = val;
4060 _SET(set, _TRACE_MINOR_SET);
4061 } else if (!strcmp(left, "uuid")) {
4062 if (_IS_SET(set, _TRACE_UUID_SET)) {
4063 _BT_LOGE_DUP_ATTR(node, "uuid", "trace");
4064 ret = -EPERM;
4065 goto error;
4066 }
4067
4068 ret = get_unary_uuid(&node->u.ctf_expression.right,
4069 ctx->ctf_tc->uuid);
4070 if (ret) {
4071 _BT_LOGE_NODE(node,
4072 "Invalid trace's `uuid` attribute.");
4073 goto error;
4074 }
4075
4076 ctx->ctf_tc->is_uuid_set = true;
4077 _SET(set, _TRACE_UUID_SET);
4078 } else if (!strcmp(left, "byte_order")) {
4079 /* Default byte order is already known at this stage */
4080 if (_IS_SET(set, _TRACE_BYTE_ORDER_SET)) {
4081 _BT_LOGE_DUP_ATTR(node, "byte_order",
4082 "trace");
4083 ret = -EPERM;
4084 goto error;
4085 }
4086
4087 BT_ASSERT(ctx->ctf_tc->default_byte_order != -1);
4088 _SET(set, _TRACE_BYTE_ORDER_SET);
4089 } else if (!strcmp(left, "packet.header")) {
4090 if (_IS_SET(set, _TRACE_PACKET_HEADER_SET)) {
4091 _BT_LOGE_NODE(node,
4092 "Duplicate `packet.header` entry in trace.");
4093 ret = -EPERM;
4094 goto error;
4095 }
4096
4097 ret = visit_field_class_specifier_list(ctx,
4098 _BT_LIST_FIRST_ENTRY(
4099 &node->u.ctf_expression.right,
4100 struct ctf_node, siblings),
4101 &ctx->ctf_tc->packet_header_fc);
4102 if (ret) {
4103 _BT_LOGE_NODE(node,
4104 "Cannot create trace's packet header field class.");
4105 goto error;
4106 }
4107
4108 BT_ASSERT(ctx->ctf_tc->packet_header_fc);
4109 _SET(set, _TRACE_PACKET_HEADER_SET);
4110 } else {
4111 _BT_LOGW_NODE(node,
4112 "Unknown attribute in stream class: "
4113 "attr-name=\"%s\"", left);
4114 }
4115
4116 g_free(left);
4117 left = NULL;
4118 break;
4119 }
4120 default:
4121 _BT_LOGE_NODE(node, "Unknown expression in trace.");
4122 ret = -EINVAL;
4123 goto error;
4124 }
4125
4126 return 0;
4127
4128 error:
4129 g_free(left);
4130 return ret;
4131 }
4132
4133 static
4134 int visit_trace_decl(struct ctx *ctx, struct ctf_node *node)
4135 {
4136 int ret = 0;
4137 int set = 0;
4138 struct ctf_node *iter;
4139 struct bt_list_head *decl_list = &node->u.trace.declaration_list;
4140
4141 if (node->visited) {
4142 goto end;
4143 }
4144
4145 node->visited = TRUE;
4146
4147 if (ctx->is_trace_visited) {
4148 _BT_LOGE_NODE(node, "Duplicate trace (`trace` block).");
4149 ret = -EEXIST;
4150 goto error;
4151 }
4152
4153 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
4154
4155 bt_list_for_each_entry(iter, decl_list, siblings) {
4156 ret = visit_trace_decl_entry(ctx, iter, &set);
4157 if (ret) {
4158 _BT_LOGE_NODE(iter, "Cannot visit trace's entry (`trace` block): "
4159 "ret=%d", ret);
4160 ctx_pop_scope(ctx);
4161 goto error;
4162 }
4163 }
4164
4165 ctx_pop_scope(ctx);
4166
4167 if (!_IS_SET(&set, _TRACE_MAJOR_SET)) {
4168 _BT_LOGE_NODE(node,
4169 "Missing `major` attribute in trace (`trace` block).");
4170 ret = -EPERM;
4171 goto error;
4172 }
4173
4174 if (!_IS_SET(&set, _TRACE_MINOR_SET)) {
4175 _BT_LOGE_NODE(node,
4176 "Missing `minor` attribute in trace (`trace` block).");
4177 ret = -EPERM;
4178 goto error;
4179 }
4180
4181 if (!_IS_SET(&set, _TRACE_BYTE_ORDER_SET)) {
4182 _BT_LOGE_NODE(node,
4183 "Missing `byte_order` attribute in trace (`trace` block).");
4184 ret = -EPERM;
4185 goto error;
4186 }
4187
4188 ctx->is_trace_visited = true;
4189
4190 end:
4191 return 0;
4192
4193 error:
4194 return ret;
4195 }
4196
4197 static
4198 int visit_env(struct ctx *ctx, struct ctf_node *node)
4199 {
4200 int ret = 0;
4201 char *left = NULL;
4202 struct ctf_node *entry_node;
4203 struct bt_list_head *decl_list = &node->u.env.declaration_list;
4204
4205 if (node->visited) {
4206 goto end;
4207 }
4208
4209 node->visited = TRUE;
4210
4211 bt_list_for_each_entry(entry_node, decl_list, siblings) {
4212 struct bt_list_head *right_head =
4213 &entry_node->u.ctf_expression.right;
4214
4215 if (entry_node->type != NODE_CTF_EXPRESSION) {
4216 _BT_LOGE_NODE(entry_node,
4217 "Wrong expression in environment entry: "
4218 "node-type=%d", entry_node->type);
4219 ret = -EPERM;
4220 goto error;
4221 }
4222
4223 left = concatenate_unary_strings(
4224 &entry_node->u.ctf_expression.left);
4225 if (!left) {
4226 _BT_LOGE_NODE(entry_node,
4227 "Cannot get environment entry's name.");
4228 ret = -EINVAL;
4229 goto error;
4230 }
4231
4232 if (is_unary_string(right_head)) {
4233 char *right = concatenate_unary_strings(right_head);
4234
4235 if (!right) {
4236 _BT_LOGE_NODE(entry_node,
4237 "Unexpected unary expression for environment entry's value: "
4238 "name=\"%s\"", left);
4239 ret = -EINVAL;
4240 goto error;
4241 }
4242
4243 if (strcmp(left, "tracer_name") == 0) {
4244 if (strncmp(right, "lttng", 5) == 0) {
4245 BT_LOGI("Detected LTTng trace from `%s` environment value: "
4246 "tracer-name=\"%s\"",
4247 left, right);
4248 ctx->is_lttng = true;
4249 }
4250 }
4251
4252 ctf_trace_class_append_env_entry(ctx->ctf_tc,
4253 left, CTF_TRACE_CLASS_ENV_ENTRY_TYPE_STR,
4254 right, 0);
4255 g_free(right);
4256 } else if (is_unary_unsigned(right_head) ||
4257 is_unary_signed(right_head)) {
4258 int64_t v;
4259
4260 if (is_unary_unsigned(right_head)) {
4261 ret = get_unary_unsigned(right_head,
4262 (uint64_t *) &v);
4263 } else {
4264 ret = get_unary_signed(right_head, &v);
4265 }
4266 if (ret) {
4267 _BT_LOGE_NODE(entry_node,
4268 "Unexpected unary expression for environment entry's value: "
4269 "name=\"%s\"", left);
4270 ret = -EINVAL;
4271 goto error;
4272 }
4273
4274 ctf_trace_class_append_env_entry(ctx->ctf_tc,
4275 left, CTF_TRACE_CLASS_ENV_ENTRY_TYPE_INT,
4276 NULL, v);
4277 } else {
4278 _BT_LOGW_NODE(entry_node,
4279 "Environment entry has unknown type: "
4280 "name=\"%s\"", left);
4281 }
4282
4283 g_free(left);
4284 left = NULL;
4285 }
4286
4287 end:
4288 return 0;
4289
4290 error:
4291 g_free(left);
4292 return ret;
4293 }
4294
4295 static
4296 int set_trace_byte_order(struct ctx *ctx, struct ctf_node *trace_node)
4297 {
4298 int ret = 0;
4299 int set = 0;
4300 char *left = NULL;
4301 struct ctf_node *node;
4302 struct bt_list_head *decl_list = &trace_node->u.trace.declaration_list;
4303
4304 bt_list_for_each_entry(node, decl_list, siblings) {
4305 if (node->type == NODE_CTF_EXPRESSION) {
4306 struct ctf_node *right_node;
4307
4308 left = concatenate_unary_strings(
4309 &node->u.ctf_expression.left);
4310 if (!left) {
4311 _BT_LOGE_NODE(node,
4312 "Cannot concatenate unary strings.");
4313 ret = -EINVAL;
4314 goto error;
4315 }
4316
4317 if (!strcmp(left, "byte_order")) {
4318 enum ctf_byte_order bo;
4319
4320 if (_IS_SET(&set, _TRACE_BYTE_ORDER_SET)) {
4321 _BT_LOGE_DUP_ATTR(node, "byte_order",
4322 "trace");
4323 ret = -EPERM;
4324 goto error;
4325 }
4326
4327 _SET(&set, _TRACE_BYTE_ORDER_SET);
4328 right_node = _BT_LIST_FIRST_ENTRY(
4329 &node->u.ctf_expression.right,
4330 struct ctf_node, siblings);
4331 bo = byte_order_from_unary_expr(right_node);
4332 if (bo == -1) {
4333 _BT_LOGE_NODE(node,
4334 "Invalid `byte_order` attribute in trace (`trace` block): "
4335 "expecting `le`, `be`, or `network`.");
4336 ret = -EINVAL;
4337 goto error;
4338 } else if (bo == CTF_BYTE_ORDER_DEFAULT) {
4339 _BT_LOGE_NODE(node,
4340 "Invalid `byte_order` attribute in trace (`trace` block): "
4341 "cannot be set to `native` here.");
4342 ret = -EPERM;
4343 goto error;
4344 }
4345
4346 ctx->ctf_tc->default_byte_order = bo;
4347 }
4348
4349 g_free(left);
4350 left = NULL;
4351 }
4352 }
4353
4354 if (!_IS_SET(&set, _TRACE_BYTE_ORDER_SET)) {
4355 _BT_LOGE_NODE(trace_node,
4356 "Missing `byte_order` attribute in trace (`trace` block).");
4357 ret = -EINVAL;
4358 goto error;
4359 }
4360
4361 return 0;
4362
4363 error:
4364 g_free(left);
4365 return ret;
4366 }
4367
4368 static
4369 int visit_clock_decl_entry(struct ctx *ctx, struct ctf_node *entry_node,
4370 struct bt_private_clock_class *clock, int *set, int64_t *offset_seconds,
4371 uint64_t *offset_cycles)
4372 {
4373 int ret = 0;
4374 char *left = NULL;
4375
4376 if (entry_node->type != NODE_CTF_EXPRESSION) {
4377 _BT_LOGE_NODE(entry_node,
4378 "Unexpected node type: node-type=%d",
4379 entry_node->type);
4380 ret = -EPERM;
4381 goto error;
4382 }
4383
4384 left = concatenate_unary_strings(&entry_node->u.ctf_expression.left);
4385 if (!left) {
4386 _BT_LOGE_NODE(entry_node, "Cannot concatenate unary strings.");
4387 ret = -EINVAL;
4388 goto error;
4389 }
4390
4391 if (!strcmp(left, "name")) {
4392 char *right;
4393
4394 if (_IS_SET(set, _CLOCK_NAME_SET)) {
4395 _BT_LOGE_DUP_ATTR(entry_node, "name", "clock class");
4396 ret = -EPERM;
4397 goto error;
4398 }
4399
4400 right = concatenate_unary_strings(
4401 &entry_node->u.ctf_expression.right);
4402 if (!right) {
4403 _BT_LOGE_NODE(entry_node,
4404 "Unexpected unary expression for clock class's `name` attribute.");
4405 ret = -EINVAL;
4406 goto error;
4407 }
4408
4409 ret = bt_private_clock_class_set_name(clock, right);
4410 if (ret) {
4411 _BT_LOGE_NODE(entry_node,
4412 "cannot set clock class's name");
4413 g_free(right);
4414 goto error;
4415 }
4416
4417 g_free(right);
4418 _SET(set, _CLOCK_NAME_SET);
4419 } else if (!strcmp(left, "uuid")) {
4420 uint8_t uuid[BABELTRACE_UUID_LEN];
4421
4422 if (_IS_SET(set, _CLOCK_UUID_SET)) {
4423 _BT_LOGE_DUP_ATTR(entry_node, "uuid", "clock class");
4424 ret = -EPERM;
4425 goto error;
4426 }
4427
4428 ret = get_unary_uuid(&entry_node->u.ctf_expression.right, uuid);
4429 if (ret) {
4430 _BT_LOGE_NODE(entry_node,
4431 "Invalid clock class's `uuid` attribute.");
4432 goto error;
4433 }
4434
4435 bt_private_clock_class_set_uuid(clock, uuid);
4436 _SET(set, _CLOCK_UUID_SET);
4437 } else if (!strcmp(left, "description")) {
4438 char *right;
4439
4440 if (_IS_SET(set, _CLOCK_DESCRIPTION_SET)) {
4441 _BT_LOGE_DUP_ATTR(entry_node, "description",
4442 "clock class");
4443 ret = -EPERM;
4444 goto error;
4445 }
4446
4447 right = concatenate_unary_strings(
4448 &entry_node->u.ctf_expression.right);
4449 if (!right) {
4450 _BT_LOGE_NODE(entry_node,
4451 "Unexpected unary expression for clock class's `description` attribute.");
4452 ret = -EINVAL;
4453 goto error;
4454 }
4455
4456 ret = bt_private_clock_class_set_description(clock, right);
4457 if (ret) {
4458 _BT_LOGE_NODE(entry_node,
4459 "Cannot set clock class's description.");
4460 g_free(right);
4461 goto error;
4462 }
4463
4464 g_free(right);
4465 _SET(set, _CLOCK_DESCRIPTION_SET);
4466 } else if (!strcmp(left, "freq")) {
4467 uint64_t freq = UINT64_C(-1);
4468
4469 if (_IS_SET(set, _CLOCK_FREQ_SET)) {
4470 _BT_LOGE_DUP_ATTR(entry_node, "freq", "clock class");
4471 ret = -EPERM;
4472 goto error;
4473 }
4474
4475 ret = get_unary_unsigned(
4476 &entry_node->u.ctf_expression.right, &freq);
4477 if (ret) {
4478 _BT_LOGE_NODE(entry_node,
4479 "Unexpected unary expression for clock class's `freq` attribute.");
4480 ret = -EINVAL;
4481 goto error;
4482 }
4483
4484 if (freq == UINT64_C(-1) || freq == 0) {
4485 _BT_LOGE_NODE(entry_node,
4486 "Invalid clock class frequency: freq=%" PRIu64,
4487 freq);
4488 ret = -EINVAL;
4489 goto error;
4490 }
4491
4492 bt_private_clock_class_set_frequency(clock, freq);
4493 _SET(set, _CLOCK_FREQ_SET);
4494 } else if (!strcmp(left, "precision")) {
4495 uint64_t precision;
4496
4497 if (_IS_SET(set, _CLOCK_PRECISION_SET)) {
4498 _BT_LOGE_DUP_ATTR(entry_node, "precision",
4499 "clock class");
4500 ret = -EPERM;
4501 goto error;
4502 }
4503
4504 ret = get_unary_unsigned(
4505 &entry_node->u.ctf_expression.right, &precision);
4506 if (ret) {
4507 _BT_LOGE_NODE(entry_node,
4508 "Unexpected unary expression for clock class's `precision` attribute.");
4509 ret = -EINVAL;
4510 goto error;
4511 }
4512
4513 bt_private_clock_class_set_precision(clock, precision);
4514 _SET(set, _CLOCK_PRECISION_SET);
4515 } else if (!strcmp(left, "offset_s")) {
4516 if (_IS_SET(set, _CLOCK_OFFSET_S_SET)) {
4517 _BT_LOGE_DUP_ATTR(entry_node, "offset_s",
4518 "clock class");
4519 ret = -EPERM;
4520 goto error;
4521 }
4522
4523 ret = get_unary_signed(
4524 &entry_node->u.ctf_expression.right, offset_seconds);
4525 if (ret) {
4526 _BT_LOGE_NODE(entry_node,
4527 "Unexpected unary expression for clock class's `offset_s` attribute.");
4528 ret = -EINVAL;
4529 goto error;
4530 }
4531
4532 _SET(set, _CLOCK_OFFSET_S_SET);
4533 } else if (!strcmp(left, "offset")) {
4534 if (_IS_SET(set, _CLOCK_OFFSET_SET)) {
4535 _BT_LOGE_DUP_ATTR(entry_node, "offset", "clock class");
4536 ret = -EPERM;
4537 goto error;
4538 }
4539
4540 ret = get_unary_unsigned(
4541 &entry_node->u.ctf_expression.right, offset_cycles);
4542 if (ret) {
4543 _BT_LOGE_NODE(entry_node,
4544 "Unexpected unary expression for clock class's `offset` attribute.");
4545 ret = -EINVAL;
4546 goto error;
4547 }
4548
4549 _SET(set, _CLOCK_OFFSET_SET);
4550 } else if (!strcmp(left, "absolute")) {
4551 struct ctf_node *right;
4552
4553 if (_IS_SET(set, _CLOCK_ABSOLUTE_SET)) {
4554 _BT_LOGE_DUP_ATTR(entry_node, "absolute",
4555 "clock class");
4556 ret = -EPERM;
4557 goto error;
4558 }
4559
4560 right = _BT_LIST_FIRST_ENTRY(
4561 &entry_node->u.ctf_expression.right,
4562 struct ctf_node, siblings);
4563 ret = get_boolean(right);
4564 if (ret < 0) {
4565 _BT_LOGE_NODE(entry_node,
4566 "Unexpected unary expression for clock class's `absolute` attribute.");
4567 ret = -EINVAL;
4568 goto error;
4569 }
4570
4571 bt_private_clock_class_set_is_absolute(clock, ret);
4572 _SET(set, _CLOCK_ABSOLUTE_SET);
4573 } else {
4574 _BT_LOGW_NODE(entry_node,
4575 "Unknown attribute in clock class: attr-name=\"%s\"",
4576 left);
4577 }
4578
4579 g_free(left);
4580 left = NULL;
4581 return 0;
4582
4583 error:
4584 g_free(left);
4585 return ret;
4586 }
4587
4588 static inline
4589 uint64_t cycles_from_ns(uint64_t frequency, uint64_t ns)
4590 {
4591 uint64_t cycles;
4592
4593 /* 1GHz */
4594 if (frequency == UINT64_C(1000000000)) {
4595 cycles = ns;
4596 } else {
4597 cycles = (uint64_t) (((double) ns * (double) frequency) / 1e9);
4598 }
4599
4600 return cycles;
4601 }
4602
4603 static
4604 void calibrate_clock_class_offsets(int64_t *offset_seconds,
4605 uint64_t *offset_cycles, uint64_t freq)
4606 {
4607 if (*offset_cycles >= freq) {
4608 const uint64_t s_in_offset_cycles = *offset_cycles / freq;
4609
4610 *offset_seconds += (int64_t) s_in_offset_cycles;
4611 *offset_cycles -= (s_in_offset_cycles * freq);
4612 }
4613 }
4614
4615 static
4616 void apply_clock_class_offset(struct ctx *ctx,
4617 struct bt_private_clock_class *clock)
4618 {
4619 uint64_t freq;
4620 int64_t offset_s_to_apply = ctx->decoder_config.clock_class_offset_s;
4621 uint64_t offset_ns_to_apply;
4622 int64_t cur_offset_s;
4623 uint64_t cur_offset_cycles;
4624
4625 if (ctx->decoder_config.clock_class_offset_s == 0 &&
4626 ctx->decoder_config.clock_class_offset_ns == 0) {
4627 goto end;
4628 }
4629
4630 /* Transfer nanoseconds to seconds as much as possible */
4631 if (ctx->decoder_config.clock_class_offset_ns < 0) {
4632 const int64_t abs_ns = -ctx->decoder_config.clock_class_offset_ns;
4633 const int64_t abs_extra_s = abs_ns / INT64_C(1000000000) + 1;
4634 const int64_t extra_s = -abs_extra_s;
4635 const int64_t offset_ns = ctx->decoder_config.clock_class_offset_ns -
4636 (extra_s * INT64_C(1000000000));
4637
4638 BT_ASSERT(offset_ns > 0);
4639 offset_ns_to_apply = (uint64_t) offset_ns;
4640 offset_s_to_apply += extra_s;
4641 } else {
4642 const int64_t extra_s = ctx->decoder_config.clock_class_offset_ns /
4643 INT64_C(1000000000);
4644 const int64_t offset_ns = ctx->decoder_config.clock_class_offset_ns -
4645 (extra_s * INT64_C(1000000000));
4646
4647 BT_ASSERT(offset_ns >= 0);
4648 offset_ns_to_apply = (uint64_t) offset_ns;
4649 offset_s_to_apply += extra_s;
4650 }
4651
4652 freq = bt_clock_class_get_frequency(
4653 bt_private_clock_class_borrow_clock_class(clock));
4654 bt_clock_class_get_offset(bt_private_clock_class_borrow_clock_class(clock),
4655 &cur_offset_s, &cur_offset_cycles);
4656
4657 /* Apply offsets */
4658 cur_offset_s += offset_s_to_apply;
4659 cur_offset_cycles += cycles_from_ns(freq, offset_ns_to_apply);
4660
4661 /*
4662 * Recalibrate offsets because the part in cycles can be greater
4663 * than the frequency at this point.
4664 */
4665 calibrate_clock_class_offsets(&cur_offset_s, &cur_offset_cycles, freq);
4666
4667 /* Set final offsets */
4668 bt_private_clock_class_set_offset(clock, cur_offset_s, cur_offset_cycles);
4669
4670 end:
4671 return;
4672 }
4673
4674 static
4675 int visit_clock_decl(struct ctx *ctx, struct ctf_node *clock_node)
4676 {
4677 int ret = 0;
4678 int set = 0;
4679 struct bt_private_clock_class *clock;
4680 struct ctf_node *entry_node;
4681 struct bt_list_head *decl_list = &clock_node->u.clock.declaration_list;
4682 const char *clock_class_name;
4683 int64_t offset_seconds = 0;
4684 uint64_t offset_cycles = 0;
4685 uint64_t freq;
4686
4687 if (clock_node->visited) {
4688 return 0;
4689 }
4690
4691 clock_node->visited = TRUE;
4692
4693 /* CTF 1.8's default frequency for a clock class is 1 GHz */
4694 clock = bt_private_clock_class_create();
4695 if (!clock) {
4696 _BT_LOGE_NODE(clock_node,
4697 "Cannot create default clock class.");
4698 ret = -ENOMEM;
4699 goto end;
4700 }
4701
4702 /* CTF: not absolute by default */
4703 bt_private_clock_class_set_is_absolute(clock, BT_FALSE);
4704
4705 bt_list_for_each_entry(entry_node, decl_list, siblings) {
4706 ret = visit_clock_decl_entry(ctx, entry_node, clock, &set,
4707 &offset_seconds, &offset_cycles);
4708 if (ret) {
4709 _BT_LOGE_NODE(entry_node,
4710 "Cannot visit clock class's entry: ret=%d",
4711 ret);
4712 goto end;
4713 }
4714 }
4715
4716 if (!_IS_SET(&set, _CLOCK_NAME_SET)) {
4717 _BT_LOGE_NODE(clock_node,
4718 "Missing `name` attribute in clock class.");
4719 ret = -EPERM;
4720 goto end;
4721 }
4722
4723 clock_class_name = bt_clock_class_get_name(
4724 bt_private_clock_class_borrow_clock_class(clock));
4725 BT_ASSERT(clock_class_name);
4726 if (ctx->is_lttng && strcmp(clock_class_name, "monotonic") == 0) {
4727 /*
4728 * Old versions of LTTng forgot to set its clock class
4729 * as absolute, even if it is. This is important because
4730 * it's a condition to be able to sort notifications
4731 * from different sources.
4732 */
4733 bt_private_clock_class_set_is_absolute(clock, BT_TRUE);
4734 }
4735
4736 /*
4737 * Adjust offsets so that the part in cycles is less than the
4738 * frequency (move to the part in seconds).
4739 */
4740 freq = bt_clock_class_get_frequency(
4741 bt_private_clock_class_borrow_clock_class(clock));
4742 calibrate_clock_class_offsets(&offset_seconds, &offset_cycles, freq);
4743 BT_ASSERT(offset_cycles < bt_clock_class_get_frequency(
4744 bt_private_clock_class_borrow_clock_class(clock)));
4745 bt_private_clock_class_set_offset(clock, offset_seconds, offset_cycles);
4746 apply_clock_class_offset(ctx, clock);
4747 g_ptr_array_add(ctx->ctf_tc->clock_classes, 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_private_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 return bt_object_get_ref(ctx->trace);
4906 }
4907
4908 BT_HIDDEN
4909 struct ctf_trace_class *ctf_visitor_generate_ir_borrow_ctf_trace_class(
4910 struct ctf_visitor_generate_ir *visitor)
4911 {
4912 struct ctx *ctx = (void *) visitor;
4913
4914 BT_ASSERT(ctx);
4915 BT_ASSERT(ctx->ctf_tc);
4916 return ctx->ctf_tc;
4917 }
4918
4919 BT_HIDDEN
4920 int ctf_visitor_generate_ir_visit_node(struct ctf_visitor_generate_ir *visitor,
4921 struct ctf_node *node)
4922 {
4923 int ret = 0;
4924 struct ctx *ctx = (void *) visitor;
4925
4926 BT_LOGI_STR("Visiting metadata's AST to generate CTF IR objects.");
4927
4928 switch (node->type) {
4929 case NODE_ROOT:
4930 {
4931 struct ctf_node *iter;
4932 bool got_trace_decl = false;
4933
4934 /*
4935 * The first thing we need is the native byte order of
4936 * the trace block, because early class aliases can have
4937 * a `byte_order` attribute set to `native`. If we don't
4938 * have the native byte order yet, and we don't have any
4939 * trace block yet, then fail with EINCOMPLETE.
4940 */
4941 if (ctx->ctf_tc->default_byte_order == -1) {
4942 bt_list_for_each_entry(iter, &node->u.root.trace, siblings) {
4943 if (got_trace_decl) {
4944 _BT_LOGE_NODE(node,
4945 "Duplicate trace (`trace` block).");
4946 ret = -1;
4947 goto end;
4948 }
4949
4950 ret = set_trace_byte_order(ctx, iter);
4951 if (ret) {
4952 _BT_LOGE_NODE(node,
4953 "Cannot set trace's native byte order: "
4954 "ret=%d", ret);
4955 goto end;
4956 }
4957
4958 got_trace_decl = true;
4959 }
4960
4961 if (!got_trace_decl) {
4962 BT_LOGD_STR("Incomplete AST: need trace (`trace` block).");
4963 ret = -EINCOMPLETE;
4964 goto end;
4965 }
4966 }
4967
4968 BT_ASSERT(ctx->ctf_tc->default_byte_order == CTF_BYTE_ORDER_LITTLE ||
4969 ctx->ctf_tc->default_byte_order == CTF_BYTE_ORDER_BIG);
4970 BT_ASSERT(ctx->current_scope &&
4971 ctx->current_scope->parent_scope == NULL);
4972
4973 /* Environment */
4974 bt_list_for_each_entry(iter, &node->u.root.env, siblings) {
4975 ret = visit_env(ctx, iter);
4976 if (ret) {
4977 _BT_LOGE_NODE(iter,
4978 "Cannot visit trace's environment (`env` block) entry: "
4979 "ret=%d", ret);
4980 goto end;
4981 }
4982 }
4983
4984 BT_ASSERT(ctx->current_scope &&
4985 ctx->current_scope->parent_scope == NULL);
4986
4987 /*
4988 * Visit clock blocks.
4989 */
4990 bt_list_for_each_entry(iter, &node->u.root.clock, siblings) {
4991 ret = visit_clock_decl(ctx, iter);
4992 if (ret) {
4993 _BT_LOGE_NODE(iter,
4994 "Cannot visit clock class: ret=%d",
4995 ret);
4996 goto end;
4997 }
4998 }
4999
5000 BT_ASSERT(ctx->current_scope &&
5001 ctx->current_scope->parent_scope == NULL);
5002
5003 /*
5004 * Visit root declarations next, as they can be used by any
5005 * following entity.
5006 */
5007 bt_list_for_each_entry(iter, &node->u.root.declaration_list,
5008 siblings) {
5009 ret = visit_root_decl(ctx, iter);
5010 if (ret) {
5011 _BT_LOGE_NODE(iter,
5012 "Cannot visit root entry: ret=%d",
5013 ret);
5014 goto end;
5015 }
5016 }
5017
5018 BT_ASSERT(ctx->current_scope &&
5019 ctx->current_scope->parent_scope == NULL);
5020
5021 /* Callsite blocks are not supported */
5022 bt_list_for_each_entry(iter, &node->u.root.callsite, siblings) {
5023 _BT_LOGW_NODE(iter,
5024 "\"callsite\" blocks are not supported as of this version.");
5025 }
5026
5027 BT_ASSERT(ctx->current_scope &&
5028 ctx->current_scope->parent_scope == NULL);
5029
5030 /* Trace */
5031 bt_list_for_each_entry(iter, &node->u.root.trace, siblings) {
5032 ret = visit_trace_decl(ctx, iter);
5033 if (ret) {
5034 _BT_LOGE_NODE(iter,
5035 "Cannot visit trace (`trace` block): "
5036 "ret=%d", ret);
5037 goto end;
5038 }
5039 }
5040
5041 BT_ASSERT(ctx->current_scope &&
5042 ctx->current_scope->parent_scope == NULL);
5043
5044 /* Streams */
5045 bt_list_for_each_entry(iter, &node->u.root.stream, siblings) {
5046 ret = visit_stream_decl(ctx, iter);
5047 if (ret) {
5048 _BT_LOGE_NODE(iter,
5049 "Cannot visit stream class: ret=%d",
5050 ret);
5051 goto end;
5052 }
5053 }
5054
5055 BT_ASSERT(ctx->current_scope &&
5056 ctx->current_scope->parent_scope == NULL);
5057
5058 /* Events */
5059 bt_list_for_each_entry(iter, &node->u.root.event, siblings) {
5060 ret = visit_event_decl(ctx, iter);
5061 if (ret) {
5062 _BT_LOGE_NODE(iter,
5063 "Cannot visit event class: ret=%d",
5064 ret);
5065 goto end;
5066 }
5067 }
5068
5069 BT_ASSERT(ctx->current_scope &&
5070 ctx->current_scope->parent_scope == NULL);
5071 break;
5072 }
5073 default:
5074 _BT_LOGE_NODE(node,
5075 "Unexpected node type: node-type=%d",
5076 node->type);
5077 ret = -EINVAL;
5078 goto end;
5079 }
5080
5081 /* Update default clock classes */
5082 ret = ctf_trace_class_update_default_clock_classes(ctx->ctf_tc);
5083 if (ret) {
5084 ret = -EINVAL;
5085 goto end;
5086 }
5087
5088 /* Set trace's name, if not already done */
5089 ret = try_set_trace_class_name(ctx);
5090 if (ret) {
5091 ret = -EINVAL;
5092 goto end;
5093 }
5094
5095 /* Update trace class meanings */
5096 ret = ctf_trace_class_update_meanings(ctx->ctf_tc);
5097 if (ret) {
5098 ret = -EINVAL;
5099 goto end;
5100 }
5101
5102 /* Update text arrays and sequences */
5103 ret = ctf_trace_class_update_text_array_sequence(ctx->ctf_tc);
5104 if (ret) {
5105 ret = -EINVAL;
5106 goto end;
5107 }
5108
5109 /* Resolve sequence lengths and variant tags */
5110 ret = ctf_trace_class_resolve_field_classes(ctx->ctf_tc);
5111 if (ret) {
5112 ret = -EINVAL;
5113 goto end;
5114 }
5115
5116 /* Update "in IR" for field classes */
5117 ret = ctf_trace_class_update_in_ir(ctx->ctf_tc);
5118 if (ret) {
5119 ret = -EINVAL;
5120 goto end;
5121 }
5122
5123 /* Update saved value indexes */
5124 ret = ctf_trace_class_update_value_storing_indexes(ctx->ctf_tc);
5125 if (ret) {
5126 ret = -EINVAL;
5127 goto end;
5128 }
5129
5130 /* Validate what we have so far */
5131 ret = ctf_trace_class_validate(ctx->ctf_tc);
5132 if (ret) {
5133 ret = -EINVAL;
5134 goto end;
5135 }
5136
5137 /* Copy new CTF metadata -> new IR metadata */
5138 ret = ctf_trace_class_translate(ctx->trace, ctx->ctf_tc);
5139 if (ret) {
5140 ret = -EINVAL;
5141 goto end;
5142 }
5143
5144 end:
5145 return ret;
5146 }
This page took 0.201075 seconds and 4 git commands to generate.