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