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