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