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