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