Fix: plugin-so.c: dereference after `NULL` check
[babeltrace.git] / src / plugins / ctf / common / metadata / visitor-generate-ir.c
CommitLineData
e98a2d6e
PP
1/*
2 * ctf-visitor-generate-ir.c
3 *
4 * Common Trace Format metadata visitor (generates CTF IR objects).
5 *
6 * Based on older ctf-visitor-generate-io-struct.c.
7 *
8 * Copyright 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
44c440bc 9 * Copyright 2015-2018 - Philippe Proulx <philippe.proulx@efficios.com>
e98a2d6e
PP
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a copy
12 * of this software and associated documentation files (the "Software"), to deal
13 * in the Software without restriction, including without limitation the rights
14 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 * copies of the Software, and to permit persons to whom the Software is
16 * furnished to do so, subject to the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 * SOFTWARE.
28 */
29
f7b785ac
PP
30#define BT_COMP_LOG_SELF_COMP (ctx->log_cfg.self_comp)
31#define BT_LOG_OUTPUT_LEVEL (ctx->log_cfg.log_level)
350ad6c1 32#define BT_LOG_TAG "PLUGIN/CTF/META/IR-VISITOR"
d9c39b0a 33#include "logging/comp-logging.h"
08da4f77 34
e98a2d6e
PP
35#include <stdio.h>
36#include <unistd.h>
37#include <string.h>
c55a9f58 38#include <stdbool.h>
e98a2d6e
PP
39#include <stdlib.h>
40#include <ctype.h>
578e048b 41#include "common/assert.h"
e98a2d6e
PP
42#include <glib.h>
43#include <inttypes.h>
44#include <errno.h>
578e048b 45#include "common/common.h"
6162e6b7 46#include "common/uuid.h"
578e048b 47#include "compat/endian.h"
3fadfbc0 48#include <babeltrace2/babeltrace.h>
e98a2d6e 49
0746848c 50#include "logging.h"
06a626b8
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;
e2bd7d40 1012 enum ctf_byte_order bo = CTF_BYTE_ORDER_UNKNOWN;
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);
e2bd7d40 2332 if (byte_order == CTF_BYTE_ORDER_UNKNOWN) {
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);
e2bd7d40 2679 if (byte_order == CTF_BYTE_ORDER_UNKNOWN) {
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;
6da709aa 3176 bool is_log_level_known = true;
4cdfc5e8 3177 bt_event_class_log_level log_level = -1;
e98a2d6e 3178
44c440bc 3179 if (_IS_SET(set, _EVENT_LOG_LEVEL_SET)) {
f7b785ac 3180 _BT_COMP_LOGE_DUP_ATTR(node, "loglevel",
08da4f77 3181 "event class");
e98a2d6e
PP
3182 ret = -EPERM;
3183 goto error;
3184 }
3185
0746848c
PP
3186 ret = get_unary_unsigned(ctx,
3187 &node->u.ctf_expression.right, &loglevel_value);
e98a2d6e 3188 if (ret) {
f7b785ac 3189 _BT_COMP_LOGE_NODE(node,
28973adf 3190 "Unexpected unary expression for event class's `loglevel` attribute.");
e98a2d6e
PP
3191 ret = -EINVAL;
3192 goto error;
3193 }
cf76ce92
PP
3194
3195 switch (loglevel_value) {
3196 case 0:
50842bdc 3197 log_level = BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY;
cf76ce92
PP
3198 break;
3199 case 1:
50842bdc 3200 log_level = BT_EVENT_CLASS_LOG_LEVEL_ALERT;
cf76ce92
PP
3201 break;
3202 case 2:
50842bdc 3203 log_level = BT_EVENT_CLASS_LOG_LEVEL_CRITICAL;
cf76ce92
PP
3204 break;
3205 case 3:
50842bdc 3206 log_level = BT_EVENT_CLASS_LOG_LEVEL_ERROR;
cf76ce92
PP
3207 break;
3208 case 4:
50842bdc 3209 log_level = BT_EVENT_CLASS_LOG_LEVEL_WARNING;
cf76ce92
PP
3210 break;
3211 case 5:
50842bdc 3212 log_level = BT_EVENT_CLASS_LOG_LEVEL_NOTICE;
cf76ce92
PP
3213 break;
3214 case 6:
50842bdc 3215 log_level = BT_EVENT_CLASS_LOG_LEVEL_INFO;
cf76ce92
PP
3216 break;
3217 case 7:
50842bdc 3218 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM;
cf76ce92
PP
3219 break;
3220 case 8:
50842bdc 3221 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM;
cf76ce92
PP
3222 break;
3223 case 9:
50842bdc 3224 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS;
cf76ce92
PP
3225 break;
3226 case 10:
50842bdc 3227 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE;
cf76ce92
PP
3228 break;
3229 case 11:
50842bdc 3230 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT;
cf76ce92
PP
3231 break;
3232 case 12:
50842bdc 3233 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION;
cf76ce92
PP
3234 break;
3235 case 13:
50842bdc 3236 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE;
cf76ce92
PP
3237 break;
3238 case 14:
50842bdc 3239 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG;
cf76ce92
PP
3240 break;
3241 default:
6da709aa 3242 is_log_level_known = false;
f7b785ac 3243 _BT_COMP_LOGW_NODE(node, "Not setting event class's log level because its value is unknown: "
cf76ce92 3244 "log-level=%" PRIu64, loglevel_value);
c3c30b08 3245 }
cf76ce92 3246
6da709aa
JR
3247 if (is_log_level_known) {
3248 ctf_event_class_set_log_level(event_class, log_level);
c3c30b08 3249 }
cf76ce92 3250
44c440bc 3251 _SET(set, _EVENT_LOG_LEVEL_SET);
2242b43d 3252 } else if (strcmp(left, "model.emf.uri") == 0) {
e98a2d6e
PP
3253 char *right;
3254
3255 if (_IS_SET(set, _EVENT_MODEL_EMF_URI_SET)) {
f7b785ac 3256 _BT_COMP_LOGE_DUP_ATTR(node, "model.emf.uri",
28973adf 3257 "event class");
e98a2d6e
PP
3258 ret = -EPERM;
3259 goto error;
3260 }
3261
3262 right = concatenate_unary_strings(
3263 &node->u.ctf_expression.right);
3264 if (!right) {
f7b785ac 3265 _BT_COMP_LOGE_NODE(node,
28973adf 3266 "Unexpected unary expression for event class's `model.emf.uri` attribute.");
e98a2d6e
PP
3267 ret = -EINVAL;
3268 goto error;
3269 }
3270
cf76ce92 3271 if (strlen(right) == 0) {
f7b785ac 3272 _BT_COMP_LOGW_NODE(node,
cf76ce92
PP
3273 "Not setting event class's EMF URI because it's empty.");
3274 } else {
44c440bc
PP
3275 g_string_assign(event_class->emf_uri,
3276 right);
28973adf 3277 }
cf76ce92 3278
e98a2d6e
PP
3279 g_free(right);
3280 _SET(set, _EVENT_MODEL_EMF_URI_SET);
3281 } else {
f7b785ac 3282 _BT_COMP_LOGW_NODE(node,
28973adf 3283 "Unknown attribute in event class: "
08da4f77 3284 "attr-name=\"%s\"", left);
e98a2d6e
PP
3285 }
3286
3287 g_free(left);
3288 left = NULL;
3289 break;
3290 }
3291 default:
3292 ret = -EPERM;
3293 goto error;
3294 }
3295
44c440bc 3296 goto end;
e98a2d6e
PP
3297
3298error:
19bbdc9b 3299 g_free(left);
e98a2d6e 3300
44c440bc 3301end:
e98a2d6e
PP
3302 return ret;
3303}
3304
3305static
3306char *get_event_decl_name(struct ctx *ctx, struct ctf_node *node)
3307{
3308 char *left = NULL;
3309 char *name = NULL;
3310 struct ctf_node *iter;
3311 struct bt_list_head *decl_list = &node->u.event.declaration_list;
3312
3313 bt_list_for_each_entry(iter, decl_list, siblings) {
3314 if (iter->type != NODE_CTF_EXPRESSION) {
3315 continue;
3316 }
3317
3318 left = concatenate_unary_strings(&iter->u.ctf_expression.left);
3319 if (!left) {
f7b785ac 3320 _BT_COMP_LOGE_NODE(iter,
28973adf 3321 "Cannot concatenate unary strings.");
e98a2d6e
PP
3322 goto error;
3323 }
3324
2242b43d 3325 if (strcmp(left, "name") == 0) {
e98a2d6e
PP
3326 name = concatenate_unary_strings(
3327 &iter->u.ctf_expression.right);
3328 if (!name) {
f7b785ac 3329 _BT_COMP_LOGE_NODE(iter,
28973adf 3330 "Unexpected unary expression for event class's `name` attribute.");
e98a2d6e
PP
3331 goto error;
3332 }
3333 }
3334
3335 g_free(left);
3336 left = NULL;
3337
3338 if (name) {
3339 break;
3340 }
3341 }
3342
3343 return name;
3344
3345error:
3346 g_free(left);
e98a2d6e
PP
3347 return NULL;
3348}
3349
3350static
3351int visit_event_decl(struct ctx *ctx, struct ctf_node *node)
3352{
3353 int ret = 0;
3354 int set = 0;
e98a2d6e 3355 struct ctf_node *iter;
44c440bc 3356 uint64_t stream_id = 0;
e98a2d6e 3357 char *event_name = NULL;
44c440bc
PP
3358 struct ctf_event_class *event_class = NULL;
3359 struct ctf_stream_class *stream_class = NULL;
e98a2d6e 3360 struct bt_list_head *decl_list = &node->u.event.declaration_list;
1e649dff 3361 bool pop_scope = false;
e98a2d6e
PP
3362
3363 if (node->visited) {
3364 goto end;
3365 }
3366
3367 node->visited = TRUE;
3368 event_name = get_event_decl_name(ctx, node);
3369 if (!event_name) {
f7b785ac 3370 _BT_COMP_LOGE_NODE(node,
28973adf 3371 "Missing `name` attribute in event class.");
e98a2d6e
PP
3372 ret = -EPERM;
3373 goto error;
3374 }
3375
44c440bc
PP
3376 event_class = ctf_event_class_create();
3377 BT_ASSERT(event_class);
3378 g_string_assign(event_class->name, event_name);
3379 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
1e649dff
PP
3380 pop_scope = true;
3381
e98a2d6e
PP
3382 bt_list_for_each_entry(iter, decl_list, siblings) {
3383 ret = visit_event_decl_entry(ctx, iter, event_class,
3384 &stream_id, &set);
3385 if (ret) {
f7b785ac 3386 _BT_COMP_LOGE_NODE(iter, "Cannot visit event class's entry: "
28973adf 3387 "ret=%d", ret);
e98a2d6e
PP
3388 goto error;
3389 }
3390 }
3391
3392 if (!_IS_SET(&set, _EVENT_STREAM_ID_SET)) {
1e649dff
PP
3393 /*
3394 * Allow missing stream_id if there is only a single
3395 * stream class.
3396 */
44c440bc 3397 switch (ctx->ctf_tc->stream_classes->len) {
e98a2d6e 3398 case 0:
1e649dff 3399 /* Create implicit stream class if there's none */
7b4b1ba2 3400 stream_id = 0;
44c440bc
PP
3401 stream_class = ctf_stream_class_create();
3402 BT_ASSERT(stream_class);
3403 stream_class->id = stream_id;
3404 g_ptr_array_add(ctx->ctf_tc->stream_classes,
3405 stream_class);
e98a2d6e
PP
3406 break;
3407 case 1:
1e649dff 3408 /* Single stream class: get its ID */
44c440bc
PP
3409 stream_class = ctx->ctf_tc->stream_classes->pdata[0];
3410 stream_id = stream_class->id;
e98a2d6e
PP
3411 break;
3412 default:
f7b785ac 3413 _BT_COMP_LOGE_NODE(node,
28973adf 3414 "Missing `stream_id` attribute in event class.");
e98a2d6e
PP
3415 ret = -EPERM;
3416 goto error;
3417 }
3418 }
3419
1e649dff 3420 /* We have the stream ID now; get the stream class if found */
e98a2d6e 3421 if (!stream_class) {
44c440bc
PP
3422 stream_class = ctf_trace_class_borrow_stream_class_by_id(
3423 ctx->ctf_tc, stream_id);
1e649dff 3424 if (!stream_class) {
f7b785ac 3425 _BT_COMP_LOGE_NODE(node,
28973adf 3426 "Cannot find stream class at this point: "
08da4f77 3427 "id=%" PRId64, stream_id);
1e649dff
PP
3428 ret = -EINVAL;
3429 goto error;
3430 }
e98a2d6e
PP
3431 }
3432
f6ccaed9 3433 BT_ASSERT(stream_class);
1e649dff 3434
e98a2d6e
PP
3435 if (!_IS_SET(&set, _EVENT_ID_SET)) {
3436 /* Allow only one event without ID per stream */
44c440bc 3437 if (stream_class->event_classes->len != 0) {
f7b785ac 3438 _BT_COMP_LOGE_NODE(node,
28973adf 3439 "Missing `id` attribute in event class.");
e98a2d6e
PP
3440 ret = -EPERM;
3441 goto error;
3442 }
3443
3444 /* Automatic ID */
44c440bc 3445 event_class->id = 0;
e98a2d6e
PP
3446 }
3447
44c440bc
PP
3448 if (ctf_stream_class_borrow_event_class_by_id(stream_class,
3449 event_class->id)) {
f7b785ac 3450 _BT_COMP_LOGE_NODE(node,
28973adf 3451 "Duplicate event class (same ID) in the same stream class: "
44c440bc 3452 "id=%" PRId64, event_class->id);
e98a2d6e
PP
3453 ret = -EEXIST;
3454 goto error;
3455 }
3456
44c440bc
PP
3457 ctf_stream_class_append_event_class(stream_class, event_class);
3458 event_class = NULL;
1e649dff 3459 goto end;
e98a2d6e
PP
3460
3461error:
44c440bc
PP
3462 ctf_event_class_destroy(event_class);
3463 event_class = NULL;
3464
3465 if (ret >= 0) {
3466 ret = -1;
3467 }
e98a2d6e 3468
1e649dff
PP
3469end:
3470 if (pop_scope) {
3471 ctx_pop_scope(ctx);
3472 }
e98a2d6e 3473
19bbdc9b 3474 g_free(event_name);
44c440bc 3475
e98a2d6e
PP
3476 return ret;
3477}
3478
56b43721 3479static
7bf5af54 3480int auto_map_field_to_trace_clock_class(struct ctx *ctx,
5cd6d0e5 3481 struct ctf_field_class *fc)
56b43721 3482{
0f2d58c9 3483 struct ctf_clock_class *clock_class_to_map_to = NULL;
5cd6d0e5 3484 struct ctf_field_class_int *int_fc = (void *) fc;
56b43721 3485 int ret = 0;
44c440bc
PP
3486 uint64_t clock_class_count;
3487
5cd6d0e5 3488 if (!fc) {
44c440bc
PP
3489 goto end;
3490 }
56b43721 3491
864cad70
PP
3492 if (fc->type != CTF_FIELD_CLASS_TYPE_INT &&
3493 fc->type != CTF_FIELD_CLASS_TYPE_ENUM) {
56b43721
PP
3494 goto end;
3495 }
3496
5cd6d0e5 3497 if (int_fc->mapped_clock_class) {
44c440bc 3498 /* Already mapped */
56b43721
PP
3499 goto end;
3500 }
3501
44c440bc 3502 clock_class_count = ctx->ctf_tc->clock_classes->len;
7bf5af54
PP
3503
3504 switch (clock_class_count) {
3505 case 0:
3506 /*
44c440bc
PP
3507 * No clock class exists in the trace at this point. Create an
3508 * implicit one at 1 GHz, named `default`, and use this clock
3509 * class.
7bf5af54 3510 */
0f2d58c9 3511 clock_class_to_map_to = ctf_clock_class_create();
44c440bc 3512 BT_ASSERT(clock_class_to_map_to);
0f2d58c9
PP
3513 clock_class_to_map_to->frequency = UINT64_C(1000000000);
3514 g_string_assign(clock_class_to_map_to->name, "default");
44c440bc
PP
3515 BT_ASSERT(ret == 0);
3516 g_ptr_array_add(ctx->ctf_tc->clock_classes,
398454ed 3517 clock_class_to_map_to);
7bf5af54
PP
3518 break;
3519 case 1:
3520 /*
44c440bc
PP
3521 * Only one clock class exists in the trace at this point: use
3522 * this one.
7bf5af54 3523 */
398454ed 3524 clock_class_to_map_to = ctx->ctf_tc->clock_classes->pdata[0];
7bf5af54
PP
3525 break;
3526 default:
3527 /*
44c440bc
PP
3528 * Timestamp field not mapped to a clock class and there's more
3529 * than one clock class in the trace: this is an error.
7bf5af54 3530 */
f7b785ac 3531 BT_COMP_LOGE_STR("Timestamp field found with no mapped clock class, "
7bf5af54
PP
3532 "but there's more than one clock class in the trace at this point.");
3533 ret = -1;
56b43721
PP
3534 goto end;
3535 }
3536
f6ccaed9 3537 BT_ASSERT(clock_class_to_map_to);
398454ed 3538 int_fc->mapped_clock_class = clock_class_to_map_to;
56b43721 3539
7bf5af54 3540end:
7bf5af54
PP
3541 return ret;
3542}
56b43721 3543
7bf5af54
PP
3544static
3545int auto_map_fields_to_trace_clock_class(struct ctx *ctx,
5cd6d0e5 3546 struct ctf_field_class *root_fc, const char *field_name)
7bf5af54
PP
3547{
3548 int ret = 0;
44c440bc 3549 uint64_t i, count;
5cd6d0e5
PP
3550 struct ctf_field_class_struct *struct_fc = (void *) root_fc;
3551 struct ctf_field_class_variant *var_fc = (void *) root_fc;
56b43721 3552
5cd6d0e5 3553 if (!root_fc) {
7bf5af54
PP
3554 goto end;
3555 }
56b43721 3556
864cad70
PP
3557 if (root_fc->type != CTF_FIELD_CLASS_TYPE_STRUCT &&
3558 root_fc->type != CTF_FIELD_CLASS_TYPE_VARIANT) {
7bf5af54
PP
3559 goto end;
3560 }
3561
864cad70 3562 if (root_fc->type == CTF_FIELD_CLASS_TYPE_STRUCT) {
5cd6d0e5 3563 count = struct_fc->members->len;
7bf5af54 3564 } else {
5cd6d0e5 3565 count = var_fc->options->len;
7bf5af54
PP
3566 }
3567
7bf5af54 3568 for (i = 0; i < count; i++) {
5cd6d0e5 3569 struct ctf_named_field_class *named_fc = NULL;
7bf5af54 3570
864cad70 3571 if (root_fc->type == CTF_FIELD_CLASS_TYPE_STRUCT) {
5cd6d0e5
PP
3572 named_fc = ctf_field_class_struct_borrow_member_by_index(
3573 struct_fc, i);
864cad70 3574 } else if (root_fc->type == CTF_FIELD_CLASS_TYPE_VARIANT) {
5cd6d0e5
PP
3575 named_fc = ctf_field_class_variant_borrow_option_by_index(
3576 var_fc, i);
7bf5af54
PP
3577 }
3578
5cd6d0e5 3579 if (strcmp(named_fc->name->str, field_name) == 0) {
44c440bc 3580 ret = auto_map_field_to_trace_clock_class(ctx,
5cd6d0e5 3581 named_fc->fc);
7bf5af54 3582 if (ret) {
f7b785ac 3583 BT_COMP_LOGE("Cannot automatically map field to trace's clock class: "
7bf5af54 3584 "field-name=\"%s\"", field_name);
7bf5af54 3585 goto end;
56b43721
PP
3586 }
3587 }
3588
5cd6d0e5 3589 ret = auto_map_fields_to_trace_clock_class(ctx, named_fc->fc,
44c440bc 3590 field_name);
7bf5af54 3591 if (ret) {
f7b785ac 3592 BT_COMP_LOGE("Cannot automatically map structure or variant field class's fields to trace's clock class: "
7bf5af54 3593 "field-name=\"%s\", root-field-name=\"%s\"",
5cd6d0e5 3594 field_name, named_fc->name->str);
7bf5af54
PP
3595 goto end;
3596 }
56b43721
PP
3597 }
3598
3599end:
56b43721
PP
3600 return ret;
3601}
3602
e98a2d6e
PP
3603static
3604int visit_stream_decl_entry(struct ctx *ctx, struct ctf_node *node,
44c440bc 3605 struct ctf_stream_class *stream_class, int *set)
e98a2d6e
PP
3606{
3607 int ret = 0;
3608 char *left = NULL;
e98a2d6e
PP
3609
3610 switch (node->type) {
3611 case NODE_TYPEDEF:
5cd6d0e5
PP
3612 ret = visit_field_class_def(ctx, node->u.field_class_def.field_class_specifier_list,
3613 &node->u.field_class_def.field_class_declarators);
e98a2d6e 3614 if (ret) {
f7b785ac 3615 _BT_COMP_LOGE_NODE(node,
5cd6d0e5 3616 "Cannot add field class found in stream class.");
e98a2d6e
PP
3617 goto error;
3618 }
3619 break;
3620 case NODE_TYPEALIAS:
5cd6d0e5
PP
3621 ret = visit_field_class_alias(ctx, node->u.field_class_alias.target,
3622 node->u.field_class_alias.alias);
e98a2d6e 3623 if (ret) {
f7b785ac 3624 _BT_COMP_LOGE_NODE(node,
5cd6d0e5 3625 "Cannot add field class alias found in stream class.");
e98a2d6e
PP
3626 goto error;
3627 }
3628 break;
3629 case NODE_CTF_EXPRESSION:
3630 {
3631 left = concatenate_unary_strings(&node->u.ctf_expression.left);
3632 if (!left) {
f7b785ac 3633 _BT_COMP_LOGE_NODE(node, "Cannot concatenate unary strings.");
e98a2d6e
PP
3634 ret = -EINVAL;
3635 goto error;
3636 }
3637
2242b43d 3638 if (strcmp(left, "id") == 0) {
e98a2d6e 3639 int64_t id;
e98a2d6e
PP
3640
3641 if (_IS_SET(set, _STREAM_ID_SET)) {
f7b785ac 3642 _BT_COMP_LOGE_DUP_ATTR(node, "id",
28973adf 3643 "stream declaration");
e98a2d6e
PP
3644 ret = -EPERM;
3645 goto error;
3646 }
3647
0746848c
PP
3648 ret = get_unary_unsigned(ctx,
3649 &node->u.ctf_expression.right,
e98a2d6e 3650 (uint64_t *) &id);
44c440bc 3651
5eae0c3c
JG
3652 /* Only read "id" if get_unary_unsigned() succeeded. */
3653 if (ret || (!ret && id < 0)) {
f7b785ac 3654 _BT_COMP_LOGE_NODE(node,
28973adf 3655 "Unexpected unary expression for stream class's `id` attribute.");
e98a2d6e
PP
3656 ret = -EINVAL;
3657 goto error;
3658 }
3659
44c440bc
PP
3660 if (ctf_trace_class_borrow_stream_class_by_id(
3661 ctx->ctf_tc, id)) {
f7b785ac 3662 _BT_COMP_LOGE_NODE(node,
28973adf 3663 "Duplicate stream class (same ID): id=%" PRId64,
e98a2d6e
PP
3664 id);
3665 ret = -EEXIST;
3666 goto error;
3667 }
3668
44c440bc 3669 stream_class->id = id;
e98a2d6e 3670 _SET(set, _STREAM_ID_SET);
2242b43d 3671 } else if (strcmp(left, "event.header") == 0) {
e98a2d6e 3672 if (_IS_SET(set, _STREAM_EVENT_HEADER_SET)) {
f7b785ac 3673 _BT_COMP_LOGE_NODE(node,
28973adf 3674 "Duplicate `event.header` entry in stream class.");
e98a2d6e
PP
3675 ret = -EPERM;
3676 goto error;
3677 }
3678
5cd6d0e5 3679 ret = visit_field_class_specifier_list(ctx,
e98a2d6e
PP
3680 _BT_LIST_FIRST_ENTRY(
3681 &node->u.ctf_expression.right,
3682 struct ctf_node, siblings),
5cd6d0e5 3683 &stream_class->event_header_fc);
e98a2d6e 3684 if (ret) {
f7b785ac 3685 _BT_COMP_LOGE_NODE(node,
5cd6d0e5 3686 "Cannot create stream class's event header field class.");
e98a2d6e
PP
3687 goto error;
3688 }
3689
5cd6d0e5 3690 BT_ASSERT(stream_class->event_header_fc);
56b43721 3691 ret = auto_map_fields_to_trace_clock_class(ctx,
5cd6d0e5 3692 stream_class->event_header_fc, "timestamp");
56b43721 3693 if (ret) {
f7b785ac 3694 _BT_COMP_LOGE_NODE(node,
5cd6d0e5 3695 "Cannot automatically map specific event header field class fields named `timestamp` to trace's clock class.");
56b43721
PP
3696 goto error;
3697 }
e98a2d6e 3698
e98a2d6e 3699 _SET(set, _STREAM_EVENT_HEADER_SET);
2242b43d 3700 } else if (strcmp(left, "event.context") == 0) {
e98a2d6e 3701 if (_IS_SET(set, _STREAM_EVENT_CONTEXT_SET)) {
f7b785ac 3702 _BT_COMP_LOGE_NODE(node,
28973adf 3703 "Duplicate `event.context` entry in stream class.");
e98a2d6e
PP
3704 ret = -EPERM;
3705 goto error;
3706 }
3707
5cd6d0e5 3708 ret = visit_field_class_specifier_list(ctx,
e98a2d6e
PP
3709 _BT_LIST_FIRST_ENTRY(
3710 &node->u.ctf_expression.right,
3711 struct ctf_node, siblings),
5cd6d0e5 3712 &stream_class->event_common_context_fc);
e98a2d6e 3713 if (ret) {
f7b785ac 3714 _BT_COMP_LOGE_NODE(node,
5cd6d0e5 3715 "Cannot create stream class's event context field class.");
e98a2d6e
PP
3716 goto error;
3717 }
3718
5cd6d0e5 3719 BT_ASSERT(stream_class->event_common_context_fc);
e98a2d6e 3720 _SET(set, _STREAM_EVENT_CONTEXT_SET);
2242b43d 3721 } else if (strcmp(left, "packet.context") == 0) {
e98a2d6e 3722 if (_IS_SET(set, _STREAM_PACKET_CONTEXT_SET)) {
f7b785ac 3723 _BT_COMP_LOGE_NODE(node,
28973adf 3724 "Duplicate `packet.context` entry in stream class.");
e98a2d6e
PP
3725 ret = -EPERM;
3726 goto error;
3727 }
3728
5cd6d0e5 3729 ret = visit_field_class_specifier_list(ctx,
e98a2d6e
PP
3730 _BT_LIST_FIRST_ENTRY(
3731 &node->u.ctf_expression.right,
3732 struct ctf_node, siblings),
5cd6d0e5 3733 &stream_class->packet_context_fc);
e98a2d6e 3734 if (ret) {
f7b785ac 3735 _BT_COMP_LOGE_NODE(node,
5cd6d0e5 3736 "Cannot create stream class's packet context field class.");
e98a2d6e
PP
3737 goto error;
3738 }
3739
5cd6d0e5 3740 BT_ASSERT(stream_class->packet_context_fc);
56b43721 3741 ret = auto_map_fields_to_trace_clock_class(ctx,
5cd6d0e5 3742 stream_class->packet_context_fc,
44c440bc 3743 "timestamp_begin");
7bf5af54 3744 if (ret) {
f7b785ac 3745 _BT_COMP_LOGE_NODE(node,
5cd6d0e5 3746 "Cannot automatically map specific packet context field class fields named `timestamp_begin` to trace's clock class.");
7bf5af54
PP
3747 goto error;
3748 }
3749
3750 ret = auto_map_fields_to_trace_clock_class(ctx,
5cd6d0e5 3751 stream_class->packet_context_fc,
44c440bc 3752 "timestamp_end");
56b43721 3753 if (ret) {
f7b785ac 3754 _BT_COMP_LOGE_NODE(node,
5cd6d0e5 3755 "Cannot automatically map specific packet context field class fields named `timestamp_end` to trace's clock class.");
56b43721
PP
3756 goto error;
3757 }
e98a2d6e 3758
e98a2d6e
PP
3759 _SET(set, _STREAM_PACKET_CONTEXT_SET);
3760 } else {
f7b785ac 3761 _BT_COMP_LOGW_NODE(node,
28973adf 3762 "Unknown attribute in stream class: "
08da4f77 3763 "attr-name=\"%s\"", left);
e98a2d6e
PP
3764 }
3765
3766 g_free(left);
3767 left = NULL;
3768 break;
3769 }
3770
3771 default:
3772 ret = -EPERM;
3773 goto error;
3774 }
3775
3776 return 0;
3777
3778error:
3779 g_free(left);
e98a2d6e
PP
3780 return ret;
3781}
3782
3783static
3784int visit_stream_decl(struct ctx *ctx, struct ctf_node *node)
3785{
e98a2d6e
PP
3786 int set = 0;
3787 int ret = 0;
3788 struct ctf_node *iter;
44c440bc 3789 struct ctf_stream_class *stream_class = NULL;
e98a2d6e
PP
3790 struct bt_list_head *decl_list = &node->u.stream.declaration_list;
3791
3792 if (node->visited) {
3793 goto end;
3794 }
3795
3796 node->visited = TRUE;
44c440bc
PP
3797 stream_class = ctf_stream_class_create();
3798 BT_ASSERT(stream_class);
3799 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
e98a2d6e
PP
3800
3801 bt_list_for_each_entry(iter, decl_list, siblings) {
3802 ret = visit_stream_decl_entry(ctx, iter, stream_class, &set);
3803 if (ret) {
f7b785ac 3804 _BT_COMP_LOGE_NODE(iter,
28973adf
PP
3805 "Cannot visit stream class's entry: "
3806 "ret=%d", ret);
e98a2d6e
PP
3807 ctx_pop_scope(ctx);
3808 goto error;
3809 }
3810 }
3811
3812 ctx_pop_scope(ctx);
3813
3814 if (_IS_SET(&set, _STREAM_ID_SET)) {
44c440bc 3815 /* Check that packet header has `stream_id` field */
5cd6d0e5 3816 struct ctf_named_field_class *named_fc = NULL;
e98a2d6e 3817
5cd6d0e5 3818 if (!ctx->ctf_tc->packet_header_fc) {
f7b785ac 3819 _BT_COMP_LOGE_NODE(node,
28973adf 3820 "Stream class has a `id` attribute, "
5cd6d0e5 3821 "but trace has no packet header field class.");
e98a2d6e
PP
3822 goto error;
3823 }
3824
5cd6d0e5
PP
3825 named_fc = ctf_field_class_struct_borrow_member_by_name(
3826 (void *) ctx->ctf_tc->packet_header_fc, "stream_id");
3827 if (!named_fc) {
f7b785ac 3828 _BT_COMP_LOGE_NODE(node,
28973adf 3829 "Stream class has a `id` attribute, "
5cd6d0e5 3830 "but trace's packet header field class has no `stream_id` field.");
e98a2d6e
PP
3831 goto error;
3832 }
3833
864cad70
PP
3834 if (named_fc->fc->type != CTF_FIELD_CLASS_TYPE_INT &&
3835 named_fc->fc->type != CTF_FIELD_CLASS_TYPE_ENUM) {
f7b785ac 3836 _BT_COMP_LOGE_NODE(node,
28973adf 3837 "Stream class has a `id` attribute, "
5cd6d0e5 3838 "but trace's packet header field class's `stream_id` field is not an integer field class.");
e98a2d6e
PP
3839 goto error;
3840 }
e98a2d6e
PP
3841 } else {
3842 /* Allow only _one_ ID-less stream */
44c440bc 3843 if (ctx->ctf_tc->stream_classes->len != 0) {
f7b785ac 3844 _BT_COMP_LOGE_NODE(node,
28973adf 3845 "Missing `id` attribute in stream class as there's more than one stream class in the trace.");
e98a2d6e
PP
3846 ret = -EPERM;
3847 goto error;
3848 }
3849
3850 /* Automatic ID: 0 */
44c440bc 3851 stream_class->id = 0;
e98a2d6e
PP
3852 }
3853
1e649dff
PP
3854 /*
3855 * Make sure that this stream class's ID is currently unique in
3856 * the trace.
3857 */
44c440bc
PP
3858 if (ctf_trace_class_borrow_stream_class_by_id(ctx->ctf_tc,
3859 stream_class->id)) {
f7b785ac 3860 _BT_COMP_LOGE_NODE(node,
28973adf 3861 "Duplicate stream class (same ID): id=%" PRId64,
44c440bc 3862 stream_class->id);
1e649dff
PP
3863 ret = -EINVAL;
3864 goto error;
3865 }
3866
44c440bc 3867 g_ptr_array_add(ctx->ctf_tc->stream_classes, stream_class);
e98a2d6e 3868 stream_class = NULL;
1e649dff 3869 goto end;
e98a2d6e
PP
3870
3871error:
44c440bc
PP
3872 ctf_stream_class_destroy(stream_class);
3873 stream_class = NULL;
e98a2d6e 3874
1e649dff 3875end:
e98a2d6e
PP
3876 return ret;
3877}
3878
3879static
3880int visit_trace_decl_entry(struct ctx *ctx, struct ctf_node *node, int *set)
3881{
3882 int ret = 0;
3883 char *left = NULL;
44c440bc 3884 uint64_t val;
e98a2d6e
PP
3885
3886 switch (node->type) {
3887 case NODE_TYPEDEF:
5cd6d0e5
PP
3888 ret = visit_field_class_def(ctx, node->u.field_class_def.field_class_specifier_list,
3889 &node->u.field_class_def.field_class_declarators);
e98a2d6e 3890 if (ret) {
f7b785ac 3891 _BT_COMP_LOGE_NODE(node,
5cd6d0e5 3892 "Cannot add field class found in trace (`trace` block).");
e98a2d6e
PP
3893 goto error;
3894 }
3895 break;
3896 case NODE_TYPEALIAS:
5cd6d0e5
PP
3897 ret = visit_field_class_alias(ctx, node->u.field_class_alias.target,
3898 node->u.field_class_alias.alias);
e98a2d6e 3899 if (ret) {
f7b785ac 3900 _BT_COMP_LOGE_NODE(node,
5cd6d0e5 3901 "Cannot add field class alias found in trace (`trace` block).");
e98a2d6e
PP
3902 goto error;
3903 }
3904 break;
3905 case NODE_CTF_EXPRESSION:
3906 {
3907 left = concatenate_unary_strings(&node->u.ctf_expression.left);
3908 if (!left) {
f7b785ac 3909 _BT_COMP_LOGE_NODE(node, "Cannot concatenate unary strings.");
e98a2d6e
PP
3910 ret = -EINVAL;
3911 goto error;
3912 }
3913
2242b43d 3914 if (strcmp(left, "major") == 0) {
e98a2d6e 3915 if (_IS_SET(set, _TRACE_MAJOR_SET)) {
f7b785ac 3916 _BT_COMP_LOGE_DUP_ATTR(node, "major", "trace");
e98a2d6e
PP
3917 ret = -EPERM;
3918 goto error;
3919 }
3920
0746848c
PP
3921 ret = get_unary_unsigned(ctx,
3922 &node->u.ctf_expression.right, &val);
e98a2d6e 3923 if (ret) {
f7b785ac 3924 _BT_COMP_LOGE_NODE(node,
28973adf 3925 "Unexpected unary expression for trace's `major` attribute.");
e98a2d6e
PP
3926 ret = -EINVAL;
3927 goto error;
3928 }
3929
44c440bc 3930 if (val != 1) {
f7b785ac 3931 _BT_COMP_LOGE_NODE(node,
44c440bc
PP
3932 "Invalid trace's `minor` attribute: expecting 1.");
3933 goto error;
3934 }
3935
3936 ctx->ctf_tc->major = val;
e98a2d6e 3937 _SET(set, _TRACE_MAJOR_SET);
2242b43d 3938 } else if (strcmp(left, "minor") == 0) {
e98a2d6e 3939 if (_IS_SET(set, _TRACE_MINOR_SET)) {
f7b785ac 3940 _BT_COMP_LOGE_DUP_ATTR(node, "minor", "trace");
e98a2d6e
PP
3941 ret = -EPERM;
3942 goto error;
3943 }
3944
0746848c
PP
3945 ret = get_unary_unsigned(ctx,
3946 &node->u.ctf_expression.right, &val);
e98a2d6e 3947 if (ret) {
f7b785ac 3948 _BT_COMP_LOGE_NODE(node,
28973adf 3949 "Unexpected unary expression for trace's `minor` attribute.");
e98a2d6e
PP
3950 ret = -EINVAL;
3951 goto error;
3952 }
3953
44c440bc 3954 if (val != 8) {
f7b785ac 3955 _BT_COMP_LOGE_NODE(node,
44c440bc
PP
3956 "Invalid trace's `minor` attribute: expecting 8.");
3957 goto error;
3958 }
3959
3960 ctx->ctf_tc->minor = val;
e98a2d6e 3961 _SET(set, _TRACE_MINOR_SET);
2242b43d 3962 } else if (strcmp(left, "uuid") == 0) {
e98a2d6e 3963 if (_IS_SET(set, _TRACE_UUID_SET)) {
f7b785ac 3964 _BT_COMP_LOGE_DUP_ATTR(node, "uuid", "trace");
e98a2d6e
PP
3965 ret = -EPERM;
3966 goto error;
3967 }
3968
0746848c
PP
3969 ret = get_unary_uuid(ctx,
3970 &node->u.ctf_expression.right,
44c440bc 3971 ctx->ctf_tc->uuid);
e98a2d6e 3972 if (ret) {
f7b785ac 3973 _BT_COMP_LOGE_NODE(node,
28973adf 3974 "Invalid trace's `uuid` attribute.");
e98a2d6e
PP
3975 goto error;
3976 }
3977
44c440bc 3978 ctx->ctf_tc->is_uuid_set = true;
e98a2d6e 3979 _SET(set, _TRACE_UUID_SET);
2242b43d 3980 } else if (strcmp(left, "byte_order") == 0) {
44c440bc 3981 /* Default byte order is already known at this stage */
e98a2d6e 3982 if (_IS_SET(set, _TRACE_BYTE_ORDER_SET)) {
f7b785ac 3983 _BT_COMP_LOGE_DUP_ATTR(node, "byte_order",
08da4f77 3984 "trace");
e98a2d6e
PP
3985 ret = -EPERM;
3986 goto error;
3987 }
3988
e2bd7d40 3989 BT_ASSERT(ctx->ctf_tc->default_byte_order != CTF_BYTE_ORDER_UNKNOWN);
e98a2d6e 3990 _SET(set, _TRACE_BYTE_ORDER_SET);
2242b43d 3991 } else if (strcmp(left, "packet.header") == 0) {
e98a2d6e 3992 if (_IS_SET(set, _TRACE_PACKET_HEADER_SET)) {
f7b785ac 3993 _BT_COMP_LOGE_NODE(node,
28973adf 3994 "Duplicate `packet.header` entry in trace.");
e98a2d6e
PP
3995 ret = -EPERM;
3996 goto error;
3997 }
3998
5cd6d0e5 3999 ret = visit_field_class_specifier_list(ctx,
e98a2d6e
PP
4000 _BT_LIST_FIRST_ENTRY(
4001 &node->u.ctf_expression.right,
4002 struct ctf_node, siblings),
5cd6d0e5 4003 &ctx->ctf_tc->packet_header_fc);
e98a2d6e 4004 if (ret) {
f7b785ac 4005 _BT_COMP_LOGE_NODE(node,
5cd6d0e5 4006 "Cannot create trace's packet header field class.");
e98a2d6e
PP
4007 goto error;
4008 }
4009
5cd6d0e5 4010 BT_ASSERT(ctx->ctf_tc->packet_header_fc);
e98a2d6e
PP
4011 _SET(set, _TRACE_PACKET_HEADER_SET);
4012 } else {
f7b785ac 4013 _BT_COMP_LOGW_NODE(node,
28973adf 4014 "Unknown attribute in stream class: "
08da4f77 4015 "attr-name=\"%s\"", left);
e98a2d6e
PP
4016 }
4017
4018 g_free(left);
4019 left = NULL;
4020 break;
4021 }
4022 default:
f7b785ac 4023 _BT_COMP_LOGE_NODE(node, "Unknown expression in trace.");
e98a2d6e
PP
4024 ret = -EINVAL;
4025 goto error;
4026 }
4027
4028 return 0;
4029
4030error:
4031 g_free(left);
e98a2d6e
PP
4032 return ret;
4033}
4034
4035static
4036int visit_trace_decl(struct ctx *ctx, struct ctf_node *node)
4037{
4038 int ret = 0;
4039 int set = 0;
4040 struct ctf_node *iter;
4041 struct bt_list_head *decl_list = &node->u.trace.declaration_list;
4042
4043 if (node->visited) {
4044 goto end;
4045 }
4046
4047 node->visited = TRUE;
4048
4049 if (ctx->is_trace_visited) {
f7b785ac 4050 _BT_COMP_LOGE_NODE(node, "Duplicate trace (`trace` block).");
e98a2d6e
PP
4051 ret = -EEXIST;
4052 goto error;
4053 }
4054
44c440bc 4055 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
e98a2d6e
PP
4056
4057 bt_list_for_each_entry(iter, decl_list, siblings) {
4058 ret = visit_trace_decl_entry(ctx, iter, &set);
4059 if (ret) {
f7b785ac 4060 _BT_COMP_LOGE_NODE(iter, "Cannot visit trace's entry (`trace` block): "
28973adf 4061 "ret=%d", ret);
e98a2d6e
PP
4062 ctx_pop_scope(ctx);
4063 goto error;
4064 }
4065 }
4066
4067 ctx_pop_scope(ctx);
4068
4069 if (!_IS_SET(&set, _TRACE_MAJOR_SET)) {
f7b785ac 4070 _BT_COMP_LOGE_NODE(node,
28973adf 4071 "Missing `major` attribute in trace (`trace` block).");
e98a2d6e
PP
4072 ret = -EPERM;
4073 goto error;
4074 }
4075
4076 if (!_IS_SET(&set, _TRACE_MINOR_SET)) {
f7b785ac 4077 _BT_COMP_LOGE_NODE(node,
28973adf 4078 "Missing `minor` attribute in trace (`trace` block).");
e98a2d6e
PP
4079 ret = -EPERM;
4080 goto error;
4081 }
4082
4083 if (!_IS_SET(&set, _TRACE_BYTE_ORDER_SET)) {
f7b785ac 4084 _BT_COMP_LOGE_NODE(node,
28973adf 4085 "Missing `byte_order` attribute in trace (`trace` block).");
e98a2d6e
PP
4086 ret = -EPERM;
4087 goto error;
4088 }
4089
44c440bc 4090 ctx->is_trace_visited = true;
e98a2d6e
PP
4091
4092end:
4093 return 0;
4094
4095error:
4096 return ret;
4097}
4098
4099static
4100int visit_env(struct ctx *ctx, struct ctf_node *node)
4101{
4102 int ret = 0;
4103 char *left = NULL;
4104 struct ctf_node *entry_node;
4105 struct bt_list_head *decl_list = &node->u.env.declaration_list;
4106
4107 if (node->visited) {
4108 goto end;
4109 }
4110
4111 node->visited = TRUE;
4112
4113 bt_list_for_each_entry(entry_node, decl_list, siblings) {
4114 struct bt_list_head *right_head =
4115 &entry_node->u.ctf_expression.right;
4116
4117 if (entry_node->type != NODE_CTF_EXPRESSION) {
f7b785ac 4118 _BT_COMP_LOGE_NODE(entry_node,
28973adf 4119 "Wrong expression in environment entry: "
08da4f77 4120 "node-type=%d", entry_node->type);
e98a2d6e
PP
4121 ret = -EPERM;
4122 goto error;
4123 }
4124
4125 left = concatenate_unary_strings(
4126 &entry_node->u.ctf_expression.left);
4127 if (!left) {
f7b785ac 4128 _BT_COMP_LOGE_NODE(entry_node,
28973adf 4129 "Cannot get environment entry's name.");
e98a2d6e
PP
4130 ret = -EINVAL;
4131 goto error;
4132 }
4133
4134 if (is_unary_string(right_head)) {
4135 char *right = concatenate_unary_strings(right_head);
4136
4137 if (!right) {
f7b785ac 4138 _BT_COMP_LOGE_NODE(entry_node,
28973adf 4139 "Unexpected unary expression for environment entry's value: "
08da4f77 4140 "name=\"%s\"", left);
e98a2d6e
PP
4141 ret = -EINVAL;
4142 goto error;
4143 }
4144
7bf5af54
PP
4145 if (strcmp(left, "tracer_name") == 0) {
4146 if (strncmp(right, "lttng", 5) == 0) {
f7b785ac 4147 BT_COMP_LOGI("Detected LTTng trace from `%s` environment value: "
7bf5af54
PP
4148 "tracer-name=\"%s\"",
4149 left, right);
44c440bc 4150 ctx->is_lttng = true;
f4421ff3
PP
4151 }
4152 }
4153
44c440bc
PP
4154 ctf_trace_class_append_env_entry(ctx->ctf_tc,
4155 left, CTF_TRACE_CLASS_ENV_ENTRY_TYPE_STR,
4156 right, 0);
e98a2d6e 4157 g_free(right);
e98a2d6e
PP
4158 } else if (is_unary_unsigned(right_head) ||
4159 is_unary_signed(right_head)) {
4160 int64_t v;
4161
4162 if (is_unary_unsigned(right_head)) {
0746848c 4163 ret = get_unary_unsigned(ctx, right_head,
e98a2d6e
PP
4164 (uint64_t *) &v);
4165 } else {
4166 ret = get_unary_signed(right_head, &v);
4167 }
4168 if (ret) {
f7b785ac 4169 _BT_COMP_LOGE_NODE(entry_node,
28973adf 4170 "Unexpected unary expression for environment entry's value: "
08da4f77 4171 "name=\"%s\"", left);
e98a2d6e
PP
4172 ret = -EINVAL;
4173 goto error;
4174 }
4175
44c440bc
PP
4176 ctf_trace_class_append_env_entry(ctx->ctf_tc,
4177 left, CTF_TRACE_CLASS_ENV_ENTRY_TYPE_INT,
4178 NULL, v);
e98a2d6e 4179 } else {
f7b785ac 4180 _BT_COMP_LOGW_NODE(entry_node,
28973adf 4181 "Environment entry has unknown type: "
08da4f77 4182 "name=\"%s\"", left);
e98a2d6e
PP
4183 }
4184
4185 g_free(left);
4186 left = NULL;
4187 }
4188
4189end:
4190 return 0;
4191
4192error:
4193 g_free(left);
e98a2d6e
PP
4194 return ret;
4195}
4196
4197static
4198int set_trace_byte_order(struct ctx *ctx, struct ctf_node *trace_node)
4199{
4200 int ret = 0;
4201 int set = 0;
4202 char *left = NULL;
4203 struct ctf_node *node;
4204 struct bt_list_head *decl_list = &trace_node->u.trace.declaration_list;
4205
4206 bt_list_for_each_entry(node, decl_list, siblings) {
4207 if (node->type == NODE_CTF_EXPRESSION) {
4208 struct ctf_node *right_node;
4209
4210 left = concatenate_unary_strings(
4211 &node->u.ctf_expression.left);
4212 if (!left) {
f7b785ac 4213 _BT_COMP_LOGE_NODE(node,
28973adf 4214 "Cannot concatenate unary strings.");
e98a2d6e
PP
4215 ret = -EINVAL;
4216 goto error;
4217 }
4218
2242b43d 4219 if (strcmp(left, "byte_order") == 0) {
44c440bc 4220 enum ctf_byte_order bo;
e98a2d6e
PP
4221
4222 if (_IS_SET(&set, _TRACE_BYTE_ORDER_SET)) {
f7b785ac 4223 _BT_COMP_LOGE_DUP_ATTR(node, "byte_order",
08da4f77 4224 "trace");
e98a2d6e
PP
4225 ret = -EPERM;
4226 goto error;
4227 }
4228
4229 _SET(&set, _TRACE_BYTE_ORDER_SET);
4230 right_node = _BT_LIST_FIRST_ENTRY(
4231 &node->u.ctf_expression.right,
4232 struct ctf_node, siblings);
0746848c
PP
4233 bo = byte_order_from_unary_expr(ctx,
4234 right_node);
e2bd7d40 4235 if (bo == CTF_BYTE_ORDER_UNKNOWN) {
f7b785ac 4236 _BT_COMP_LOGE_NODE(node,
28973adf
PP
4237 "Invalid `byte_order` attribute in trace (`trace` block): "
4238 "expecting `le`, `be`, or `network`.");
e98a2d6e
PP
4239 ret = -EINVAL;
4240 goto error;
44c440bc 4241 } else if (bo == CTF_BYTE_ORDER_DEFAULT) {
f7b785ac 4242 _BT_COMP_LOGE_NODE(node,
28973adf 4243 "Invalid `byte_order` attribute in trace (`trace` block): "
08da4f77 4244 "cannot be set to `native` here.");
e98a2d6e
PP
4245 ret = -EPERM;
4246 goto error;
4247 }
4248
44c440bc 4249 ctx->ctf_tc->default_byte_order = bo;
e98a2d6e
PP
4250 }
4251
4252 g_free(left);
4253 left = NULL;
4254 }
4255 }
4256
4257 if (!_IS_SET(&set, _TRACE_BYTE_ORDER_SET)) {
f7b785ac 4258 _BT_COMP_LOGE_NODE(trace_node,
28973adf 4259 "Missing `byte_order` attribute in trace (`trace` block).");
e98a2d6e
PP
4260 ret = -EINVAL;
4261 goto error;
4262 }
4263
4264 return 0;
4265
4266error:
4267 g_free(left);
e98a2d6e
PP
4268 return ret;
4269}
4270
4271static
4272int visit_clock_decl_entry(struct ctx *ctx, struct ctf_node *entry_node,
0f2d58c9 4273 struct ctf_clock_class *clock, int *set, int64_t *offset_seconds,
44c440bc 4274 uint64_t *offset_cycles)
e98a2d6e
PP
4275{
4276 int ret = 0;
4277 char *left = NULL;
4278
4279 if (entry_node->type != NODE_CTF_EXPRESSION) {
f7b785ac 4280 _BT_COMP_LOGE_NODE(entry_node,
28973adf
PP
4281 "Unexpected node type: node-type=%d",
4282 entry_node->type);
e98a2d6e
PP
4283 ret = -EPERM;
4284 goto error;
4285 }
4286
4287 left = concatenate_unary_strings(&entry_node->u.ctf_expression.left);
4288 if (!left) {
f7b785ac 4289 _BT_COMP_LOGE_NODE(entry_node, "Cannot concatenate unary strings.");
e98a2d6e
PP
4290 ret = -EINVAL;
4291 goto error;
4292 }
4293
2242b43d 4294 if (strcmp(left, "name") == 0) {
e98a2d6e
PP
4295 char *right;
4296
4297 if (_IS_SET(set, _CLOCK_NAME_SET)) {
f7b785ac 4298 _BT_COMP_LOGE_DUP_ATTR(entry_node, "name", "clock class");
e98a2d6e
PP
4299 ret = -EPERM;
4300 goto error;
4301 }
4302
4303 right = concatenate_unary_strings(
4304 &entry_node->u.ctf_expression.right);
4305 if (!right) {
f7b785ac 4306 _BT_COMP_LOGE_NODE(entry_node,
28973adf 4307 "Unexpected unary expression for clock class's `name` attribute.");
e98a2d6e
PP
4308 ret = -EINVAL;
4309 goto error;
4310 }
4311
0f2d58c9 4312 g_string_assign(clock->name, right);
e98a2d6e
PP
4313 g_free(right);
4314 _SET(set, _CLOCK_NAME_SET);
2242b43d 4315 } else if (strcmp(left, "uuid") == 0) {
6162e6b7 4316 bt_uuid_t uuid;
e98a2d6e
PP
4317
4318 if (_IS_SET(set, _CLOCK_UUID_SET)) {
f7b785ac 4319 _BT_COMP_LOGE_DUP_ATTR(entry_node, "uuid", "clock class");
e98a2d6e
PP
4320 ret = -EPERM;
4321 goto error;
4322 }
4323
0746848c
PP
4324 ret = get_unary_uuid(ctx, &entry_node->u.ctf_expression.right,
4325 uuid);
e98a2d6e 4326 if (ret) {
f7b785ac 4327 _BT_COMP_LOGE_NODE(entry_node,
28973adf 4328 "Invalid clock class's `uuid` attribute.");
e98a2d6e
PP
4329 goto error;
4330 }
4331
0f2d58c9 4332 clock->has_uuid = true;
6162e6b7 4333 bt_uuid_copy(clock->uuid, uuid);
e98a2d6e 4334 _SET(set, _CLOCK_UUID_SET);
2242b43d 4335 } else if (strcmp(left, "description") == 0) {
e98a2d6e
PP
4336 char *right;
4337
4338 if (_IS_SET(set, _CLOCK_DESCRIPTION_SET)) {
f7b785ac 4339 _BT_COMP_LOGE_DUP_ATTR(entry_node, "description",
28973adf 4340 "clock class");
e98a2d6e
PP
4341 ret = -EPERM;
4342 goto error;
4343 }
4344
4345 right = concatenate_unary_strings(
4346 &entry_node->u.ctf_expression.right);
4347 if (!right) {
f7b785ac 4348 _BT_COMP_LOGE_NODE(entry_node,
28973adf 4349 "Unexpected unary expression for clock class's `description` attribute.");
e98a2d6e
PP
4350 ret = -EINVAL;
4351 goto error;
4352 }
4353
0f2d58c9 4354 g_string_assign(clock->description, right);
e98a2d6e
PP
4355 g_free(right);
4356 _SET(set, _CLOCK_DESCRIPTION_SET);
2242b43d 4357 } else if (strcmp(left, "freq") == 0) {
44c440bc 4358 uint64_t freq = UINT64_C(-1);
e98a2d6e
PP
4359
4360 if (_IS_SET(set, _CLOCK_FREQ_SET)) {
f7b785ac 4361 _BT_COMP_LOGE_DUP_ATTR(entry_node, "freq", "clock class");
e98a2d6e
PP
4362 ret = -EPERM;
4363 goto error;
4364 }
4365
0746848c 4366 ret = get_unary_unsigned(ctx,
e98a2d6e
PP
4367 &entry_node->u.ctf_expression.right, &freq);
4368 if (ret) {
f7b785ac 4369 _BT_COMP_LOGE_NODE(entry_node,
28973adf 4370 "Unexpected unary expression for clock class's `freq` attribute.");
e98a2d6e
PP
4371 ret = -EINVAL;
4372 goto error;
4373 }
4374
44c440bc 4375 if (freq == UINT64_C(-1) || freq == 0) {
f7b785ac 4376 _BT_COMP_LOGE_NODE(entry_node,
239744fc
PP
4377 "Invalid clock class frequency: freq=%" PRIu64,
4378 freq);
4379 ret = -EINVAL;
4380 goto error;
4381 }
4382
0f2d58c9 4383 clock->frequency = freq;
e98a2d6e 4384 _SET(set, _CLOCK_FREQ_SET);
2242b43d 4385 } else if (strcmp(left, "precision") == 0) {
e98a2d6e
PP
4386 uint64_t precision;
4387
4388 if (_IS_SET(set, _CLOCK_PRECISION_SET)) {
f7b785ac 4389 _BT_COMP_LOGE_DUP_ATTR(entry_node, "precision",
28973adf 4390 "clock class");
e98a2d6e
PP
4391 ret = -EPERM;
4392 goto error;
4393 }
4394
0746848c 4395 ret = get_unary_unsigned(ctx,
e98a2d6e
PP
4396 &entry_node->u.ctf_expression.right, &precision);
4397 if (ret) {
f7b785ac 4398 _BT_COMP_LOGE_NODE(entry_node,
28973adf 4399 "Unexpected unary expression for clock class's `precision` attribute.");
e98a2d6e
PP
4400 ret = -EINVAL;
4401 goto error;
4402 }
4403
0f2d58c9 4404 clock->precision = precision;
e98a2d6e 4405 _SET(set, _CLOCK_PRECISION_SET);
2242b43d 4406 } else if (strcmp(left, "offset_s") == 0) {
e98a2d6e 4407 if (_IS_SET(set, _CLOCK_OFFSET_S_SET)) {
f7b785ac 4408 _BT_COMP_LOGE_DUP_ATTR(entry_node, "offset_s",
28973adf 4409 "clock class");
e98a2d6e
PP
4410 ret = -EPERM;
4411 goto error;
4412 }
4413
fb4ac437 4414 ret = get_unary_signed(
44c440bc 4415 &entry_node->u.ctf_expression.right, offset_seconds);
e98a2d6e 4416 if (ret) {
f7b785ac 4417 _BT_COMP_LOGE_NODE(entry_node,
28973adf 4418 "Unexpected unary expression for clock class's `offset_s` attribute.");
e98a2d6e
PP
4419 ret = -EINVAL;
4420 goto error;
4421 }
4422
e98a2d6e 4423 _SET(set, _CLOCK_OFFSET_S_SET);
2242b43d 4424 } else if (strcmp(left, "offset") == 0) {
e98a2d6e 4425 if (_IS_SET(set, _CLOCK_OFFSET_SET)) {
f7b785ac 4426 _BT_COMP_LOGE_DUP_ATTR(entry_node, "offset", "clock class");
e98a2d6e
PP
4427 ret = -EPERM;
4428 goto error;
4429 }
4430
0746848c 4431 ret = get_unary_unsigned(ctx,
44c440bc 4432 &entry_node->u.ctf_expression.right, offset_cycles);
e98a2d6e 4433 if (ret) {
f7b785ac 4434 _BT_COMP_LOGE_NODE(entry_node,
28973adf 4435 "Unexpected unary expression for clock class's `offset` attribute.");
e98a2d6e
PP
4436 ret = -EINVAL;
4437 goto error;
4438 }
4439
e98a2d6e 4440 _SET(set, _CLOCK_OFFSET_SET);
2242b43d 4441 } else if (strcmp(left, "absolute") == 0) {
e98a2d6e
PP
4442 struct ctf_node *right;
4443
4444 if (_IS_SET(set, _CLOCK_ABSOLUTE_SET)) {
f7b785ac 4445 _BT_COMP_LOGE_DUP_ATTR(entry_node, "absolute",
28973adf 4446 "clock class");
e98a2d6e
PP
4447 ret = -EPERM;
4448 goto error;
4449 }
4450
4451 right = _BT_LIST_FIRST_ENTRY(
4452 &entry_node->u.ctf_expression.right,
4453 struct ctf_node, siblings);
0746848c 4454 ret = get_boolean(ctx, right);
e98a2d6e 4455 if (ret < 0) {
f7b785ac 4456 _BT_COMP_LOGE_NODE(entry_node,
28973adf 4457 "Unexpected unary expression for clock class's `absolute` attribute.");
e98a2d6e
PP
4458 ret = -EINVAL;
4459 goto error;
4460 }
4461
0f2d58c9 4462 clock->is_absolute = ret;
e98a2d6e
PP
4463 _SET(set, _CLOCK_ABSOLUTE_SET);
4464 } else {
f7b785ac 4465 _BT_COMP_LOGW_NODE(entry_node,
28973adf 4466 "Unknown attribute in clock class: attr-name=\"%s\"",
e98a2d6e
PP
4467 left);
4468 }
4469
4470 g_free(left);
4471 left = NULL;
e98a2d6e
PP
4472 return 0;
4473
4474error:
4475 g_free(left);
e98a2d6e
PP
4476 return ret;
4477}
4478
44c440bc
PP
4479static inline
4480uint64_t cycles_from_ns(uint64_t frequency, uint64_t ns)
92540773 4481{
44c440bc 4482 uint64_t cycles;
92540773
JD
4483
4484 /* 1GHz */
44c440bc 4485 if (frequency == UINT64_C(1000000000)) {
92540773
JD
4486 cycles = ns;
4487 } else {
4488 cycles = (uint64_t) (((double) ns * (double) frequency) / 1e9);
4489 }
4490
4491 return cycles;
4492}
4493
4494static
44c440bc
PP
4495void calibrate_clock_class_offsets(int64_t *offset_seconds,
4496 uint64_t *offset_cycles, uint64_t freq)
4497{
4498 if (*offset_cycles >= freq) {
4499 const uint64_t s_in_offset_cycles = *offset_cycles / freq;
4500
4501 *offset_seconds += (int64_t) s_in_offset_cycles;
4502 *offset_cycles -= (s_in_offset_cycles * freq);
4503 }
4504}
4505
4506static
e5be10ef 4507void apply_clock_class_offset(struct ctx *ctx,
0f2d58c9 4508 struct ctf_clock_class *clock)
92540773 4509{
92540773 4510 uint64_t freq;
44c440bc
PP
4511 int64_t offset_s_to_apply = ctx->decoder_config.clock_class_offset_s;
4512 uint64_t offset_ns_to_apply;
4513 int64_t cur_offset_s;
4514 uint64_t cur_offset_cycles;
92540773 4515
44c440bc
PP
4516 if (ctx->decoder_config.clock_class_offset_s == 0 &&
4517 ctx->decoder_config.clock_class_offset_ns == 0) {
92540773
JD
4518 goto end;
4519 }
4520
44c440bc
PP
4521 /* Transfer nanoseconds to seconds as much as possible */
4522 if (ctx->decoder_config.clock_class_offset_ns < 0) {
4523 const int64_t abs_ns = -ctx->decoder_config.clock_class_offset_ns;
4524 const int64_t abs_extra_s = abs_ns / INT64_C(1000000000) + 1;
4525 const int64_t extra_s = -abs_extra_s;
4526 const int64_t offset_ns = ctx->decoder_config.clock_class_offset_ns -
4527 (extra_s * INT64_C(1000000000));
4528
4529 BT_ASSERT(offset_ns > 0);
4530 offset_ns_to_apply = (uint64_t) offset_ns;
4531 offset_s_to_apply += extra_s;
4532 } else {
4533 const int64_t extra_s = ctx->decoder_config.clock_class_offset_ns /
4534 INT64_C(1000000000);
4535 const int64_t offset_ns = ctx->decoder_config.clock_class_offset_ns -
4536 (extra_s * INT64_C(1000000000));
4537
4538 BT_ASSERT(offset_ns >= 0);
4539 offset_ns_to_apply = (uint64_t) offset_ns;
4540 offset_s_to_apply += extra_s;
92540773
JD
4541 }
4542
0f2d58c9
PP
4543 freq = clock->frequency;
4544 cur_offset_s = clock->offset_seconds;
4545 cur_offset_cycles = clock->offset_cycles;
44c440bc
PP
4546
4547 /* Apply offsets */
4548 cur_offset_s += offset_s_to_apply;
4549 cur_offset_cycles += cycles_from_ns(freq, offset_ns_to_apply);
4550
4551 /*
4552 * Recalibrate offsets because the part in cycles can be greater
4553 * than the frequency at this point.
4554 */
4555 calibrate_clock_class_offsets(&cur_offset_s, &cur_offset_cycles, freq);
4556
4557 /* Set final offsets */
0f2d58c9
PP
4558 clock->offset_seconds = cur_offset_s;
4559 clock->offset_cycles = cur_offset_cycles;
92540773
JD
4560
4561end:
44c440bc 4562 return;
92540773
JD
4563}
4564
4565static
1e649dff 4566int visit_clock_decl(struct ctx *ctx, struct ctf_node *clock_node)
e98a2d6e
PP
4567{
4568 int ret = 0;
4569 int set = 0;
0f2d58c9 4570 struct ctf_clock_class *clock;
e98a2d6e
PP
4571 struct ctf_node *entry_node;
4572 struct bt_list_head *decl_list = &clock_node->u.clock.declaration_list;
f4421ff3 4573 const char *clock_class_name;
44c440bc
PP
4574 int64_t offset_seconds = 0;
4575 uint64_t offset_cycles = 0;
4576 uint64_t freq;
e98a2d6e
PP
4577
4578 if (clock_node->visited) {
4579 return 0;
4580 }
4581
4582 clock_node->visited = TRUE;
f3534905
PP
4583
4584 /* CTF 1.8's default frequency for a clock class is 1 GHz */
0f2d58c9 4585 clock = ctf_clock_class_create();
e98a2d6e 4586 if (!clock) {
f7b785ac 4587 _BT_COMP_LOGE_NODE(clock_node,
28973adf 4588 "Cannot create default clock class.");
e98a2d6e 4589 ret = -ENOMEM;
44c440bc
PP
4590 goto end;
4591 }
4592
e98a2d6e 4593 bt_list_for_each_entry(entry_node, decl_list, siblings) {
44c440bc
PP
4594 ret = visit_clock_decl_entry(ctx, entry_node, clock, &set,
4595 &offset_seconds, &offset_cycles);
e98a2d6e 4596 if (ret) {
f7b785ac 4597 _BT_COMP_LOGE_NODE(entry_node,
28973adf
PP
4598 "Cannot visit clock class's entry: ret=%d",
4599 ret);
44c440bc 4600 goto end;
e98a2d6e
PP
4601 }
4602 }
4603
4604 if (!_IS_SET(&set, _CLOCK_NAME_SET)) {
f7b785ac 4605 _BT_COMP_LOGE_NODE(clock_node,
28973adf 4606 "Missing `name` attribute in clock class.");
e98a2d6e 4607 ret = -EPERM;
44c440bc 4608 goto end;
e98a2d6e
PP
4609 }
4610
0f2d58c9 4611 clock_class_name = clock->name->str;
f6ccaed9 4612 BT_ASSERT(clock_class_name);
f4421ff3
PP
4613 if (ctx->is_lttng && strcmp(clock_class_name, "monotonic") == 0) {
4614 /*
4615 * Old versions of LTTng forgot to set its clock class
4616 * as absolute, even if it is. This is important because
d6e69534 4617 * it's a condition to be able to sort messages
f4421ff3
PP
4618 * from different sources.
4619 */
0f2d58c9 4620 clock->is_absolute = true;
e98a2d6e
PP
4621 }
4622
44c440bc
PP
4623 /*
4624 * Adjust offsets so that the part in cycles is less than the
4625 * frequency (move to the part in seconds).
4626 */
0f2d58c9 4627 freq = clock->frequency;
44c440bc 4628 calibrate_clock_class_offsets(&offset_seconds, &offset_cycles, freq);
0f2d58c9
PP
4629 BT_ASSERT(offset_cycles < clock->frequency);
4630 clock->offset_seconds = offset_seconds;
4631 clock->offset_cycles = offset_cycles;
44c440bc 4632 apply_clock_class_offset(ctx, clock);
398454ed 4633 g_ptr_array_add(ctx->ctf_tc->clock_classes, clock);
0f2d58c9 4634 clock = NULL;
e98a2d6e 4635
44c440bc 4636end:
0f2d58c9
PP
4637 if (clock) {
4638 ctf_clock_class_destroy(clock);
4639 }
4640
e98a2d6e
PP
4641 return ret;
4642}
4643
4644static
4645int visit_root_decl(struct ctx *ctx, struct ctf_node *root_decl_node)
4646{
4647 int ret = 0;
4648
4649 if (root_decl_node->visited) {
4650 goto end;
4651 }
4652
4653 root_decl_node->visited = TRUE;
4654
4655 switch (root_decl_node->type) {
4656 case NODE_TYPEDEF:
5cd6d0e5
PP
4657 ret = visit_field_class_def(ctx,
4658 root_decl_node->u.field_class_def.field_class_specifier_list,
4659 &root_decl_node->u.field_class_def.field_class_declarators);
e98a2d6e 4660 if (ret) {
f7b785ac 4661 _BT_COMP_LOGE_NODE(root_decl_node,
5cd6d0e5 4662 "Cannot add field class found in root scope.");
e98a2d6e
PP
4663 goto end;
4664 }
4665 break;
4666 case NODE_TYPEALIAS:
5cd6d0e5
PP
4667 ret = visit_field_class_alias(ctx, root_decl_node->u.field_class_alias.target,
4668 root_decl_node->u.field_class_alias.alias);
e98a2d6e 4669 if (ret) {
f7b785ac 4670 _BT_COMP_LOGE_NODE(root_decl_node,
5cd6d0e5 4671 "Cannot add field class alias found in root scope.");
e98a2d6e
PP
4672 goto end;
4673 }
4674 break;
4675 case NODE_TYPE_SPECIFIER_LIST:
4676 {
5cd6d0e5 4677 struct ctf_field_class *decl = NULL;
e98a2d6e
PP
4678
4679 /*
5cd6d0e5 4680 * Just add the field class specifier to the root
e98a2d6e
PP
4681 * declaration scope. Put local reference.
4682 */
5cd6d0e5 4683 ret = visit_field_class_specifier_list(ctx, root_decl_node, &decl);
e98a2d6e 4684 if (ret) {
f7b785ac 4685 _BT_COMP_LOGE_NODE(root_decl_node,
5cd6d0e5 4686 "Cannot visit root scope's field class: "
28973adf 4687 "ret=%d", ret);
f6ccaed9 4688 BT_ASSERT(!decl);
e98a2d6e
PP
4689 goto end;
4690 }
4691
5cd6d0e5 4692 ctf_field_class_destroy(decl);
44c440bc 4693 decl = NULL;
e98a2d6e
PP
4694 break;
4695 }
4696 default:
f7b785ac 4697 _BT_COMP_LOGE_NODE(root_decl_node,
28973adf
PP
4698 "Unexpected node type: node-type=%d",
4699 root_decl_node->type);
e98a2d6e
PP
4700 ret = -EPERM;
4701 goto end;
4702 }
4703
4704end:
4705 return ret;
4706}
4707
1e649dff 4708BT_HIDDEN
55314f2a 4709struct ctf_visitor_generate_ir *ctf_visitor_generate_ir_create(
862ca4ed 4710 const struct ctf_metadata_decoder_config *decoder_config)
e98a2d6e 4711{
e98a2d6e 4712 struct ctx *ctx = NULL;
e98a2d6e 4713
1e649dff 4714 /* Create visitor's context */
f7b785ac 4715 ctx = ctx_create(decoder_config);
e98a2d6e 4716 if (!ctx) {
f7b785ac 4717 BT_COMP_LOGE_STR("Cannot create visitor's context.");
e98a2d6e
PP
4718 goto error;
4719 }
4720
1e649dff
PP
4721 goto end;
4722
4723error:
4724 ctx_destroy(ctx);
4725 ctx = NULL;
4726
4727end:
1e649dff
PP
4728 return (void *) ctx;
4729}
4730
4731BT_HIDDEN
4732void ctf_visitor_generate_ir_destroy(struct ctf_visitor_generate_ir *visitor)
4733{
4734 ctx_destroy((void *) visitor);
4735}
4736
4737BT_HIDDEN
b19ff26f 4738bt_trace_class *ctf_visitor_generate_ir_get_ir_trace_class(
1e649dff
PP
4739 struct ctf_visitor_generate_ir *visitor)
4740{
4741 struct ctx *ctx = (void *) visitor;
4742
f6ccaed9 4743 BT_ASSERT(ctx);
41693723
PP
4744
4745 if (ctx->trace_class) {
4746 bt_trace_class_get_ref(ctx->trace_class);
4747 }
4748
862ca4ed 4749 return ctx->trace_class;
1e649dff
PP
4750}
4751
44c440bc
PP
4752BT_HIDDEN
4753struct ctf_trace_class *ctf_visitor_generate_ir_borrow_ctf_trace_class(
4754 struct ctf_visitor_generate_ir *visitor)
4755{
4756 struct ctx *ctx = (void *) visitor;
4757
4758 BT_ASSERT(ctx);
4759 BT_ASSERT(ctx->ctf_tc);
4760 return ctx->ctf_tc;
4761}
4762
1e649dff
PP
4763BT_HIDDEN
4764int ctf_visitor_generate_ir_visit_node(struct ctf_visitor_generate_ir *visitor,
4765 struct ctf_node *node)
4766{
4767 int ret = 0;
4768 struct ctx *ctx = (void *) visitor;
4769
f7b785ac 4770 BT_COMP_LOGI_STR("Visiting metadata's AST to generate CTF IR objects.");
1e649dff 4771
e98a2d6e
PP
4772 switch (node->type) {
4773 case NODE_ROOT:
4774 {
4775 struct ctf_node *iter;
44c440bc 4776 bool got_trace_decl = false;
e98a2d6e
PP
4777
4778 /*
1e649dff 4779 * The first thing we need is the native byte order of
5cd6d0e5 4780 * the trace block, because early class aliases can have
1e649dff
PP
4781 * a `byte_order` attribute set to `native`. If we don't
4782 * have the native byte order yet, and we don't have any
4783 * trace block yet, then fail with EINCOMPLETE.
e98a2d6e 4784 */
e2bd7d40 4785 if (ctx->ctf_tc->default_byte_order == CTF_BYTE_ORDER_UNKNOWN) {
1e649dff
PP
4786 bt_list_for_each_entry(iter, &node->u.root.trace, siblings) {
4787 if (got_trace_decl) {
f7b785ac 4788 _BT_COMP_LOGE_NODE(node,
28973adf 4789 "Duplicate trace (`trace` block).");
1e649dff
PP
4790 ret = -1;
4791 goto end;
4792 }
e98a2d6e 4793
1e649dff
PP
4794 ret = set_trace_byte_order(ctx, iter);
4795 if (ret) {
f7b785ac 4796 _BT_COMP_LOGE_NODE(node,
28973adf 4797 "Cannot set trace's native byte order: "
08da4f77 4798 "ret=%d", ret);
1e649dff
PP
4799 goto end;
4800 }
4801
44c440bc 4802 got_trace_decl = true;
e98a2d6e
PP
4803 }
4804
1e649dff 4805 if (!got_trace_decl) {
f7b785ac 4806 BT_COMP_LOGD_STR("Incomplete AST: need trace (`trace` block).");
1e649dff
PP
4807 ret = -EINCOMPLETE;
4808 goto end;
4809 }
e98a2d6e
PP
4810 }
4811
44c440bc
PP
4812 BT_ASSERT(ctx->ctf_tc->default_byte_order == CTF_BYTE_ORDER_LITTLE ||
4813 ctx->ctf_tc->default_byte_order == CTF_BYTE_ORDER_BIG);
f6ccaed9 4814 BT_ASSERT(ctx->current_scope &&
5084732e 4815 !ctx->current_scope->parent_scope);
e98a2d6e 4816
f4421ff3
PP
4817 /* Environment */
4818 bt_list_for_each_entry(iter, &node->u.root.env, siblings) {
4819 ret = visit_env(ctx, iter);
4820 if (ret) {
f7b785ac 4821 _BT_COMP_LOGE_NODE(iter,
28973adf 4822 "Cannot visit trace's environment (`env` block) entry: "
08da4f77 4823 "ret=%d", ret);
f4421ff3
PP
4824 goto end;
4825 }
4826 }
4827
f6ccaed9 4828 BT_ASSERT(ctx->current_scope &&
5084732e 4829 !ctx->current_scope->parent_scope);
f4421ff3 4830
e98a2d6e 4831 /*
f4421ff3 4832 * Visit clock blocks.
e98a2d6e
PP
4833 */
4834 bt_list_for_each_entry(iter, &node->u.root.clock, siblings) {
1e649dff 4835 ret = visit_clock_decl(ctx, iter);
e98a2d6e 4836 if (ret) {
f7b785ac 4837 _BT_COMP_LOGE_NODE(iter,
28973adf 4838 "Cannot visit clock class: ret=%d",
e98a2d6e 4839 ret);
1e649dff 4840 goto end;
e98a2d6e
PP
4841 }
4842 }
4843
f6ccaed9 4844 BT_ASSERT(ctx->current_scope &&
5084732e 4845 !ctx->current_scope->parent_scope);
1e649dff 4846
e98a2d6e
PP
4847 /*
4848 * Visit root declarations next, as they can be used by any
4849 * following entity.
4850 */
4851 bt_list_for_each_entry(iter, &node->u.root.declaration_list,
4852 siblings) {
4853 ret = visit_root_decl(ctx, iter);
4854 if (ret) {
f7b785ac 4855 _BT_COMP_LOGE_NODE(iter,
28973adf 4856 "Cannot visit root entry: ret=%d",
e98a2d6e 4857 ret);
1e649dff 4858 goto end;
e98a2d6e
PP
4859 }
4860 }
4861
f6ccaed9 4862 BT_ASSERT(ctx->current_scope &&
5084732e 4863 !ctx->current_scope->parent_scope);
1e649dff
PP
4864
4865 /* Callsite blocks are not supported */
e98a2d6e 4866 bt_list_for_each_entry(iter, &node->u.root.callsite, siblings) {
f7b785ac 4867 _BT_COMP_LOGW_NODE(iter,
28973adf 4868 "\"callsite\" blocks are not supported as of this version.");
e98a2d6e
PP
4869 }
4870
f6ccaed9 4871 BT_ASSERT(ctx->current_scope &&
5084732e 4872 !ctx->current_scope->parent_scope);
1e649dff 4873
e98a2d6e
PP
4874 /* Trace */
4875 bt_list_for_each_entry(iter, &node->u.root.trace, siblings) {
4876 ret = visit_trace_decl(ctx, iter);
4877 if (ret) {
f7b785ac 4878 _BT_COMP_LOGE_NODE(iter,
28973adf 4879 "Cannot visit trace (`trace` block): "
08da4f77 4880 "ret=%d", ret);
1e649dff 4881 goto end;
e98a2d6e
PP
4882 }
4883 }
4884
f6ccaed9 4885 BT_ASSERT(ctx->current_scope &&
5084732e 4886 !ctx->current_scope->parent_scope);
1e649dff 4887
e98a2d6e
PP
4888 /* Streams */
4889 bt_list_for_each_entry(iter, &node->u.root.stream, siblings) {
4890 ret = visit_stream_decl(ctx, iter);
4891 if (ret) {
f7b785ac 4892 _BT_COMP_LOGE_NODE(iter,
28973adf 4893 "Cannot visit stream class: ret=%d",
08da4f77 4894 ret);
1e649dff 4895 goto end;
e98a2d6e
PP
4896 }
4897 }
4898
f6ccaed9 4899 BT_ASSERT(ctx->current_scope &&
5084732e 4900 !ctx->current_scope->parent_scope);
1e649dff 4901
e98a2d6e
PP
4902 /* Events */
4903 bt_list_for_each_entry(iter, &node->u.root.event, siblings) {
4904 ret = visit_event_decl(ctx, iter);
4905 if (ret) {
f7b785ac 4906 _BT_COMP_LOGE_NODE(iter,
28973adf 4907 "Cannot visit event class: ret=%d",
08da4f77 4908 ret);
1e649dff 4909 goto end;
e98a2d6e
PP
4910 }
4911 }
1e649dff 4912
f6ccaed9 4913 BT_ASSERT(ctx->current_scope &&
5084732e 4914 !ctx->current_scope->parent_scope);
e98a2d6e
PP
4915 break;
4916 }
e98a2d6e 4917 default:
f7b785ac 4918 _BT_COMP_LOGE_NODE(node,
28973adf 4919 "Unexpected node type: node-type=%d",
08da4f77 4920 node->type);
e98a2d6e 4921 ret = -EINVAL;
1e649dff 4922 goto end;
e98a2d6e
PP
4923 }
4924
44c440bc 4925 /* Update default clock classes */
0746848c 4926 ret = ctf_trace_class_update_default_clock_classes(ctx->ctf_tc,
f7b785ac 4927 &ctx->log_cfg);
44c440bc
PP
4928 if (ret) {
4929 ret = -EINVAL;
4930 goto end;
4931 }
4932
44c440bc
PP
4933 /* Update trace class meanings */
4934 ret = ctf_trace_class_update_meanings(ctx->ctf_tc);
4935 if (ret) {
4936 ret = -EINVAL;
4937 goto end;
4938 }
4939
afd45274
PP
4940 /* Update stream class configuration */
4941 ret = ctf_trace_class_update_stream_class_config(ctx->ctf_tc);
4942 if (ret) {
4943 ret = -EINVAL;
4944 goto end;
4945 }
4946
44c440bc
PP
4947 /* Update text arrays and sequences */
4948 ret = ctf_trace_class_update_text_array_sequence(ctx->ctf_tc);
4949 if (ret) {
4950 ret = -EINVAL;
4951 goto end;
4952 }
4953
4954 /* Resolve sequence lengths and variant tags */
f7b785ac 4955 ret = ctf_trace_class_resolve_field_classes(ctx->ctf_tc, &ctx->log_cfg);
44c440bc
PP
4956 if (ret) {
4957 ret = -EINVAL;
4958 goto end;
4959 }
4960
41693723
PP
4961 if (ctx->trace_class) {
4962 /*
4963 * Update "in IR" for field classes.
4964 *
4965 * If we have no IR trace class, then we'll have no way
4966 * to create IR fields anyway, so we leave all the
4967 * `in_ir` members false.
4968 */
4969 ret = ctf_trace_class_update_in_ir(ctx->ctf_tc);
4970 if (ret) {
4971 ret = -EINVAL;
4972 goto end;
4973 }
44c440bc
PP
4974 }
4975
4976 /* Update saved value indexes */
4977 ret = ctf_trace_class_update_value_storing_indexes(ctx->ctf_tc);
e98a2d6e 4978 if (ret) {
44c440bc
PP
4979 ret = -EINVAL;
4980 goto end;
4981 }
4982
4983 /* Validate what we have so far */
f7b785ac 4984 ret = ctf_trace_class_validate(ctx->ctf_tc, &ctx->log_cfg);
44c440bc
PP
4985 if (ret) {
4986 ret = -EINVAL;
4987 goto end;
4988 }
4989
83ebb7f1
PP
4990 /*
4991 * If there are fields which are not related to the CTF format
4992 * itself in the packet header and in event header field
4993 * classes, warn about it because they are never translated.
4994 */
0746848c 4995 ctf_trace_class_warn_meaningless_header_fields(ctx->ctf_tc,
f7b785ac 4996 &ctx->log_cfg);
83ebb7f1 4997
41693723
PP
4998 if (ctx->trace_class) {
4999 /* Copy new CTF metadata -> new IR metadata */
f7b785ac 5000 ret = ctf_trace_class_translate(ctx->log_cfg.self_comp,
7fcdb0a9 5001 ctx->trace_class, ctx->ctf_tc);
41693723
PP
5002 if (ret) {
5003 ret = -EINVAL;
5004 goto end;
5005 }
e98a2d6e
PP
5006 }
5007
1e649dff 5008end:
e98a2d6e
PP
5009 return ret;
5010}
This page took 0.37761 seconds and 4 git commands to generate.