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