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