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