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