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