Rename: field type -> field class
[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) */
50842bdc 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
557 bt_put(ctx->trace);
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
44c440bc
PP
593 ctx->trace = bt_trace_create();
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
5cd6d0e5 1352 if (nested_decl->id == CTF_FIELD_CLASS_ID_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
PP
1686 /* Do not allow field class def and alias of untagged variants */
1687 if (class_decl->id == CTF_FIELD_CLASS_ID_VARIANT) {
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
PP
1744 /* Do not allow field class def and alias of untagged variants */
1745 if (class_decl->id == CTF_FIELD_CLASS_ID_VARIANT) {
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
5cd6d0e5
PP
2269 if (integer_decl->base.base.id != CTF_FIELD_CLASS_ID_INT) {
2270 BT_LOGE("Container field class for enumeration field class is not an integer field class: "
2271 "fc-id=%d", integer_decl->base.base.id);
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;
44c440bc
PP
2368 struct bt_clock_class *mapped_clock_class = NULL;
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;
2722 (*integer_decl)->mapped_clock_class = bt_get(mapped_clock_class);
e98a2d6e
PP
2723 return 0;
2724
2725error:
5cd6d0e5 2726 ctf_field_class_destroy((void *) *integer_decl);
44c440bc 2727 *integer_decl = NULL;
e98a2d6e
PP
2728 return ret;
2729}
2730
2731static
2732int visit_floating_point_number_decl(struct ctx *ctx,
44c440bc 2733 struct bt_list_head *expressions,
5cd6d0e5 2734 struct ctf_field_class_float **float_decl)
e98a2d6e
PP
2735{
2736 int set = 0;
2737 int ret = 0;
2738 struct ctf_node *expression;
2739 uint64_t alignment = 1, exp_dig = 0, mant_dig = 0;
44c440bc 2740 enum ctf_byte_order byte_order = ctx->ctf_tc->default_byte_order;
e98a2d6e
PP
2741
2742 *float_decl = NULL;
2743
2744 bt_list_for_each_entry(expression, expressions, siblings) {
2745 struct ctf_node *left, *right;
2746
2747 left = _BT_LIST_FIRST_ENTRY(&expression->u.ctf_expression.left,
2748 struct ctf_node, siblings);
2749 right = _BT_LIST_FIRST_ENTRY(
2750 &expression->u.ctf_expression.right, struct ctf_node,
2751 siblings);
2752
2753 if (left->u.unary_expression.type != UNARY_STRING) {
28973adf
PP
2754 _BT_LOGE_NODE(left,
2755 "Unexpected unary expression type: type=%d",
2756 left->u.unary_expression.type);
e98a2d6e
PP
2757 ret = -EINVAL;
2758 goto error;
2759 }
2760
2761 if (!strcmp(left->u.unary_expression.u.string, "byte_order")) {
2762 if (_IS_SET(&set, _FLOAT_BYTE_ORDER_SET)) {
28973adf 2763 _BT_LOGE_DUP_ATTR(left, "byte_order",
5cd6d0e5 2764 "floating point number field class");
e98a2d6e
PP
2765 ret = -EPERM;
2766 goto error;
2767 }
2768
2769 byte_order = get_real_byte_order(ctx, right);
44c440bc 2770 if (byte_order == -1) {
28973adf 2771 _BT_LOGE_NODE(right,
5cd6d0e5 2772 "Invalid `byte_order` attribute in floating point number field class: "
08da4f77 2773 "ret=%d", ret);
e98a2d6e
PP
2774 ret = -EINVAL;
2775 goto error;
2776 }
2777
2778 _SET(&set, _FLOAT_BYTE_ORDER_SET);
2779 } else if (!strcmp(left->u.unary_expression.u.string,
2780 "exp_dig")) {
2781 if (_IS_SET(&set, _FLOAT_EXP_DIG_SET)) {
28973adf 2782 _BT_LOGE_DUP_ATTR(left, "exp_dig",
5cd6d0e5 2783 "floating point number field class");
e98a2d6e
PP
2784 ret = -EPERM;
2785 goto error;
2786 }
2787
2788 if (right->u.unary_expression.type !=
2789 UNARY_UNSIGNED_CONSTANT) {
28973adf 2790 _BT_LOGE_NODE(right,
5cd6d0e5 2791 "Invalid `exp_dig` attribute in floating point number field class: "
08da4f77
PP
2792 "expecting unsigned constant integer: "
2793 "node-type=%d",
2794 right->u.unary_expression.type);
e98a2d6e
PP
2795 ret = -EINVAL;
2796 goto error;
2797 }
2798
2799 exp_dig = right->u.unary_expression.u.unsigned_constant;
2800 _SET(&set, _FLOAT_EXP_DIG_SET);
2801 } else if (!strcmp(left->u.unary_expression.u.string,
2802 "mant_dig")) {
2803 if (_IS_SET(&set, _FLOAT_MANT_DIG_SET)) {
28973adf 2804 _BT_LOGE_DUP_ATTR(left, "mant_dig",
5cd6d0e5 2805 "floating point number field class");
e98a2d6e
PP
2806 ret = -EPERM;
2807 goto error;
2808 }
2809
2810 if (right->u.unary_expression.type !=
2811 UNARY_UNSIGNED_CONSTANT) {
28973adf 2812 _BT_LOGE_NODE(right,
5cd6d0e5 2813 "Invalid `mant_dig` attribute in floating point number field class: "
08da4f77
PP
2814 "expecting unsigned constant integer: "
2815 "node-type=%d",
2816 right->u.unary_expression.type);
e98a2d6e
PP
2817 ret = -EINVAL;
2818 goto error;
2819 }
2820
2821 mant_dig = right->u.unary_expression.u.
2822 unsigned_constant;
2823 _SET(&set, _FLOAT_MANT_DIG_SET);
2824 } else if (!strcmp(left->u.unary_expression.u.string,
2825 "align")) {
2826 if (_IS_SET(&set, _FLOAT_ALIGN_SET)) {
28973adf 2827 _BT_LOGE_DUP_ATTR(left, "align",
5cd6d0e5 2828 "floating point number field class");
e98a2d6e
PP
2829 ret = -EPERM;
2830 goto error;
2831 }
2832
2833 if (right->u.unary_expression.type !=
2834 UNARY_UNSIGNED_CONSTANT) {
28973adf 2835 _BT_LOGE_NODE(right,
5cd6d0e5 2836 "Invalid `align` attribute in floating point number field class: "
08da4f77
PP
2837 "expecting unsigned constant integer: "
2838 "node-type=%d",
2839 right->u.unary_expression.type);
e98a2d6e
PP
2840 ret = -EINVAL;
2841 goto error;
2842 }
2843
2844 alignment = right->u.unary_expression.u.
2845 unsigned_constant;
2846
2847 if (!is_align_valid(alignment)) {
28973adf 2848 _BT_LOGE_NODE(right,
5cd6d0e5 2849 "Invalid `align` attribute in floating point number field class: "
08da4f77
PP
2850 "expecting power of two: "
2851 "align=%" PRIu64, alignment);
e98a2d6e
PP
2852 ret = -EINVAL;
2853 goto error;
2854 }
2855
2856 _SET(&set, _FLOAT_ALIGN_SET);
2857 } else {
28973adf 2858 _BT_LOGW_NODE(left,
5cd6d0e5 2859 "Unknown attribute in floating point number field class: "
08da4f77 2860 "attr-name=\"%s\"",
e98a2d6e
PP
2861 left->u.unary_expression.u.string);
2862 }
2863 }
2864
2865 if (!_IS_SET(&set, _FLOAT_MANT_DIG_SET)) {
5cd6d0e5 2866 BT_LOGE_STR("Missing `mant_dig` attribute in floating point number field class.");
e98a2d6e
PP
2867 ret = -EPERM;
2868 goto error;
2869 }
2870
2871 if (!_IS_SET(&set, _FLOAT_EXP_DIG_SET)) {
5cd6d0e5 2872 BT_LOGE_STR("Missing `exp_dig` attribute in floating point number field class.");
e98a2d6e
PP
2873 ret = -EPERM;
2874 goto error;
2875 }
2876
44c440bc
PP
2877 if (mant_dig != 24 && mant_dig != 53) {
2878 BT_LOGE_STR("`mant_dig` attribute: expecting 24 or 53.");
2879 ret = -EPERM;
2880 goto error;
2881 }
2882
2883 if (mant_dig == 24 && exp_dig != 8) {
2884 BT_LOGE_STR("`exp_dig` attribute: expecting 8 because `mant_dig` is 24.");
2885 ret = -EPERM;
2886 goto error;
2887 }
2888
2889 if (mant_dig == 53 && exp_dig != 11) {
2890 BT_LOGE_STR("`exp_dig` attribute: expecting 11 because `mant_dig` is 53.");
2891 ret = -EPERM;
2892 goto error;
2893 }
2894
e98a2d6e
PP
2895 if (!_IS_SET(&set, _INTEGER_ALIGN_SET)) {
2896 if ((mant_dig + exp_dig) % CHAR_BIT) {
2897 /* Bit-packed alignment */
2898 alignment = 1;
2899 } else {
2900 /* Byte-packed alignment */
2901 alignment = CHAR_BIT;
2902 }
2903 }
2904
5cd6d0e5 2905 *float_decl = ctf_field_class_float_create();
44c440bc
PP
2906 BT_ASSERT(*float_decl);
2907 (*float_decl)->base.base.alignment = alignment;
2908 (*float_decl)->base.byte_order = byte_order;
2909 (*float_decl)->base.size = mant_dig + exp_dig;
e98a2d6e
PP
2910 return 0;
2911
2912error:
5cd6d0e5 2913 ctf_field_class_destroy((void *) *float_decl);
44c440bc 2914 *float_decl = NULL;
e98a2d6e
PP
2915 return ret;
2916}
2917
2918static
2919int visit_string_decl(struct ctx *ctx,
44c440bc 2920 struct bt_list_head *expressions,
5cd6d0e5 2921 struct ctf_field_class_string **string_decl)
e98a2d6e
PP
2922{
2923 int set = 0;
2924 int ret = 0;
2925 struct ctf_node *expression;
44c440bc 2926 enum ctf_encoding encoding = CTF_ENCODING_UTF8;
e98a2d6e
PP
2927
2928 *string_decl = NULL;
2929
2930 bt_list_for_each_entry(expression, expressions, siblings) {
2931 struct ctf_node *left, *right;
2932
2933 left = _BT_LIST_FIRST_ENTRY(&expression->u.ctf_expression.left,
2934 struct ctf_node, siblings);
2935 right = _BT_LIST_FIRST_ENTRY(
2936 &expression->u.ctf_expression.right, struct ctf_node,
2937 siblings);
2938
2939 if (left->u.unary_expression.type != UNARY_STRING) {
28973adf
PP
2940 _BT_LOGE_NODE(left,
2941 "Unexpected unary expression type: type=%d",
2942 left->u.unary_expression.type);
e98a2d6e
PP
2943 ret = -EINVAL;
2944 goto error;
2945 }
2946
2947 if (!strcmp(left->u.unary_expression.u.string, "encoding")) {
2948 char *s_right;
2949
2950 if (_IS_SET(&set, _STRING_ENCODING_SET)) {
28973adf 2951 _BT_LOGE_DUP_ATTR(left, "encoding",
5cd6d0e5 2952 "string field class");
e98a2d6e
PP
2953 ret = -EPERM;
2954 goto error;
2955 }
2956
2957 if (right->u.unary_expression.type != UNARY_STRING) {
28973adf 2958 _BT_LOGE_NODE(right,
5cd6d0e5 2959 "Invalid `encoding` attribute in string field class: "
08da4f77 2960 "expecting unary string.");
e98a2d6e
PP
2961 ret = -EINVAL;
2962 goto error;
2963 }
2964
2965 s_right = concatenate_unary_strings(
2966 &expression->u.ctf_expression.right);
2967 if (!s_right) {
28973adf 2968 _BT_LOGE_NODE(right,
5cd6d0e5 2969 "Unexpected unary expression for string field class's `encoding` attribute.");
e98a2d6e
PP
2970 ret = -EINVAL;
2971 goto error;
2972 }
2973
2974 if (!strcmp(s_right, "UTF8") ||
2975 !strcmp(s_right, "utf8") ||
2976 !strcmp(s_right, "utf-8") ||
44c440bc
PP
2977 !strcmp(s_right, "UTF-8") ||
2978 !strcmp(s_right, "ASCII") ||
e98a2d6e 2979 !strcmp(s_right, "ascii")) {
44c440bc 2980 encoding = CTF_ENCODING_UTF8;
e98a2d6e 2981 } else if (!strcmp(s_right, "none")) {
44c440bc 2982 encoding = CTF_ENCODING_NONE;
e98a2d6e 2983 } else {
28973adf 2984 _BT_LOGE_NODE(right,
5cd6d0e5 2985 "Invalid `encoding` attribute in string field class: "
08da4f77 2986 "unknown encoding: encoding=\"%s\"",
e98a2d6e
PP
2987 s_right);
2988 g_free(s_right);
2989 ret = -EINVAL;
2990 goto error;
2991 }
2992
2993 g_free(s_right);
2994 _SET(&set, _STRING_ENCODING_SET);
2995 } else {
28973adf 2996 _BT_LOGW_NODE(left,
5cd6d0e5 2997 "Unknown attribute in string field class: "
08da4f77 2998 "attr-name=\"%s\"",
e98a2d6e
PP
2999 left->u.unary_expression.u.string);
3000 }
3001 }
3002
5cd6d0e5 3003 *string_decl = ctf_field_class_string_create();
44c440bc
PP
3004 BT_ASSERT(*string_decl);
3005 (*string_decl)->encoding = encoding;
e98a2d6e
PP
3006 return 0;
3007
3008error:
5cd6d0e5 3009 ctf_field_class_destroy((void *) *string_decl);
44c440bc 3010 *string_decl = NULL;
e98a2d6e
PP
3011 return ret;
3012}
3013
3014static
5cd6d0e5
PP
3015int visit_field_class_specifier_list(struct ctx *ctx,
3016 struct ctf_node *ts_list, struct ctf_field_class **decl)
e98a2d6e
PP
3017{
3018 int ret = 0;
3019 struct ctf_node *first, *node;
3020
3021 *decl = NULL;
3022
3023 if (ts_list->type != NODE_TYPE_SPECIFIER_LIST) {
28973adf
PP
3024 _BT_LOGE_NODE(ts_list,
3025 "Unexpected node type: node-type=%d", ts_list->type);
e98a2d6e
PP
3026 ret = -EINVAL;
3027 goto error;
3028 }
3029
5cd6d0e5 3030 first = _BT_LIST_FIRST_ENTRY(&ts_list->u.field_class_specifier_list.head,
e98a2d6e
PP
3031 struct ctf_node, siblings);
3032 if (first->type != NODE_TYPE_SPECIFIER) {
28973adf
PP
3033 _BT_LOGE_NODE(first,
3034 "Unexpected node type: node-type=%d", first->type);
e98a2d6e
PP
3035 ret = -EINVAL;
3036 goto error;
3037 }
3038
5cd6d0e5 3039 node = first->u.field_class_specifier.node;
e98a2d6e 3040
5cd6d0e5 3041 switch (first->u.field_class_specifier.type) {
e98a2d6e
PP
3042 case TYPESPEC_INTEGER:
3043 ret = visit_integer_decl(ctx, &node->u.integer.expressions,
44c440bc 3044 (void *) decl);
e98a2d6e 3045 if (ret) {
f6ccaed9 3046 BT_ASSERT(!*decl);
e98a2d6e
PP
3047 goto error;
3048 }
3049 break;
3050 case TYPESPEC_FLOATING_POINT:
3051 ret = visit_floating_point_number_decl(ctx,
44c440bc 3052 &node->u.floating_point.expressions, (void *) decl);
e98a2d6e 3053 if (ret) {
f6ccaed9 3054 BT_ASSERT(!*decl);
e98a2d6e
PP
3055 goto error;
3056 }
3057 break;
3058 case TYPESPEC_STRING:
3059 ret = visit_string_decl(ctx,
44c440bc 3060 &node->u.string.expressions, (void *) decl);
e98a2d6e 3061 if (ret) {
f6ccaed9 3062 BT_ASSERT(!*decl);
e98a2d6e
PP
3063 goto error;
3064 }
3065 break;
3066 case TYPESPEC_STRUCT:
3067 ret = visit_struct_decl(ctx, node->u._struct.name,
3068 &node->u._struct.declaration_list,
3069 node->u._struct.has_body,
44c440bc 3070 &node->u._struct.min_align, (void *) decl);
e98a2d6e 3071 if (ret) {
f6ccaed9 3072 BT_ASSERT(!*decl);
e98a2d6e
PP
3073 goto error;
3074 }
3075 break;
3076 case TYPESPEC_VARIANT:
3077 ret = visit_variant_decl(ctx, node->u.variant.name,
3078 node->u.variant.choice,
3079 &node->u.variant.declaration_list,
44c440bc 3080 node->u.variant.has_body, (void *) decl);
e98a2d6e 3081 if (ret) {
f6ccaed9 3082 BT_ASSERT(!*decl);
e98a2d6e
PP
3083 goto error;
3084 }
3085 break;
3086 case TYPESPEC_ENUM:
3087 ret = visit_enum_decl(ctx, node->u._enum.enum_id,
5cd6d0e5 3088 node->u._enum.container_field_class,
e98a2d6e 3089 &node->u._enum.enumerator_list,
44c440bc 3090 node->u._enum.has_body, (void *) decl);
e98a2d6e 3091 if (ret) {
f6ccaed9 3092 BT_ASSERT(!*decl);
e98a2d6e
PP
3093 goto error;
3094 }
3095 break;
3096 case TYPESPEC_VOID:
3097 case TYPESPEC_CHAR:
3098 case TYPESPEC_SHORT:
3099 case TYPESPEC_INT:
3100 case TYPESPEC_LONG:
3101 case TYPESPEC_FLOAT:
3102 case TYPESPEC_DOUBLE:
3103 case TYPESPEC_SIGNED:
3104 case TYPESPEC_UNSIGNED:
3105 case TYPESPEC_BOOL:
3106 case TYPESPEC_COMPLEX:
3107 case TYPESPEC_IMAGINARY:
3108 case TYPESPEC_CONST:
3109 case TYPESPEC_ID_TYPE:
5cd6d0e5 3110 ret = visit_field_class_specifier(ctx, ts_list, decl);
e98a2d6e 3111 if (ret) {
28973adf 3112 _BT_LOGE_NODE(first,
5cd6d0e5 3113 "Cannot visit field class specifier: ret=%d",
28973adf 3114 ret);
f6ccaed9 3115 BT_ASSERT(!*decl);
e98a2d6e
PP
3116 goto error;
3117 }
3118 break;
3119 default:
28973adf 3120 _BT_LOGE_NODE(first,
5cd6d0e5
PP
3121 "Unexpected field class specifier type: node-type=%d",
3122 first->u.field_class_specifier.type);
e98a2d6e
PP
3123 ret = -EINVAL;
3124 goto error;
3125 }
3126
f6ccaed9 3127 BT_ASSERT(*decl);
e98a2d6e
PP
3128 return 0;
3129
3130error:
5cd6d0e5 3131 ctf_field_class_destroy((void *) *decl);
44c440bc 3132 *decl = NULL;
e98a2d6e
PP
3133 return ret;
3134}
3135
3136static
3137int visit_event_decl_entry(struct ctx *ctx, struct ctf_node *node,
44c440bc
PP
3138 struct ctf_event_class *event_class, uint64_t *stream_id,
3139 int *set)
e98a2d6e
PP
3140{
3141 int ret = 0;
3142 char *left = NULL;
e98a2d6e
PP
3143
3144 switch (node->type) {
3145 case NODE_TYPEDEF:
5cd6d0e5
PP
3146 ret = visit_field_class_def(ctx, node->u.field_class_def.field_class_specifier_list,
3147 &node->u.field_class_def.field_class_declarators);
e98a2d6e 3148 if (ret) {
28973adf 3149 _BT_LOGE_NODE(node,
5cd6d0e5 3150 "Cannot add field class found in event class.");
e98a2d6e
PP
3151 goto error;
3152 }
3153 break;
3154 case NODE_TYPEALIAS:
5cd6d0e5
PP
3155 ret = visit_field_class_alias(ctx, node->u.field_class_alias.target,
3156 node->u.field_class_alias.alias);
e98a2d6e 3157 if (ret) {
28973adf 3158 _BT_LOGE_NODE(node,
5cd6d0e5 3159 "Cannot add field class alias found in event class.");
e98a2d6e
PP
3160 goto error;
3161 }
3162 break;
3163 case NODE_CTF_EXPRESSION:
3164 {
3165 left = concatenate_unary_strings(&node->u.ctf_expression.left);
3166 if (!left) {
28973adf 3167 _BT_LOGE_NODE(node, "Cannot concatenate unary strings.");
e98a2d6e
PP
3168 ret = -EINVAL;
3169 goto error;
3170 }
3171
3172 if (!strcmp(left, "name")) {
3173 /* This is already known at this stage */
3174 if (_IS_SET(set, _EVENT_NAME_SET)) {
44c440bc 3175 _BT_LOGE_DUP_ATTR(node, "name", "event class");
e98a2d6e
PP
3176 ret = -EPERM;
3177 goto error;
3178 }
3179
3180 _SET(set, _EVENT_NAME_SET);
3181 } else if (!strcmp(left, "id")) {
bc85036f 3182 int64_t id = -1;
e98a2d6e
PP
3183
3184 if (_IS_SET(set, _EVENT_ID_SET)) {
44c440bc 3185 _BT_LOGE_DUP_ATTR(node, "id", "event class");
e98a2d6e
PP
3186 ret = -EPERM;
3187 goto error;
3188 }
3189
3190 ret = get_unary_unsigned(&node->u.ctf_expression.right,
3191 (uint64_t *) &id);
5eae0c3c
JG
3192 /* Only read "id" if get_unary_unsigned() succeeded. */
3193 if (ret || (!ret && id < 0)) {
28973adf
PP
3194 _BT_LOGE_NODE(node,
3195 "Unexpected unary expression for event class's `id` attribute.");
e98a2d6e
PP
3196 ret = -EINVAL;
3197 goto error;
3198 }
3199
44c440bc 3200 event_class->id = id;
e98a2d6e
PP
3201 _SET(set, _EVENT_ID_SET);
3202 } else if (!strcmp(left, "stream_id")) {
3203 if (_IS_SET(set, _EVENT_STREAM_ID_SET)) {
28973adf 3204 _BT_LOGE_DUP_ATTR(node, "stream_id",
08da4f77 3205 "event class");
e98a2d6e
PP
3206 ret = -EPERM;
3207 goto error;
3208 }
3209
3210 ret = get_unary_unsigned(&node->u.ctf_expression.right,
44c440bc
PP
3211 stream_id);
3212
5eae0c3c
JG
3213 /*
3214 * Only read "stream_id" if get_unary_unsigned()
3215 * succeeded.
3216 */
3217 if (ret || (!ret && *stream_id < 0)) {
28973adf
PP
3218 _BT_LOGE_NODE(node,
3219 "Unexpected unary expression for event class's `stream_id` attribute.");
e98a2d6e
PP
3220 ret = -EINVAL;
3221 goto error;
3222 }
3223
3224 _SET(set, _EVENT_STREAM_ID_SET);
3225 } else if (!strcmp(left, "context")) {
3226 if (_IS_SET(set, _EVENT_CONTEXT_SET)) {
28973adf
PP
3227 _BT_LOGE_NODE(node,
3228 "Duplicate `context` entry in event class.");
e98a2d6e
PP
3229 ret = -EPERM;
3230 goto error;
3231 }
3232
5cd6d0e5 3233 ret = visit_field_class_specifier_list(ctx,
e98a2d6e
PP
3234 _BT_LIST_FIRST_ENTRY(
3235 &node->u.ctf_expression.right,
3236 struct ctf_node, siblings),
5cd6d0e5 3237 &event_class->spec_context_fc);
e98a2d6e 3238 if (ret) {
28973adf 3239 _BT_LOGE_NODE(node,
5cd6d0e5 3240 "Cannot create event class's context field class.");
e98a2d6e
PP
3241 goto error;
3242 }
3243
5cd6d0e5 3244 BT_ASSERT(event_class->spec_context_fc);
e98a2d6e
PP
3245 _SET(set, _EVENT_CONTEXT_SET);
3246 } else if (!strcmp(left, "fields")) {
3247 if (_IS_SET(set, _EVENT_FIELDS_SET)) {
28973adf
PP
3248 _BT_LOGE_NODE(node,
3249 "Duplicate `fields` entry in event class.");
e98a2d6e
PP
3250 ret = -EPERM;
3251 goto error;
3252 }
3253
5cd6d0e5 3254 ret = visit_field_class_specifier_list(ctx,
e98a2d6e
PP
3255 _BT_LIST_FIRST_ENTRY(
3256 &node->u.ctf_expression.right,
3257 struct ctf_node, siblings),
5cd6d0e5 3258 &event_class->payload_fc);
e98a2d6e 3259 if (ret) {
28973adf 3260 _BT_LOGE_NODE(node,
5cd6d0e5 3261 "Cannot create event class's payload field class.");
e98a2d6e
PP
3262 goto error;
3263 }
3264
5cd6d0e5 3265 BT_ASSERT(event_class->payload_fc);
e98a2d6e
PP
3266 _SET(set, _EVENT_FIELDS_SET);
3267 } else if (!strcmp(left, "loglevel")) {
c3c30b08 3268 uint64_t loglevel_value;
44c440bc 3269 enum bt_event_class_log_level log_level = -1;
e98a2d6e 3270
44c440bc 3271 if (_IS_SET(set, _EVENT_LOG_LEVEL_SET)) {
28973adf 3272 _BT_LOGE_DUP_ATTR(node, "loglevel",
08da4f77 3273 "event class");
e98a2d6e
PP
3274 ret = -EPERM;
3275 goto error;
3276 }
3277
3278 ret = get_unary_unsigned(&node->u.ctf_expression.right,
c3c30b08 3279 &loglevel_value);
e98a2d6e 3280 if (ret) {
28973adf
PP
3281 _BT_LOGE_NODE(node,
3282 "Unexpected unary expression for event class's `loglevel` attribute.");
e98a2d6e
PP
3283 ret = -EINVAL;
3284 goto error;
3285 }
cf76ce92
PP
3286
3287 switch (loglevel_value) {
3288 case 0:
50842bdc 3289 log_level = BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY;
cf76ce92
PP
3290 break;
3291 case 1:
50842bdc 3292 log_level = BT_EVENT_CLASS_LOG_LEVEL_ALERT;
cf76ce92
PP
3293 break;
3294 case 2:
50842bdc 3295 log_level = BT_EVENT_CLASS_LOG_LEVEL_CRITICAL;
cf76ce92
PP
3296 break;
3297 case 3:
50842bdc 3298 log_level = BT_EVENT_CLASS_LOG_LEVEL_ERROR;
cf76ce92
PP
3299 break;
3300 case 4:
50842bdc 3301 log_level = BT_EVENT_CLASS_LOG_LEVEL_WARNING;
cf76ce92
PP
3302 break;
3303 case 5:
50842bdc 3304 log_level = BT_EVENT_CLASS_LOG_LEVEL_NOTICE;
cf76ce92
PP
3305 break;
3306 case 6:
50842bdc 3307 log_level = BT_EVENT_CLASS_LOG_LEVEL_INFO;
cf76ce92
PP
3308 break;
3309 case 7:
50842bdc 3310 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM;
cf76ce92
PP
3311 break;
3312 case 8:
50842bdc 3313 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM;
cf76ce92
PP
3314 break;
3315 case 9:
50842bdc 3316 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS;
cf76ce92
PP
3317 break;
3318 case 10:
50842bdc 3319 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE;
cf76ce92
PP
3320 break;
3321 case 11:
50842bdc 3322 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT;
cf76ce92
PP
3323 break;
3324 case 12:
50842bdc 3325 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION;
cf76ce92
PP
3326 break;
3327 case 13:
50842bdc 3328 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE;
cf76ce92
PP
3329 break;
3330 case 14:
50842bdc 3331 log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG;
cf76ce92
PP
3332 break;
3333 default:
3334 _BT_LOGW_NODE(node, "Not setting event class's log level because its value is unknown: "
3335 "log-level=%" PRIu64, loglevel_value);
c3c30b08 3336 }
cf76ce92 3337
44c440bc
PP
3338 if (log_level != -1) {
3339 event_class->log_level = log_level;
c3c30b08 3340 }
cf76ce92 3341
44c440bc 3342 _SET(set, _EVENT_LOG_LEVEL_SET);
e98a2d6e
PP
3343 } else if (!strcmp(left, "model.emf.uri")) {
3344 char *right;
3345
3346 if (_IS_SET(set, _EVENT_MODEL_EMF_URI_SET)) {
28973adf
PP
3347 _BT_LOGE_DUP_ATTR(node, "model.emf.uri",
3348 "event class");
e98a2d6e
PP
3349 ret = -EPERM;
3350 goto error;
3351 }
3352
3353 right = concatenate_unary_strings(
3354 &node->u.ctf_expression.right);
3355 if (!right) {
28973adf
PP
3356 _BT_LOGE_NODE(node,
3357 "Unexpected unary expression for event class's `model.emf.uri` attribute.");
e98a2d6e
PP
3358 ret = -EINVAL;
3359 goto error;
3360 }
3361
cf76ce92
PP
3362 if (strlen(right) == 0) {
3363 _BT_LOGW_NODE(node,
3364 "Not setting event class's EMF URI because it's empty.");
3365 } else {
44c440bc
PP
3366 g_string_assign(event_class->emf_uri,
3367 right);
28973adf 3368 }
cf76ce92 3369
e98a2d6e
PP
3370 g_free(right);
3371 _SET(set, _EVENT_MODEL_EMF_URI_SET);
3372 } else {
28973adf
PP
3373 _BT_LOGW_NODE(node,
3374 "Unknown attribute in event class: "
08da4f77 3375 "attr-name=\"%s\"", left);
e98a2d6e
PP
3376 }
3377
3378 g_free(left);
3379 left = NULL;
3380 break;
3381 }
3382 default:
3383 ret = -EPERM;
3384 goto error;
3385 }
3386
44c440bc 3387 goto end;
e98a2d6e
PP
3388
3389error:
3390 if (left) {
3391 g_free(left);
3392 }
3393
44c440bc 3394end:
e98a2d6e
PP
3395 return ret;
3396}
3397
3398static
3399char *get_event_decl_name(struct ctx *ctx, struct ctf_node *node)
3400{
3401 char *left = NULL;
3402 char *name = NULL;
3403 struct ctf_node *iter;
3404 struct bt_list_head *decl_list = &node->u.event.declaration_list;
3405
3406 bt_list_for_each_entry(iter, decl_list, siblings) {
3407 if (iter->type != NODE_CTF_EXPRESSION) {
3408 continue;
3409 }
3410
3411 left = concatenate_unary_strings(&iter->u.ctf_expression.left);
3412 if (!left) {
28973adf
PP
3413 _BT_LOGE_NODE(iter,
3414 "Cannot concatenate unary strings.");
e98a2d6e
PP
3415 goto error;
3416 }
3417
3418 if (!strcmp(left, "name")) {
3419 name = concatenate_unary_strings(
3420 &iter->u.ctf_expression.right);
3421 if (!name) {
28973adf
PP
3422 _BT_LOGE_NODE(iter,
3423 "Unexpected unary expression for event class's `name` attribute.");
e98a2d6e
PP
3424 goto error;
3425 }
3426 }
3427
3428 g_free(left);
3429 left = NULL;
3430
3431 if (name) {
3432 break;
3433 }
3434 }
3435
3436 return name;
3437
3438error:
3439 g_free(left);
e98a2d6e
PP
3440 return NULL;
3441}
3442
3443static
3444int visit_event_decl(struct ctx *ctx, struct ctf_node *node)
3445{
3446 int ret = 0;
3447 int set = 0;
e98a2d6e 3448 struct ctf_node *iter;
44c440bc 3449 uint64_t stream_id = 0;
e98a2d6e 3450 char *event_name = NULL;
44c440bc
PP
3451 struct ctf_event_class *event_class = NULL;
3452 struct ctf_stream_class *stream_class = NULL;
e98a2d6e 3453 struct bt_list_head *decl_list = &node->u.event.declaration_list;
1e649dff 3454 bool pop_scope = false;
e98a2d6e
PP
3455
3456 if (node->visited) {
3457 goto end;
3458 }
3459
3460 node->visited = TRUE;
3461 event_name = get_event_decl_name(ctx, node);
3462 if (!event_name) {
28973adf
PP
3463 _BT_LOGE_NODE(node,
3464 "Missing `name` attribute in event class.");
e98a2d6e
PP
3465 ret = -EPERM;
3466 goto error;
3467 }
3468
44c440bc
PP
3469 event_class = ctf_event_class_create();
3470 BT_ASSERT(event_class);
3471 g_string_assign(event_class->name, event_name);
3472 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
1e649dff
PP
3473 pop_scope = true;
3474
e98a2d6e
PP
3475 bt_list_for_each_entry(iter, decl_list, siblings) {
3476 ret = visit_event_decl_entry(ctx, iter, event_class,
3477 &stream_id, &set);
3478 if (ret) {
28973adf
PP
3479 _BT_LOGE_NODE(iter, "Cannot visit event class's entry: "
3480 "ret=%d", ret);
e98a2d6e
PP
3481 goto error;
3482 }
3483 }
3484
3485 if (!_IS_SET(&set, _EVENT_STREAM_ID_SET)) {
1e649dff
PP
3486 /*
3487 * Allow missing stream_id if there is only a single
3488 * stream class.
3489 */
44c440bc 3490 switch (ctx->ctf_tc->stream_classes->len) {
e98a2d6e 3491 case 0:
1e649dff 3492 /* Create implicit stream class if there's none */
7b4b1ba2 3493 stream_id = 0;
44c440bc
PP
3494 stream_class = ctf_stream_class_create();
3495 BT_ASSERT(stream_class);
3496 stream_class->id = stream_id;
3497 g_ptr_array_add(ctx->ctf_tc->stream_classes,
3498 stream_class);
3499 stream_class = stream_class;
e98a2d6e
PP
3500 break;
3501 case 1:
1e649dff 3502 /* Single stream class: get its ID */
44c440bc
PP
3503 stream_class = ctx->ctf_tc->stream_classes->pdata[0];
3504 stream_id = stream_class->id;
e98a2d6e
PP
3505 break;
3506 default:
28973adf
PP
3507 _BT_LOGE_NODE(node,
3508 "Missing `stream_id` attribute in event class.");
e98a2d6e
PP
3509 ret = -EPERM;
3510 goto error;
3511 }
3512 }
3513
1e649dff 3514 /* We have the stream ID now; get the stream class if found */
e98a2d6e 3515 if (!stream_class) {
44c440bc
PP
3516 stream_class = ctf_trace_class_borrow_stream_class_by_id(
3517 ctx->ctf_tc, stream_id);
1e649dff 3518 if (!stream_class) {
28973adf
PP
3519 _BT_LOGE_NODE(node,
3520 "Cannot find stream class at this point: "
08da4f77 3521 "id=%" PRId64, stream_id);
1e649dff
PP
3522 ret = -EINVAL;
3523 goto error;
3524 }
e98a2d6e
PP
3525 }
3526
f6ccaed9 3527 BT_ASSERT(stream_class);
1e649dff 3528
e98a2d6e
PP
3529 if (!_IS_SET(&set, _EVENT_ID_SET)) {
3530 /* Allow only one event without ID per stream */
44c440bc 3531 if (stream_class->event_classes->len != 0) {
28973adf
PP
3532 _BT_LOGE_NODE(node,
3533 "Missing `id` attribute in event class.");
e98a2d6e
PP
3534 ret = -EPERM;
3535 goto error;
3536 }
3537
3538 /* Automatic ID */
44c440bc 3539 event_class->id = 0;
e98a2d6e
PP
3540 }
3541
44c440bc
PP
3542 if (ctf_stream_class_borrow_event_class_by_id(stream_class,
3543 event_class->id)) {
28973adf
PP
3544 _BT_LOGE_NODE(node,
3545 "Duplicate event class (same ID) in the same stream class: "
44c440bc 3546 "id=%" PRId64, event_class->id);
e98a2d6e
PP
3547 ret = -EEXIST;
3548 goto error;
3549 }
3550
44c440bc
PP
3551 ctf_stream_class_append_event_class(stream_class, event_class);
3552 event_class = NULL;
1e649dff 3553 goto end;
e98a2d6e
PP
3554
3555error:
44c440bc
PP
3556 ctf_event_class_destroy(event_class);
3557 event_class = NULL;
3558
3559 if (ret >= 0) {
3560 ret = -1;
3561 }
e98a2d6e 3562
1e649dff
PP
3563end:
3564 if (pop_scope) {
3565 ctx_pop_scope(ctx);
3566 }
e98a2d6e 3567
44c440bc
PP
3568 if (event_name) {
3569 g_free(event_name);
3570 }
3571
e98a2d6e
PP
3572 return ret;
3573}
3574
56b43721 3575static
7bf5af54 3576int auto_map_field_to_trace_clock_class(struct ctx *ctx,
5cd6d0e5 3577 struct ctf_field_class *fc)
56b43721 3578{
50842bdc 3579 struct bt_clock_class *clock_class_to_map_to = NULL;
5cd6d0e5 3580 struct ctf_field_class_int *int_fc = (void *) fc;
56b43721 3581 int ret = 0;
44c440bc
PP
3582 uint64_t clock_class_count;
3583
5cd6d0e5 3584 if (!fc) {
44c440bc
PP
3585 goto end;
3586 }
56b43721 3587
5cd6d0e5
PP
3588 if (fc->id != CTF_FIELD_CLASS_ID_INT &&
3589 fc->id != CTF_FIELD_CLASS_ID_ENUM) {
56b43721
PP
3590 goto end;
3591 }
3592
5cd6d0e5 3593 if (int_fc->mapped_clock_class) {
44c440bc 3594 /* Already mapped */
56b43721
PP
3595 goto end;
3596 }
3597
44c440bc 3598 clock_class_count = ctx->ctf_tc->clock_classes->len;
7bf5af54
PP
3599
3600 switch (clock_class_count) {
3601 case 0:
3602 /*
44c440bc
PP
3603 * No clock class exists in the trace at this point. Create an
3604 * implicit one at 1 GHz, named `default`, and use this clock
3605 * class.
7bf5af54 3606 */
44c440bc
PP
3607 clock_class_to_map_to = bt_clock_class_create();
3608 BT_ASSERT(clock_class_to_map_to);
3609 ret = bt_clock_class_set_frequency(clock_class_to_map_to,
3610 UINT64_C(1000000000));
3611 BT_ASSERT(ret == 0);
3612 ret = bt_clock_class_set_name(clock_class_to_map_to,
3613 "default");
3614 BT_ASSERT(ret == 0);
3615 g_ptr_array_add(ctx->ctf_tc->clock_classes,
3616 bt_get(clock_class_to_map_to));
7bf5af54
PP
3617 break;
3618 case 1:
3619 /*
44c440bc
PP
3620 * Only one clock class exists in the trace at this point: use
3621 * this one.
7bf5af54
PP
3622 */
3623 clock_class_to_map_to =
44c440bc 3624 bt_get(ctx->ctf_tc->clock_classes->pdata[0]);
7bf5af54
PP
3625 break;
3626 default:
3627 /*
44c440bc
PP
3628 * Timestamp field not mapped to a clock class and there's more
3629 * than one clock class in the trace: this is an error.
7bf5af54
PP
3630 */
3631 BT_LOGE_STR("Timestamp field found with no mapped clock class, "
3632 "but there's more than one clock class in the trace at this point.");
3633 ret = -1;
56b43721
PP
3634 goto end;
3635 }
3636
f6ccaed9 3637 BT_ASSERT(clock_class_to_map_to);
5cd6d0e5 3638 int_fc->mapped_clock_class = bt_get(clock_class_to_map_to);
56b43721 3639
7bf5af54
PP
3640end:
3641 bt_put(clock_class_to_map_to);
7bf5af54
PP
3642 return ret;
3643}
56b43721 3644
7bf5af54
PP
3645static
3646int auto_map_fields_to_trace_clock_class(struct ctx *ctx,
5cd6d0e5 3647 struct ctf_field_class *root_fc, const char *field_name)
7bf5af54
PP
3648{
3649 int ret = 0;
44c440bc 3650 uint64_t i, count;
5cd6d0e5
PP
3651 struct ctf_field_class_struct *struct_fc = (void *) root_fc;
3652 struct ctf_field_class_variant *var_fc = (void *) root_fc;
56b43721 3653
5cd6d0e5 3654 if (!root_fc) {
7bf5af54
PP
3655 goto end;
3656 }
56b43721 3657
5cd6d0e5
PP
3658 if (root_fc->id != CTF_FIELD_CLASS_ID_STRUCT &&
3659 root_fc->id != CTF_FIELD_CLASS_ID_VARIANT) {
7bf5af54
PP
3660 goto end;
3661 }
3662
5cd6d0e5
PP
3663 if (root_fc->id == CTF_FIELD_CLASS_ID_STRUCT) {
3664 count = struct_fc->members->len;
7bf5af54 3665 } else {
5cd6d0e5 3666 count = var_fc->options->len;
7bf5af54
PP
3667 }
3668
7bf5af54 3669 for (i = 0; i < count; i++) {
5cd6d0e5 3670 struct ctf_named_field_class *named_fc = NULL;
7bf5af54 3671
5cd6d0e5
PP
3672 if (root_fc->id == CTF_FIELD_CLASS_ID_STRUCT) {
3673 named_fc = ctf_field_class_struct_borrow_member_by_index(
3674 struct_fc, i);
3675 } else if (root_fc->id == CTF_FIELD_CLASS_ID_VARIANT) {
3676 named_fc = ctf_field_class_variant_borrow_option_by_index(
3677 var_fc, i);
7bf5af54
PP
3678 }
3679
5cd6d0e5 3680 if (strcmp(named_fc->name->str, field_name) == 0) {
44c440bc 3681 ret = auto_map_field_to_trace_clock_class(ctx,
5cd6d0e5 3682 named_fc->fc);
7bf5af54
PP
3683 if (ret) {
3684 BT_LOGE("Cannot automatically map field to trace's clock class: "
3685 "field-name=\"%s\"", field_name);
7bf5af54 3686 goto end;
56b43721
PP
3687 }
3688 }
3689
5cd6d0e5 3690 ret = auto_map_fields_to_trace_clock_class(ctx, named_fc->fc,
44c440bc 3691 field_name);
7bf5af54 3692 if (ret) {
5cd6d0e5 3693 BT_LOGE("Cannot automatically map structure or variant field class's fields to trace's clock class: "
7bf5af54 3694 "field-name=\"%s\", root-field-name=\"%s\"",
5cd6d0e5 3695 field_name, named_fc->name->str);
7bf5af54
PP
3696 goto end;
3697 }
56b43721
PP
3698 }
3699
3700end:
56b43721
PP
3701 return ret;
3702}
3703
e98a2d6e
PP
3704static
3705int visit_stream_decl_entry(struct ctx *ctx, struct ctf_node *node,
44c440bc 3706 struct ctf_stream_class *stream_class, int *set)
e98a2d6e
PP
3707{
3708 int ret = 0;
3709 char *left = NULL;
e98a2d6e
PP
3710
3711 switch (node->type) {
3712 case NODE_TYPEDEF:
5cd6d0e5
PP
3713 ret = visit_field_class_def(ctx, node->u.field_class_def.field_class_specifier_list,
3714 &node->u.field_class_def.field_class_declarators);
e98a2d6e 3715 if (ret) {
28973adf 3716 _BT_LOGE_NODE(node,
5cd6d0e5 3717 "Cannot add field class found in stream class.");
e98a2d6e
PP
3718 goto error;
3719 }
3720 break;
3721 case NODE_TYPEALIAS:
5cd6d0e5
PP
3722 ret = visit_field_class_alias(ctx, node->u.field_class_alias.target,
3723 node->u.field_class_alias.alias);
e98a2d6e 3724 if (ret) {
28973adf 3725 _BT_LOGE_NODE(node,
5cd6d0e5 3726 "Cannot add field class alias found in stream class.");
e98a2d6e
PP
3727 goto error;
3728 }
3729 break;
3730 case NODE_CTF_EXPRESSION:
3731 {
3732 left = concatenate_unary_strings(&node->u.ctf_expression.left);
3733 if (!left) {
28973adf 3734 _BT_LOGE_NODE(node, "Cannot concatenate unary strings.");
e98a2d6e
PP
3735 ret = -EINVAL;
3736 goto error;
3737 }
3738
3739 if (!strcmp(left, "id")) {
3740 int64_t id;
e98a2d6e
PP
3741
3742 if (_IS_SET(set, _STREAM_ID_SET)) {
28973adf
PP
3743 _BT_LOGE_DUP_ATTR(node, "id",
3744 "stream declaration");
e98a2d6e
PP
3745 ret = -EPERM;
3746 goto error;
3747 }
3748
3749 ret = get_unary_unsigned(&node->u.ctf_expression.right,
3750 (uint64_t *) &id);
44c440bc 3751
5eae0c3c
JG
3752 /* Only read "id" if get_unary_unsigned() succeeded. */
3753 if (ret || (!ret && id < 0)) {
28973adf
PP
3754 _BT_LOGE_NODE(node,
3755 "Unexpected unary expression for stream class's `id` attribute.");
e98a2d6e
PP
3756 ret = -EINVAL;
3757 goto error;
3758 }
3759
44c440bc
PP
3760 if (ctf_trace_class_borrow_stream_class_by_id(
3761 ctx->ctf_tc, id)) {
28973adf
PP
3762 _BT_LOGE_NODE(node,
3763 "Duplicate stream class (same ID): id=%" PRId64,
e98a2d6e
PP
3764 id);
3765 ret = -EEXIST;
3766 goto error;
3767 }
3768
44c440bc 3769 stream_class->id = id;
e98a2d6e
PP
3770 _SET(set, _STREAM_ID_SET);
3771 } else if (!strcmp(left, "event.header")) {
3772 if (_IS_SET(set, _STREAM_EVENT_HEADER_SET)) {
28973adf
PP
3773 _BT_LOGE_NODE(node,
3774 "Duplicate `event.header` entry in stream class.");
e98a2d6e
PP
3775 ret = -EPERM;
3776 goto error;
3777 }
3778
5cd6d0e5 3779 ret = visit_field_class_specifier_list(ctx,
e98a2d6e
PP
3780 _BT_LIST_FIRST_ENTRY(
3781 &node->u.ctf_expression.right,
3782 struct ctf_node, siblings),
5cd6d0e5 3783 &stream_class->event_header_fc);
e98a2d6e 3784 if (ret) {
28973adf 3785 _BT_LOGE_NODE(node,
5cd6d0e5 3786 "Cannot create stream class's event header field class.");
e98a2d6e
PP
3787 goto error;
3788 }
3789
5cd6d0e5 3790 BT_ASSERT(stream_class->event_header_fc);
56b43721 3791 ret = auto_map_fields_to_trace_clock_class(ctx,
5cd6d0e5 3792 stream_class->event_header_fc, "timestamp");
56b43721
PP
3793 if (ret) {
3794 _BT_LOGE_NODE(node,
5cd6d0e5 3795 "Cannot automatically map specific event header field class fields named `timestamp` to trace's clock class.");
56b43721
PP
3796 goto error;
3797 }
e98a2d6e 3798
e98a2d6e
PP
3799 _SET(set, _STREAM_EVENT_HEADER_SET);
3800 } else if (!strcmp(left, "event.context")) {
3801 if (_IS_SET(set, _STREAM_EVENT_CONTEXT_SET)) {
28973adf
PP
3802 _BT_LOGE_NODE(node,
3803 "Duplicate `event.context` entry in stream class.");
e98a2d6e
PP
3804 ret = -EPERM;
3805 goto error;
3806 }
3807
5cd6d0e5 3808 ret = visit_field_class_specifier_list(ctx,
e98a2d6e
PP
3809 _BT_LIST_FIRST_ENTRY(
3810 &node->u.ctf_expression.right,
3811 struct ctf_node, siblings),
5cd6d0e5 3812 &stream_class->event_common_context_fc);
e98a2d6e 3813 if (ret) {
28973adf 3814 _BT_LOGE_NODE(node,
5cd6d0e5 3815 "Cannot create stream class's event context field class.");
e98a2d6e
PP
3816 goto error;
3817 }
3818
5cd6d0e5 3819 BT_ASSERT(stream_class->event_common_context_fc);
e98a2d6e
PP
3820 _SET(set, _STREAM_EVENT_CONTEXT_SET);
3821 } else if (!strcmp(left, "packet.context")) {
3822 if (_IS_SET(set, _STREAM_PACKET_CONTEXT_SET)) {
28973adf
PP
3823 _BT_LOGE_NODE(node,
3824 "Duplicate `packet.context` entry in stream class.");
e98a2d6e
PP
3825 ret = -EPERM;
3826 goto error;
3827 }
3828
5cd6d0e5 3829 ret = visit_field_class_specifier_list(ctx,
e98a2d6e
PP
3830 _BT_LIST_FIRST_ENTRY(
3831 &node->u.ctf_expression.right,
3832 struct ctf_node, siblings),
5cd6d0e5 3833 &stream_class->packet_context_fc);
e98a2d6e 3834 if (ret) {
28973adf 3835 _BT_LOGE_NODE(node,
5cd6d0e5 3836 "Cannot create stream class's packet context field class.");
e98a2d6e
PP
3837 goto error;
3838 }
3839
5cd6d0e5 3840 BT_ASSERT(stream_class->packet_context_fc);
56b43721 3841 ret = auto_map_fields_to_trace_clock_class(ctx,
5cd6d0e5 3842 stream_class->packet_context_fc,
44c440bc 3843 "timestamp_begin");
7bf5af54
PP
3844 if (ret) {
3845 _BT_LOGE_NODE(node,
5cd6d0e5 3846 "Cannot automatically map specific packet context field class fields named `timestamp_begin` to trace's clock class.");
7bf5af54
PP
3847 goto error;
3848 }
3849
3850 ret = auto_map_fields_to_trace_clock_class(ctx,
5cd6d0e5 3851 stream_class->packet_context_fc,
44c440bc 3852 "timestamp_end");
56b43721
PP
3853 if (ret) {
3854 _BT_LOGE_NODE(node,
5cd6d0e5 3855 "Cannot automatically map specific packet context field class fields named `timestamp_end` to trace's clock class.");
56b43721
PP
3856 goto error;
3857 }
e98a2d6e 3858
e98a2d6e
PP
3859 _SET(set, _STREAM_PACKET_CONTEXT_SET);
3860 } else {
28973adf
PP
3861 _BT_LOGW_NODE(node,
3862 "Unknown attribute in stream class: "
08da4f77 3863 "attr-name=\"%s\"", left);
e98a2d6e
PP
3864 }
3865
3866 g_free(left);
3867 left = NULL;
3868 break;
3869 }
3870
3871 default:
3872 ret = -EPERM;
3873 goto error;
3874 }
3875
3876 return 0;
3877
3878error:
3879 g_free(left);
e98a2d6e
PP
3880 return ret;
3881}
3882
3883static
3884int visit_stream_decl(struct ctx *ctx, struct ctf_node *node)
3885{
e98a2d6e
PP
3886 int set = 0;
3887 int ret = 0;
3888 struct ctf_node *iter;
44c440bc 3889 struct ctf_stream_class *stream_class = NULL;
e98a2d6e
PP
3890 struct bt_list_head *decl_list = &node->u.stream.declaration_list;
3891
3892 if (node->visited) {
3893 goto end;
3894 }
3895
3896 node->visited = TRUE;
44c440bc
PP
3897 stream_class = ctf_stream_class_create();
3898 BT_ASSERT(stream_class);
3899 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
e98a2d6e
PP
3900
3901 bt_list_for_each_entry(iter, decl_list, siblings) {
3902 ret = visit_stream_decl_entry(ctx, iter, stream_class, &set);
3903 if (ret) {
28973adf
PP
3904 _BT_LOGE_NODE(iter,
3905 "Cannot visit stream class's entry: "
3906 "ret=%d", ret);
e98a2d6e
PP
3907 ctx_pop_scope(ctx);
3908 goto error;
3909 }
3910 }
3911
3912 ctx_pop_scope(ctx);
3913
3914 if (_IS_SET(&set, _STREAM_ID_SET)) {
44c440bc 3915 /* Check that packet header has `stream_id` field */
5cd6d0e5 3916 struct ctf_named_field_class *named_fc = NULL;
e98a2d6e 3917
5cd6d0e5 3918 if (!ctx->ctf_tc->packet_header_fc) {
28973adf
PP
3919 _BT_LOGE_NODE(node,
3920 "Stream class has a `id` attribute, "
5cd6d0e5 3921 "but trace has no packet header field class.");
e98a2d6e
PP
3922 goto error;
3923 }
3924
5cd6d0e5
PP
3925 named_fc = ctf_field_class_struct_borrow_member_by_name(
3926 (void *) ctx->ctf_tc->packet_header_fc, "stream_id");
3927 if (!named_fc) {
28973adf
PP
3928 _BT_LOGE_NODE(node,
3929 "Stream class has a `id` attribute, "
5cd6d0e5 3930 "but trace's packet header field class has no `stream_id` field.");
e98a2d6e
PP
3931 goto error;
3932 }
3933
5cd6d0e5
PP
3934 if (named_fc->fc->id != CTF_FIELD_CLASS_ID_INT &&
3935 named_fc->fc->id != CTF_FIELD_CLASS_ID_ENUM) {
28973adf
PP
3936 _BT_LOGE_NODE(node,
3937 "Stream class has a `id` attribute, "
5cd6d0e5 3938 "but trace's packet header field class's `stream_id` field is not an integer field class.");
e98a2d6e
PP
3939 goto error;
3940 }
e98a2d6e
PP
3941 } else {
3942 /* Allow only _one_ ID-less stream */
44c440bc 3943 if (ctx->ctf_tc->stream_classes->len != 0) {
28973adf
PP
3944 _BT_LOGE_NODE(node,
3945 "Missing `id` attribute in stream class as there's more than one stream class in the trace.");
e98a2d6e
PP
3946 ret = -EPERM;
3947 goto error;
3948 }
3949
3950 /* Automatic ID: 0 */
44c440bc 3951 stream_class->id = 0;
e98a2d6e
PP
3952 }
3953
1e649dff
PP
3954 /*
3955 * Make sure that this stream class's ID is currently unique in
3956 * the trace.
3957 */
44c440bc
PP
3958 if (ctf_trace_class_borrow_stream_class_by_id(ctx->ctf_tc,
3959 stream_class->id)) {
28973adf
PP
3960 _BT_LOGE_NODE(node,
3961 "Duplicate stream class (same ID): id=%" PRId64,
44c440bc 3962 stream_class->id);
1e649dff
PP
3963 ret = -EINVAL;
3964 goto error;
3965 }
3966
44c440bc 3967 g_ptr_array_add(ctx->ctf_tc->stream_classes, stream_class);
e98a2d6e 3968 stream_class = NULL;
1e649dff 3969 goto end;
e98a2d6e
PP
3970
3971error:
44c440bc
PP
3972 ctf_stream_class_destroy(stream_class);
3973 stream_class = NULL;
e98a2d6e 3974
1e649dff 3975end:
e98a2d6e
PP
3976 return ret;
3977}
3978
3979static
3980int visit_trace_decl_entry(struct ctx *ctx, struct ctf_node *node, int *set)
3981{
3982 int ret = 0;
3983 char *left = NULL;
44c440bc 3984 uint64_t val;
e98a2d6e
PP
3985
3986 switch (node->type) {
3987 case NODE_TYPEDEF:
5cd6d0e5
PP
3988 ret = visit_field_class_def(ctx, node->u.field_class_def.field_class_specifier_list,
3989 &node->u.field_class_def.field_class_declarators);
e98a2d6e 3990 if (ret) {
28973adf 3991 _BT_LOGE_NODE(node,
5cd6d0e5 3992 "Cannot add field class found in trace (`trace` block).");
e98a2d6e
PP
3993 goto error;
3994 }
3995 break;
3996 case NODE_TYPEALIAS:
5cd6d0e5
PP
3997 ret = visit_field_class_alias(ctx, node->u.field_class_alias.target,
3998 node->u.field_class_alias.alias);
e98a2d6e 3999 if (ret) {
28973adf 4000 _BT_LOGE_NODE(node,
5cd6d0e5 4001 "Cannot add field class alias found in trace (`trace` block).");
e98a2d6e
PP
4002 goto error;
4003 }
4004 break;
4005 case NODE_CTF_EXPRESSION:
4006 {
4007 left = concatenate_unary_strings(&node->u.ctf_expression.left);
4008 if (!left) {
28973adf 4009 _BT_LOGE_NODE(node, "Cannot concatenate unary strings.");
e98a2d6e
PP
4010 ret = -EINVAL;
4011 goto error;
4012 }
4013
4014 if (!strcmp(left, "major")) {
4015 if (_IS_SET(set, _TRACE_MAJOR_SET)) {
28973adf 4016 _BT_LOGE_DUP_ATTR(node, "major", "trace");
e98a2d6e
PP
4017 ret = -EPERM;
4018 goto error;
4019 }
4020
4021 ret = get_unary_unsigned(&node->u.ctf_expression.right,
44c440bc 4022 &val);
e98a2d6e 4023 if (ret) {
28973adf
PP
4024 _BT_LOGE_NODE(node,
4025 "Unexpected unary expression for trace's `major` attribute.");
e98a2d6e
PP
4026 ret = -EINVAL;
4027 goto error;
4028 }
4029
44c440bc
PP
4030 if (val != 1) {
4031 _BT_LOGE_NODE(node,
4032 "Invalid trace's `minor` attribute: expecting 1.");
4033 goto error;
4034 }
4035
4036 ctx->ctf_tc->major = val;
e98a2d6e
PP
4037 _SET(set, _TRACE_MAJOR_SET);
4038 } else if (!strcmp(left, "minor")) {
4039 if (_IS_SET(set, _TRACE_MINOR_SET)) {
28973adf 4040 _BT_LOGE_DUP_ATTR(node, "minor", "trace");
e98a2d6e
PP
4041 ret = -EPERM;
4042 goto error;
4043 }
4044
4045 ret = get_unary_unsigned(&node->u.ctf_expression.right,
44c440bc 4046 &val);
e98a2d6e 4047 if (ret) {
28973adf
PP
4048 _BT_LOGE_NODE(node,
4049 "Unexpected unary expression for trace's `minor` attribute.");
e98a2d6e
PP
4050 ret = -EINVAL;
4051 goto error;
4052 }
4053
44c440bc
PP
4054 if (val != 8) {
4055 _BT_LOGE_NODE(node,
4056 "Invalid trace's `minor` attribute: expecting 8.");
4057 goto error;
4058 }
4059
4060 ctx->ctf_tc->minor = val;
e98a2d6e
PP
4061 _SET(set, _TRACE_MINOR_SET);
4062 } else if (!strcmp(left, "uuid")) {
4063 if (_IS_SET(set, _TRACE_UUID_SET)) {
28973adf 4064 _BT_LOGE_DUP_ATTR(node, "uuid", "trace");
e98a2d6e
PP
4065 ret = -EPERM;
4066 goto error;
4067 }
4068
4069 ret = get_unary_uuid(&node->u.ctf_expression.right,
44c440bc 4070 ctx->ctf_tc->uuid);
e98a2d6e 4071 if (ret) {
28973adf
PP
4072 _BT_LOGE_NODE(node,
4073 "Invalid trace's `uuid` attribute.");
e98a2d6e
PP
4074 goto error;
4075 }
4076
44c440bc 4077 ctx->ctf_tc->is_uuid_set = true;
e98a2d6e
PP
4078 _SET(set, _TRACE_UUID_SET);
4079 } else if (!strcmp(left, "byte_order")) {
44c440bc 4080 /* Default byte order is already known at this stage */
e98a2d6e 4081 if (_IS_SET(set, _TRACE_BYTE_ORDER_SET)) {
28973adf 4082 _BT_LOGE_DUP_ATTR(node, "byte_order",
08da4f77 4083 "trace");
e98a2d6e
PP
4084 ret = -EPERM;
4085 goto error;
4086 }
4087
44c440bc 4088 BT_ASSERT(ctx->ctf_tc->default_byte_order != -1);
e98a2d6e
PP
4089 _SET(set, _TRACE_BYTE_ORDER_SET);
4090 } else if (!strcmp(left, "packet.header")) {
4091 if (_IS_SET(set, _TRACE_PACKET_HEADER_SET)) {
28973adf
PP
4092 _BT_LOGE_NODE(node,
4093 "Duplicate `packet.header` entry in trace.");
e98a2d6e
PP
4094 ret = -EPERM;
4095 goto error;
4096 }
4097
5cd6d0e5 4098 ret = visit_field_class_specifier_list(ctx,
e98a2d6e
PP
4099 _BT_LIST_FIRST_ENTRY(
4100 &node->u.ctf_expression.right,
4101 struct ctf_node, siblings),
5cd6d0e5 4102 &ctx->ctf_tc->packet_header_fc);
e98a2d6e 4103 if (ret) {
28973adf 4104 _BT_LOGE_NODE(node,
5cd6d0e5 4105 "Cannot create trace's packet header field class.");
e98a2d6e
PP
4106 goto error;
4107 }
4108
5cd6d0e5 4109 BT_ASSERT(ctx->ctf_tc->packet_header_fc);
e98a2d6e
PP
4110 _SET(set, _TRACE_PACKET_HEADER_SET);
4111 } else {
28973adf
PP
4112 _BT_LOGW_NODE(node,
4113 "Unknown attribute in stream class: "
08da4f77 4114 "attr-name=\"%s\"", left);
e98a2d6e
PP
4115 }
4116
4117 g_free(left);
4118 left = NULL;
4119 break;
4120 }
4121 default:
28973adf 4122 _BT_LOGE_NODE(node, "Unknown expression in trace.");
e98a2d6e
PP
4123 ret = -EINVAL;
4124 goto error;
4125 }
4126
4127 return 0;
4128
4129error:
4130 g_free(left);
e98a2d6e
PP
4131 return ret;
4132}
4133
4134static
4135int visit_trace_decl(struct ctx *ctx, struct ctf_node *node)
4136{
4137 int ret = 0;
4138 int set = 0;
4139 struct ctf_node *iter;
4140 struct bt_list_head *decl_list = &node->u.trace.declaration_list;
4141
4142 if (node->visited) {
4143 goto end;
4144 }
4145
4146 node->visited = TRUE;
4147
4148 if (ctx->is_trace_visited) {
28973adf 4149 _BT_LOGE_NODE(node, "Duplicate trace (`trace` block).");
e98a2d6e
PP
4150 ret = -EEXIST;
4151 goto error;
4152 }
4153
44c440bc 4154 _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
e98a2d6e
PP
4155
4156 bt_list_for_each_entry(iter, decl_list, siblings) {
4157 ret = visit_trace_decl_entry(ctx, iter, &set);
4158 if (ret) {
28973adf
PP
4159 _BT_LOGE_NODE(iter, "Cannot visit trace's entry (`trace` block): "
4160 "ret=%d", ret);
e98a2d6e
PP
4161 ctx_pop_scope(ctx);
4162 goto error;
4163 }
4164 }
4165
4166 ctx_pop_scope(ctx);
4167
4168 if (!_IS_SET(&set, _TRACE_MAJOR_SET)) {
28973adf
PP
4169 _BT_LOGE_NODE(node,
4170 "Missing `major` attribute in trace (`trace` block).");
e98a2d6e
PP
4171 ret = -EPERM;
4172 goto error;
4173 }
4174
4175 if (!_IS_SET(&set, _TRACE_MINOR_SET)) {
28973adf
PP
4176 _BT_LOGE_NODE(node,
4177 "Missing `minor` attribute in trace (`trace` block).");
e98a2d6e
PP
4178 ret = -EPERM;
4179 goto error;
4180 }
4181
4182 if (!_IS_SET(&set, _TRACE_BYTE_ORDER_SET)) {
28973adf
PP
4183 _BT_LOGE_NODE(node,
4184 "Missing `byte_order` attribute in trace (`trace` block).");
e98a2d6e
PP
4185 ret = -EPERM;
4186 goto error;
4187 }
4188
44c440bc 4189 ctx->is_trace_visited = true;
e98a2d6e
PP
4190
4191end:
4192 return 0;
4193
4194error:
4195 return ret;
4196}
4197
4198static
4199int visit_env(struct ctx *ctx, struct ctf_node *node)
4200{
4201 int ret = 0;
4202 char *left = NULL;
4203 struct ctf_node *entry_node;
4204 struct bt_list_head *decl_list = &node->u.env.declaration_list;
4205
4206 if (node->visited) {
4207 goto end;
4208 }
4209
4210 node->visited = TRUE;
4211
4212 bt_list_for_each_entry(entry_node, decl_list, siblings) {
4213 struct bt_list_head *right_head =
4214 &entry_node->u.ctf_expression.right;
4215
4216 if (entry_node->type != NODE_CTF_EXPRESSION) {
28973adf
PP
4217 _BT_LOGE_NODE(entry_node,
4218 "Wrong expression in environment entry: "
08da4f77 4219 "node-type=%d", entry_node->type);
e98a2d6e
PP
4220 ret = -EPERM;
4221 goto error;
4222 }
4223
4224 left = concatenate_unary_strings(
4225 &entry_node->u.ctf_expression.left);
4226 if (!left) {
28973adf
PP
4227 _BT_LOGE_NODE(entry_node,
4228 "Cannot get environment entry's name.");
e98a2d6e
PP
4229 ret = -EINVAL;
4230 goto error;
4231 }
4232
4233 if (is_unary_string(right_head)) {
4234 char *right = concatenate_unary_strings(right_head);
4235
4236 if (!right) {
28973adf
PP
4237 _BT_LOGE_NODE(entry_node,
4238 "Unexpected unary expression for environment entry's value: "
08da4f77 4239 "name=\"%s\"", left);
e98a2d6e
PP
4240 ret = -EINVAL;
4241 goto error;
4242 }
4243
7bf5af54
PP
4244 if (strcmp(left, "tracer_name") == 0) {
4245 if (strncmp(right, "lttng", 5) == 0) {
4246 BT_LOGI("Detected LTTng trace from `%s` environment value: "
4247 "tracer-name=\"%s\"",
4248 left, right);
44c440bc 4249 ctx->is_lttng = true;
f4421ff3
PP
4250 }
4251 }
4252
44c440bc
PP
4253 ctf_trace_class_append_env_entry(ctx->ctf_tc,
4254 left, CTF_TRACE_CLASS_ENV_ENTRY_TYPE_STR,
4255 right, 0);
e98a2d6e 4256 g_free(right);
e98a2d6e
PP
4257 } else if (is_unary_unsigned(right_head) ||
4258 is_unary_signed(right_head)) {
4259 int64_t v;
4260
4261 if (is_unary_unsigned(right_head)) {
4262 ret = get_unary_unsigned(right_head,
4263 (uint64_t *) &v);
4264 } else {
4265 ret = get_unary_signed(right_head, &v);
4266 }
4267 if (ret) {
28973adf
PP
4268 _BT_LOGE_NODE(entry_node,
4269 "Unexpected unary expression for environment entry's value: "
08da4f77 4270 "name=\"%s\"", left);
e98a2d6e
PP
4271 ret = -EINVAL;
4272 goto error;
4273 }
4274
44c440bc
PP
4275 ctf_trace_class_append_env_entry(ctx->ctf_tc,
4276 left, CTF_TRACE_CLASS_ENV_ENTRY_TYPE_INT,
4277 NULL, v);
e98a2d6e 4278 } else {
28973adf
PP
4279 _BT_LOGW_NODE(entry_node,
4280 "Environment entry has unknown type: "
08da4f77 4281 "name=\"%s\"", left);
e98a2d6e
PP
4282 }
4283
4284 g_free(left);
4285 left = NULL;
4286 }
4287
4288end:
4289 return 0;
4290
4291error:
4292 g_free(left);
e98a2d6e
PP
4293 return ret;
4294}
4295
4296static
4297int set_trace_byte_order(struct ctx *ctx, struct ctf_node *trace_node)
4298{
4299 int ret = 0;
4300 int set = 0;
4301 char *left = NULL;
4302 struct ctf_node *node;
4303 struct bt_list_head *decl_list = &trace_node->u.trace.declaration_list;
4304
4305 bt_list_for_each_entry(node, decl_list, siblings) {
4306 if (node->type == NODE_CTF_EXPRESSION) {
4307 struct ctf_node *right_node;
4308
4309 left = concatenate_unary_strings(
4310 &node->u.ctf_expression.left);
4311 if (!left) {
28973adf
PP
4312 _BT_LOGE_NODE(node,
4313 "Cannot concatenate unary strings.");
e98a2d6e
PP
4314 ret = -EINVAL;
4315 goto error;
4316 }
4317
4318 if (!strcmp(left, "byte_order")) {
44c440bc 4319 enum ctf_byte_order bo;
e98a2d6e
PP
4320
4321 if (_IS_SET(&set, _TRACE_BYTE_ORDER_SET)) {
28973adf 4322 _BT_LOGE_DUP_ATTR(node, "byte_order",
08da4f77 4323 "trace");
e98a2d6e
PP
4324 ret = -EPERM;
4325 goto error;
4326 }
4327
4328 _SET(&set, _TRACE_BYTE_ORDER_SET);
4329 right_node = _BT_LIST_FIRST_ENTRY(
4330 &node->u.ctf_expression.right,
4331 struct ctf_node, siblings);
55314f2a 4332 bo = byte_order_from_unary_expr(right_node);
44c440bc 4333 if (bo == -1) {
28973adf
PP
4334 _BT_LOGE_NODE(node,
4335 "Invalid `byte_order` attribute in trace (`trace` block): "
4336 "expecting `le`, `be`, or `network`.");
e98a2d6e
PP
4337 ret = -EINVAL;
4338 goto error;
44c440bc 4339 } else if (bo == CTF_BYTE_ORDER_DEFAULT) {
28973adf
PP
4340 _BT_LOGE_NODE(node,
4341 "Invalid `byte_order` attribute in trace (`trace` block): "
08da4f77 4342 "cannot be set to `native` here.");
e98a2d6e
PP
4343 ret = -EPERM;
4344 goto error;
4345 }
4346
44c440bc 4347 ctx->ctf_tc->default_byte_order = bo;
e98a2d6e
PP
4348 }
4349
4350 g_free(left);
4351 left = NULL;
4352 }
4353 }
4354
4355 if (!_IS_SET(&set, _TRACE_BYTE_ORDER_SET)) {
28973adf
PP
4356 _BT_LOGE_NODE(trace_node,
4357 "Missing `byte_order` attribute in trace (`trace` block).");
e98a2d6e
PP
4358 ret = -EINVAL;
4359 goto error;
4360 }
4361
4362 return 0;
4363
4364error:
4365 g_free(left);
e98a2d6e
PP
4366 return ret;
4367}
4368
4369static
4370int visit_clock_decl_entry(struct ctx *ctx, struct ctf_node *entry_node,
44c440bc
PP
4371 struct bt_clock_class *clock, int *set, int64_t *offset_seconds,
4372 uint64_t *offset_cycles)
e98a2d6e
PP
4373{
4374 int ret = 0;
4375 char *left = NULL;
4376
4377 if (entry_node->type != NODE_CTF_EXPRESSION) {
28973adf
PP
4378 _BT_LOGE_NODE(entry_node,
4379 "Unexpected node type: node-type=%d",
4380 entry_node->type);
e98a2d6e
PP
4381 ret = -EPERM;
4382 goto error;
4383 }
4384
4385 left = concatenate_unary_strings(&entry_node->u.ctf_expression.left);
4386 if (!left) {
28973adf 4387 _BT_LOGE_NODE(entry_node, "Cannot concatenate unary strings.");
e98a2d6e
PP
4388 ret = -EINVAL;
4389 goto error;
4390 }
4391
4392 if (!strcmp(left, "name")) {
4393 char *right;
4394
4395 if (_IS_SET(set, _CLOCK_NAME_SET)) {
28973adf 4396 _BT_LOGE_DUP_ATTR(entry_node, "name", "clock class");
e98a2d6e
PP
4397 ret = -EPERM;
4398 goto error;
4399 }
4400
4401 right = concatenate_unary_strings(
4402 &entry_node->u.ctf_expression.right);
4403 if (!right) {
28973adf
PP
4404 _BT_LOGE_NODE(entry_node,
4405 "Unexpected unary expression for clock class's `name` attribute.");
e98a2d6e
PP
4406 ret = -EINVAL;
4407 goto error;
4408 }
4409
50842bdc 4410 ret = bt_clock_class_set_name(clock, right);
e98a2d6e 4411 if (ret) {
28973adf
PP
4412 _BT_LOGE_NODE(entry_node,
4413 "cannot set clock class's name");
e98a2d6e
PP
4414 g_free(right);
4415 goto error;
4416 }
4417
4418 g_free(right);
4419 _SET(set, _CLOCK_NAME_SET);
4420 } else if (!strcmp(left, "uuid")) {
44c440bc 4421 uint8_t uuid[BABELTRACE_UUID_LEN];
e98a2d6e
PP
4422
4423 if (_IS_SET(set, _CLOCK_UUID_SET)) {
28973adf 4424 _BT_LOGE_DUP_ATTR(entry_node, "uuid", "clock class");
e98a2d6e
PP
4425 ret = -EPERM;
4426 goto error;
4427 }
4428
4429 ret = get_unary_uuid(&entry_node->u.ctf_expression.right, uuid);
4430 if (ret) {
28973adf
PP
4431 _BT_LOGE_NODE(entry_node,
4432 "Invalid clock class's `uuid` attribute.");
e98a2d6e
PP
4433 goto error;
4434 }
4435
50842bdc 4436 ret = bt_clock_class_set_uuid(clock, uuid);
e98a2d6e 4437 if (ret) {
28973adf
PP
4438 _BT_LOGE_NODE(entry_node,
4439 "Cannot set clock class's UUID.");
e98a2d6e
PP
4440 goto error;
4441 }
4442
4443 _SET(set, _CLOCK_UUID_SET);
4444 } else if (!strcmp(left, "description")) {
4445 char *right;
4446
4447 if (_IS_SET(set, _CLOCK_DESCRIPTION_SET)) {
28973adf
PP
4448 _BT_LOGE_DUP_ATTR(entry_node, "description",
4449 "clock class");
e98a2d6e
PP
4450 ret = -EPERM;
4451 goto error;
4452 }
4453
4454 right = concatenate_unary_strings(
4455 &entry_node->u.ctf_expression.right);
4456 if (!right) {
28973adf
PP
4457 _BT_LOGE_NODE(entry_node,
4458 "Unexpected unary expression for clock class's `description` attribute.");
e98a2d6e
PP
4459 ret = -EINVAL;
4460 goto error;
4461 }
4462
50842bdc 4463 ret = bt_clock_class_set_description(clock, right);
e98a2d6e 4464 if (ret) {
28973adf
PP
4465 _BT_LOGE_NODE(entry_node,
4466 "Cannot set clock class's description.");
e98a2d6e
PP
4467 g_free(right);
4468 goto error;
4469 }
4470
4471 g_free(right);
4472 _SET(set, _CLOCK_DESCRIPTION_SET);
4473 } else if (!strcmp(left, "freq")) {
44c440bc 4474 uint64_t freq = UINT64_C(-1);
e98a2d6e
PP
4475
4476 if (_IS_SET(set, _CLOCK_FREQ_SET)) {
28973adf 4477 _BT_LOGE_DUP_ATTR(entry_node, "freq", "clock class");
e98a2d6e
PP
4478 ret = -EPERM;
4479 goto error;
4480 }
4481
4482 ret = get_unary_unsigned(
4483 &entry_node->u.ctf_expression.right, &freq);
4484 if (ret) {
28973adf
PP
4485 _BT_LOGE_NODE(entry_node,
4486 "Unexpected unary expression for clock class's `freq` attribute.");
e98a2d6e
PP
4487 ret = -EINVAL;
4488 goto error;
4489 }
4490
44c440bc 4491 if (freq == UINT64_C(-1) || freq == 0) {
239744fc
PP
4492 _BT_LOGE_NODE(entry_node,
4493 "Invalid clock class frequency: freq=%" PRIu64,
4494 freq);
4495 ret = -EINVAL;
4496 goto error;
4497 }
4498
50842bdc 4499 ret = bt_clock_class_set_frequency(clock, freq);
e98a2d6e 4500 if (ret) {
28973adf
PP
4501 _BT_LOGE_NODE(entry_node,
4502 "Cannot set clock class's frequency.");
e98a2d6e
PP
4503 goto error;
4504 }
4505
4506 _SET(set, _CLOCK_FREQ_SET);
4507 } else if (!strcmp(left, "precision")) {
4508 uint64_t precision;
4509
4510 if (_IS_SET(set, _CLOCK_PRECISION_SET)) {
28973adf
PP
4511 _BT_LOGE_DUP_ATTR(entry_node, "precision",
4512 "clock class");
e98a2d6e
PP
4513 ret = -EPERM;
4514 goto error;
4515 }
4516
4517 ret = get_unary_unsigned(
4518 &entry_node->u.ctf_expression.right, &precision);
4519 if (ret) {
28973adf
PP
4520 _BT_LOGE_NODE(entry_node,
4521 "Unexpected unary expression for clock class's `precision` attribute.");
e98a2d6e
PP
4522 ret = -EINVAL;
4523 goto error;
4524 }
4525
50842bdc 4526 ret = bt_clock_class_set_precision(clock, precision);
e98a2d6e 4527 if (ret) {
28973adf
PP
4528 _BT_LOGE_NODE(entry_node,
4529 "Cannot set clock class's precision.");
e98a2d6e
PP
4530 goto error;
4531 }
4532
4533 _SET(set, _CLOCK_PRECISION_SET);
4534 } else if (!strcmp(left, "offset_s")) {
e98a2d6e 4535 if (_IS_SET(set, _CLOCK_OFFSET_S_SET)) {
28973adf
PP
4536 _BT_LOGE_DUP_ATTR(entry_node, "offset_s",
4537 "clock class");
e98a2d6e
PP
4538 ret = -EPERM;
4539 goto error;
4540 }
4541
fb4ac437 4542 ret = get_unary_signed(
44c440bc 4543 &entry_node->u.ctf_expression.right, offset_seconds);
e98a2d6e 4544 if (ret) {
28973adf
PP
4545 _BT_LOGE_NODE(entry_node,
4546 "Unexpected unary expression for clock class's `offset_s` attribute.");
e98a2d6e
PP
4547 ret = -EINVAL;
4548 goto error;
4549 }
4550
e98a2d6e
PP
4551 _SET(set, _CLOCK_OFFSET_S_SET);
4552 } else if (!strcmp(left, "offset")) {
e98a2d6e 4553 if (_IS_SET(set, _CLOCK_OFFSET_SET)) {
28973adf 4554 _BT_LOGE_DUP_ATTR(entry_node, "offset", "clock class");
e98a2d6e
PP
4555 ret = -EPERM;
4556 goto error;
4557 }
4558
44c440bc
PP
4559 ret = get_unary_unsigned(
4560 &entry_node->u.ctf_expression.right, offset_cycles);
e98a2d6e 4561 if (ret) {
28973adf
PP
4562 _BT_LOGE_NODE(entry_node,
4563 "Unexpected unary expression for clock class's `offset` attribute.");
e98a2d6e
PP
4564 ret = -EINVAL;
4565 goto error;
4566 }
4567
e98a2d6e
PP
4568 _SET(set, _CLOCK_OFFSET_SET);
4569 } else if (!strcmp(left, "absolute")) {
4570 struct ctf_node *right;
4571
4572 if (_IS_SET(set, _CLOCK_ABSOLUTE_SET)) {
28973adf
PP
4573 _BT_LOGE_DUP_ATTR(entry_node, "absolute",
4574 "clock class");
e98a2d6e
PP
4575 ret = -EPERM;
4576 goto error;
4577 }
4578
4579 right = _BT_LIST_FIRST_ENTRY(
4580 &entry_node->u.ctf_expression.right,
4581 struct ctf_node, siblings);
55314f2a 4582 ret = get_boolean(right);
e98a2d6e 4583 if (ret < 0) {
28973adf
PP
4584 _BT_LOGE_NODE(entry_node,
4585 "Unexpected unary expression for clock class's `absolute` attribute.");
e98a2d6e
PP
4586 ret = -EINVAL;
4587 goto error;
4588 }
4589
50842bdc 4590 ret = bt_clock_class_set_is_absolute(clock, ret);
e98a2d6e 4591 if (ret) {
28973adf
PP
4592 _BT_LOGE_NODE(entry_node,
4593 "Cannot set clock class's absolute flag.");
e98a2d6e
PP
4594 goto error;
4595 }
4596
4597 _SET(set, _CLOCK_ABSOLUTE_SET);
4598 } else {
28973adf
PP
4599 _BT_LOGW_NODE(entry_node,
4600 "Unknown attribute in clock class: attr-name=\"%s\"",
e98a2d6e
PP
4601 left);
4602 }
4603
4604 g_free(left);
4605 left = NULL;
e98a2d6e
PP
4606 return 0;
4607
4608error:
4609 g_free(left);
e98a2d6e
PP
4610 return ret;
4611}
4612
44c440bc
PP
4613static inline
4614uint64_t cycles_from_ns(uint64_t frequency, uint64_t ns)
92540773 4615{
44c440bc 4616 uint64_t cycles;
92540773
JD
4617
4618 /* 1GHz */
44c440bc 4619 if (frequency == UINT64_C(1000000000)) {
92540773
JD
4620 cycles = ns;
4621 } else {
4622 cycles = (uint64_t) (((double) ns * (double) frequency) / 1e9);
4623 }
4624
4625 return cycles;
4626}
4627
4628static
44c440bc
PP
4629void calibrate_clock_class_offsets(int64_t *offset_seconds,
4630 uint64_t *offset_cycles, uint64_t freq)
4631{
4632 if (*offset_cycles >= freq) {
4633 const uint64_t s_in_offset_cycles = *offset_cycles / freq;
4634
4635 *offset_seconds += (int64_t) s_in_offset_cycles;
4636 *offset_cycles -= (s_in_offset_cycles * freq);
4637 }
4638}
4639
4640static
4641void apply_clock_class_offset(struct ctx *ctx, struct bt_clock_class *clock)
92540773
JD
4642{
4643 int ret;
4644 uint64_t freq;
44c440bc
PP
4645 int64_t offset_s_to_apply = ctx->decoder_config.clock_class_offset_s;
4646 uint64_t offset_ns_to_apply;
4647 int64_t cur_offset_s;
4648 uint64_t cur_offset_cycles;
92540773 4649
44c440bc
PP
4650 if (ctx->decoder_config.clock_class_offset_s == 0 &&
4651 ctx->decoder_config.clock_class_offset_ns == 0) {
92540773
JD
4652 goto end;
4653 }
4654
44c440bc
PP
4655 /* Transfer nanoseconds to seconds as much as possible */
4656 if (ctx->decoder_config.clock_class_offset_ns < 0) {
4657 const int64_t abs_ns = -ctx->decoder_config.clock_class_offset_ns;
4658 const int64_t abs_extra_s = abs_ns / INT64_C(1000000000) + 1;
4659 const int64_t extra_s = -abs_extra_s;
4660 const int64_t offset_ns = ctx->decoder_config.clock_class_offset_ns -
4661 (extra_s * INT64_C(1000000000));
4662
4663 BT_ASSERT(offset_ns > 0);
4664 offset_ns_to_apply = (uint64_t) offset_ns;
4665 offset_s_to_apply += extra_s;
4666 } else {
4667 const int64_t extra_s = ctx->decoder_config.clock_class_offset_ns /
4668 INT64_C(1000000000);
4669 const int64_t offset_ns = ctx->decoder_config.clock_class_offset_ns -
4670 (extra_s * INT64_C(1000000000));
4671
4672 BT_ASSERT(offset_ns >= 0);
4673 offset_ns_to_apply = (uint64_t) offset_ns;
4674 offset_s_to_apply += extra_s;
92540773
JD
4675 }
4676
44c440bc
PP
4677 freq = bt_clock_class_get_frequency(clock);
4678 bt_clock_class_get_offset(clock, &cur_offset_s, &cur_offset_cycles);
4679
4680 /* Apply offsets */
4681 cur_offset_s += offset_s_to_apply;
4682 cur_offset_cycles += cycles_from_ns(freq, offset_ns_to_apply);
4683
4684 /*
4685 * Recalibrate offsets because the part in cycles can be greater
4686 * than the frequency at this point.
4687 */
4688 calibrate_clock_class_offsets(&cur_offset_s, &cur_offset_cycles, freq);
4689
4690 /* Set final offsets */
4691 ret = bt_clock_class_set_offset(clock, cur_offset_s, cur_offset_cycles);
4692 BT_ASSERT(ret == 0);
92540773
JD
4693
4694end:
44c440bc 4695 return;
92540773
JD
4696}
4697
4698static
1e649dff 4699int visit_clock_decl(struct ctx *ctx, struct ctf_node *clock_node)
e98a2d6e
PP
4700{
4701 int ret = 0;
4702 int set = 0;
50842bdc 4703 struct bt_clock_class *clock;
e98a2d6e
PP
4704 struct ctf_node *entry_node;
4705 struct bt_list_head *decl_list = &clock_node->u.clock.declaration_list;
f4421ff3 4706 const char *clock_class_name;
44c440bc
PP
4707 int64_t offset_seconds = 0;
4708 uint64_t offset_cycles = 0;
4709 uint64_t freq;
e98a2d6e
PP
4710
4711 if (clock_node->visited) {
4712 return 0;
4713 }
4714
4715 clock_node->visited = TRUE;
f3534905
PP
4716
4717 /* CTF 1.8's default frequency for a clock class is 1 GHz */
44c440bc 4718 clock = bt_clock_class_create();
e98a2d6e 4719 if (!clock) {
28973adf
PP
4720 _BT_LOGE_NODE(clock_node,
4721 "Cannot create default clock class.");
e98a2d6e 4722 ret = -ENOMEM;
44c440bc
PP
4723 goto end;
4724 }
4725
4726 /* CTF: not absolute by default */
4727 ret = bt_clock_class_set_is_absolute(clock, BT_FALSE);
4728 if (ret) {
4729 _BT_LOGE_NODE(clock_node,
4730 "Cannot set clock class's absolute flag.");
4731 goto end;
e98a2d6e
PP
4732 }
4733
4734 bt_list_for_each_entry(entry_node, decl_list, siblings) {
44c440bc
PP
4735 ret = visit_clock_decl_entry(ctx, entry_node, clock, &set,
4736 &offset_seconds, &offset_cycles);
e98a2d6e 4737 if (ret) {
28973adf
PP
4738 _BT_LOGE_NODE(entry_node,
4739 "Cannot visit clock class's entry: ret=%d",
4740 ret);
44c440bc 4741 goto end;
e98a2d6e
PP
4742 }
4743 }
4744
4745 if (!_IS_SET(&set, _CLOCK_NAME_SET)) {
28973adf
PP
4746 _BT_LOGE_NODE(clock_node,
4747 "Missing `name` attribute in clock class.");
e98a2d6e 4748 ret = -EPERM;
44c440bc 4749 goto end;
e98a2d6e
PP
4750 }
4751
50842bdc 4752 clock_class_name = bt_clock_class_get_name(clock);
f6ccaed9 4753 BT_ASSERT(clock_class_name);
f4421ff3
PP
4754 if (ctx->is_lttng && strcmp(clock_class_name, "monotonic") == 0) {
4755 /*
4756 * Old versions of LTTng forgot to set its clock class
4757 * as absolute, even if it is. This is important because
4758 * it's a condition to be able to sort notifications
4759 * from different sources.
4760 */
44c440bc 4761 ret = bt_clock_class_set_is_absolute(clock, BT_TRUE);
f4421ff3 4762 if (ret) {
28973adf
PP
4763 _BT_LOGE_NODE(clock_node,
4764 "Cannot set clock class's absolute flag.");
44c440bc 4765 goto end;
f4421ff3 4766 }
e98a2d6e
PP
4767 }
4768
44c440bc
PP
4769 /*
4770 * Adjust offsets so that the part in cycles is less than the
4771 * frequency (move to the part in seconds).
4772 */
4773 freq = bt_clock_class_get_frequency(clock);
4774 calibrate_clock_class_offsets(&offset_seconds, &offset_cycles, freq);
4775 BT_ASSERT(offset_cycles < bt_clock_class_get_frequency(clock));
4776 ret = bt_clock_class_set_offset(clock, offset_seconds, offset_cycles);
4777 BT_ASSERT(ret == 0);
4778 apply_clock_class_offset(ctx, clock);
4779 g_ptr_array_add(ctx->ctf_tc->clock_classes, bt_get(clock));
e98a2d6e 4780
44c440bc 4781end:
e98a2d6e 4782 BT_PUT(clock);
e98a2d6e
PP
4783 return ret;
4784}
4785
4786static
4787int visit_root_decl(struct ctx *ctx, struct ctf_node *root_decl_node)
4788{
4789 int ret = 0;
4790
4791 if (root_decl_node->visited) {
4792 goto end;
4793 }
4794
4795 root_decl_node->visited = TRUE;
4796
4797 switch (root_decl_node->type) {
4798 case NODE_TYPEDEF:
5cd6d0e5
PP
4799 ret = visit_field_class_def(ctx,
4800 root_decl_node->u.field_class_def.field_class_specifier_list,
4801 &root_decl_node->u.field_class_def.field_class_declarators);
e98a2d6e 4802 if (ret) {
28973adf 4803 _BT_LOGE_NODE(root_decl_node,
5cd6d0e5 4804 "Cannot add field class found in root scope.");
e98a2d6e
PP
4805 goto end;
4806 }
4807 break;
4808 case NODE_TYPEALIAS:
5cd6d0e5
PP
4809 ret = visit_field_class_alias(ctx, root_decl_node->u.field_class_alias.target,
4810 root_decl_node->u.field_class_alias.alias);
e98a2d6e 4811 if (ret) {
28973adf 4812 _BT_LOGE_NODE(root_decl_node,
5cd6d0e5 4813 "Cannot add field class alias found in root scope.");
e98a2d6e
PP
4814 goto end;
4815 }
4816 break;
4817 case NODE_TYPE_SPECIFIER_LIST:
4818 {
5cd6d0e5 4819 struct ctf_field_class *decl = NULL;
e98a2d6e
PP
4820
4821 /*
5cd6d0e5 4822 * Just add the field class specifier to the root
e98a2d6e
PP
4823 * declaration scope. Put local reference.
4824 */
5cd6d0e5 4825 ret = visit_field_class_specifier_list(ctx, root_decl_node, &decl);
e98a2d6e 4826 if (ret) {
28973adf 4827 _BT_LOGE_NODE(root_decl_node,
5cd6d0e5 4828 "Cannot visit root scope's field class: "
28973adf 4829 "ret=%d", ret);
f6ccaed9 4830 BT_ASSERT(!decl);
e98a2d6e
PP
4831 goto end;
4832 }
4833
5cd6d0e5 4834 ctf_field_class_destroy(decl);
44c440bc 4835 decl = NULL;
e98a2d6e
PP
4836 break;
4837 }
4838 default:
28973adf
PP
4839 _BT_LOGE_NODE(root_decl_node,
4840 "Unexpected node type: node-type=%d",
4841 root_decl_node->type);
e98a2d6e
PP
4842 ret = -EPERM;
4843 goto end;
4844 }
4845
4846end:
4847 return ret;
4848}
4849
91fd6f6a 4850static
44c440bc 4851int try_set_trace_class_name(struct ctx *ctx)
91fd6f6a 4852{
44c440bc 4853 GString *name = NULL;
91fd6f6a 4854 int ret = 0;
44c440bc
PP
4855 struct ctf_trace_class_env_entry *env_entry;
4856
4857 if (ctx->ctf_tc->name->len > 0) {
4858 /* Already set */
4859 goto end;
4860 }
91fd6f6a 4861
91fd6f6a
PP
4862 name = g_string_new(NULL);
4863 if (!name) {
28973adf 4864 BT_LOGE_STR("Failed to allocate a GString.");
91fd6f6a
PP
4865 ret = -1;
4866 goto end;
4867 }
4868
4869 /*
4870 * Check if we have a trace environment string value named `hostname`.
4871 * If so, use it as the trace name's prefix.
4872 */
44c440bc 4873 env_entry = ctf_trace_class_borrow_env_entry_by_name(ctx->ctf_tc,
91fd6f6a 4874 "hostname");
44c440bc
PP
4875 if (env_entry &&
4876 env_entry->type == CTF_TRACE_CLASS_ENV_ENTRY_TYPE_STR) {
4877 g_string_append(name, env_entry->value.str->str);
91fd6f6a 4878
44c440bc 4879 if (ctx->trace_class_name_suffix) {
91fd6f6a
PP
4880 g_string_append_c(name, G_DIR_SEPARATOR);
4881 }
4882 }
4883
44c440bc
PP
4884 if (ctx->trace_class_name_suffix) {
4885 g_string_append(name, ctx->trace_class_name_suffix);
91fd6f6a
PP
4886 }
4887
44c440bc 4888 g_string_assign(ctx->ctf_tc->name, name->str);
91fd6f6a
PP
4889 goto end;
4890
91fd6f6a 4891end:
91fd6f6a
PP
4892 if (name) {
4893 g_string_free(name, TRUE);
4894 }
4895
4896 return ret;
4897}
4898
1e649dff 4899BT_HIDDEN
55314f2a 4900struct ctf_visitor_generate_ir *ctf_visitor_generate_ir_create(
a2a54545
PP
4901 const struct ctf_metadata_decoder_config *decoder_config,
4902 const char *name)
e98a2d6e 4903{
e98a2d6e 4904 struct ctx *ctx = NULL;
e98a2d6e 4905
1e649dff 4906 /* Create visitor's context */
44c440bc 4907 ctx = ctx_create(decoder_config, name);
e98a2d6e 4908 if (!ctx) {
08da4f77 4909 BT_LOGE_STR("Cannot create visitor's context.");
e98a2d6e
PP
4910 goto error;
4911 }
4912
1e649dff
PP
4913 goto end;
4914
4915error:
4916 ctx_destroy(ctx);
4917 ctx = NULL;
4918
4919end:
1e649dff
PP
4920 return (void *) ctx;
4921}
4922
4923BT_HIDDEN
4924void ctf_visitor_generate_ir_destroy(struct ctf_visitor_generate_ir *visitor)
4925{
4926 ctx_destroy((void *) visitor);
4927}
4928
4929BT_HIDDEN
44c440bc 4930struct bt_trace *ctf_visitor_generate_ir_get_ir_trace(
1e649dff
PP
4931 struct ctf_visitor_generate_ir *visitor)
4932{
4933 struct ctx *ctx = (void *) visitor;
4934
f6ccaed9
PP
4935 BT_ASSERT(ctx);
4936 BT_ASSERT(ctx->trace);
1e649dff
PP
4937 return bt_get(ctx->trace);
4938}
4939
44c440bc
PP
4940BT_HIDDEN
4941struct ctf_trace_class *ctf_visitor_generate_ir_borrow_ctf_trace_class(
4942 struct ctf_visitor_generate_ir *visitor)
4943{
4944 struct ctx *ctx = (void *) visitor;
4945
4946 BT_ASSERT(ctx);
4947 BT_ASSERT(ctx->ctf_tc);
4948 return ctx->ctf_tc;
4949}
4950
1e649dff
PP
4951BT_HIDDEN
4952int ctf_visitor_generate_ir_visit_node(struct ctf_visitor_generate_ir *visitor,
4953 struct ctf_node *node)
4954{
4955 int ret = 0;
4956 struct ctx *ctx = (void *) visitor;
4957
08da4f77 4958 BT_LOGI_STR("Visiting metadata's AST to generate CTF IR objects.");
1e649dff 4959
e98a2d6e
PP
4960 switch (node->type) {
4961 case NODE_ROOT:
4962 {
4963 struct ctf_node *iter;
44c440bc 4964 bool got_trace_decl = false;
e98a2d6e
PP
4965
4966 /*
1e649dff 4967 * The first thing we need is the native byte order of
5cd6d0e5 4968 * the trace block, because early class aliases can have
1e649dff
PP
4969 * a `byte_order` attribute set to `native`. If we don't
4970 * have the native byte order yet, and we don't have any
4971 * trace block yet, then fail with EINCOMPLETE.
e98a2d6e 4972 */
44c440bc 4973 if (ctx->ctf_tc->default_byte_order == -1) {
1e649dff
PP
4974 bt_list_for_each_entry(iter, &node->u.root.trace, siblings) {
4975 if (got_trace_decl) {
28973adf
PP
4976 _BT_LOGE_NODE(node,
4977 "Duplicate trace (`trace` block).");
1e649dff
PP
4978 ret = -1;
4979 goto end;
4980 }
e98a2d6e 4981
1e649dff
PP
4982 ret = set_trace_byte_order(ctx, iter);
4983 if (ret) {
28973adf
PP
4984 _BT_LOGE_NODE(node,
4985 "Cannot set trace's native byte order: "
08da4f77 4986 "ret=%d", ret);
1e649dff
PP
4987 goto end;
4988 }
4989
44c440bc 4990 got_trace_decl = true;
e98a2d6e
PP
4991 }
4992
1e649dff 4993 if (!got_trace_decl) {
28973adf 4994 BT_LOGD_STR("Incomplete AST: need trace (`trace` block).");
1e649dff
PP
4995 ret = -EINCOMPLETE;
4996 goto end;
4997 }
e98a2d6e
PP
4998 }
4999
44c440bc
PP
5000 BT_ASSERT(ctx->ctf_tc->default_byte_order == CTF_BYTE_ORDER_LITTLE ||
5001 ctx->ctf_tc->default_byte_order == CTF_BYTE_ORDER_BIG);
f6ccaed9 5002 BT_ASSERT(ctx->current_scope &&
44c440bc 5003 ctx->current_scope->parent_scope == NULL);
e98a2d6e 5004
f4421ff3
PP
5005 /* Environment */
5006 bt_list_for_each_entry(iter, &node->u.root.env, siblings) {
5007 ret = visit_env(ctx, iter);
5008 if (ret) {
28973adf
PP
5009 _BT_LOGE_NODE(iter,
5010 "Cannot visit trace's environment (`env` block) entry: "
08da4f77 5011 "ret=%d", ret);
f4421ff3
PP
5012 goto end;
5013 }
5014 }
5015
f6ccaed9 5016 BT_ASSERT(ctx->current_scope &&
f4421ff3
PP
5017 ctx->current_scope->parent_scope == NULL);
5018
e98a2d6e 5019 /*
f4421ff3 5020 * Visit clock blocks.
e98a2d6e
PP
5021 */
5022 bt_list_for_each_entry(iter, &node->u.root.clock, siblings) {
1e649dff 5023 ret = visit_clock_decl(ctx, iter);
e98a2d6e 5024 if (ret) {
28973adf
PP
5025 _BT_LOGE_NODE(iter,
5026 "Cannot visit clock class: ret=%d",
e98a2d6e 5027 ret);
1e649dff 5028 goto end;
e98a2d6e
PP
5029 }
5030 }
5031
f6ccaed9 5032 BT_ASSERT(ctx->current_scope &&
1e649dff
PP
5033 ctx->current_scope->parent_scope == NULL);
5034
e98a2d6e
PP
5035 /*
5036 * Visit root declarations next, as they can be used by any
5037 * following entity.
5038 */
5039 bt_list_for_each_entry(iter, &node->u.root.declaration_list,
5040 siblings) {
5041 ret = visit_root_decl(ctx, iter);
5042 if (ret) {
28973adf
PP
5043 _BT_LOGE_NODE(iter,
5044 "Cannot visit root entry: ret=%d",
e98a2d6e 5045 ret);
1e649dff 5046 goto end;
e98a2d6e
PP
5047 }
5048 }
5049
f6ccaed9 5050 BT_ASSERT(ctx->current_scope &&
1e649dff
PP
5051 ctx->current_scope->parent_scope == NULL);
5052
5053 /* Callsite blocks are not supported */
e98a2d6e 5054 bt_list_for_each_entry(iter, &node->u.root.callsite, siblings) {
28973adf
PP
5055 _BT_LOGW_NODE(iter,
5056 "\"callsite\" blocks are not supported as of this version.");
e98a2d6e
PP
5057 }
5058
f6ccaed9 5059 BT_ASSERT(ctx->current_scope &&
1e649dff
PP
5060 ctx->current_scope->parent_scope == NULL);
5061
e98a2d6e
PP
5062 /* Trace */
5063 bt_list_for_each_entry(iter, &node->u.root.trace, siblings) {
5064 ret = visit_trace_decl(ctx, iter);
5065 if (ret) {
28973adf
PP
5066 _BT_LOGE_NODE(iter,
5067 "Cannot visit trace (`trace` block): "
08da4f77 5068 "ret=%d", ret);
1e649dff 5069 goto end;
e98a2d6e
PP
5070 }
5071 }
5072
f6ccaed9 5073 BT_ASSERT(ctx->current_scope &&
1e649dff
PP
5074 ctx->current_scope->parent_scope == NULL);
5075
e98a2d6e
PP
5076 /* Streams */
5077 bt_list_for_each_entry(iter, &node->u.root.stream, siblings) {
5078 ret = visit_stream_decl(ctx, iter);
5079 if (ret) {
28973adf
PP
5080 _BT_LOGE_NODE(iter,
5081 "Cannot visit stream class: ret=%d",
08da4f77 5082 ret);
1e649dff 5083 goto end;
e98a2d6e
PP
5084 }
5085 }
5086
f6ccaed9 5087 BT_ASSERT(ctx->current_scope &&
1e649dff
PP
5088 ctx->current_scope->parent_scope == NULL);
5089
e98a2d6e
PP
5090 /* Events */
5091 bt_list_for_each_entry(iter, &node->u.root.event, siblings) {
5092 ret = visit_event_decl(ctx, iter);
5093 if (ret) {
28973adf
PP
5094 _BT_LOGE_NODE(iter,
5095 "Cannot visit event class: ret=%d",
08da4f77 5096 ret);
1e649dff 5097 goto end;
e98a2d6e
PP
5098 }
5099 }
1e649dff 5100
f6ccaed9 5101 BT_ASSERT(ctx->current_scope &&
1e649dff 5102 ctx->current_scope->parent_scope == NULL);
e98a2d6e
PP
5103 break;
5104 }
e98a2d6e 5105 default:
28973adf
PP
5106 _BT_LOGE_NODE(node,
5107 "Unexpected node type: node-type=%d",
08da4f77 5108 node->type);
e98a2d6e 5109 ret = -EINVAL;
1e649dff 5110 goto end;
e98a2d6e
PP
5111 }
5112
44c440bc
PP
5113 /* Update default clock classes */
5114 ret = ctf_trace_class_update_default_clock_classes(ctx->ctf_tc);
5115 if (ret) {
5116 ret = -EINVAL;
5117 goto end;
5118 }
5119
5120 /* Set trace's name, if not already done */
5121 ret = try_set_trace_class_name(ctx);
5122 if (ret) {
5123 ret = -EINVAL;
5124 goto end;
5125 }
5126
5127 /* Update trace class meanings */
5128 ret = ctf_trace_class_update_meanings(ctx->ctf_tc);
5129 if (ret) {
5130 ret = -EINVAL;
5131 goto end;
5132 }
5133
5134 /* Update text arrays and sequences */
5135 ret = ctf_trace_class_update_text_array_sequence(ctx->ctf_tc);
5136 if (ret) {
5137 ret = -EINVAL;
5138 goto end;
5139 }
5140
5141 /* Resolve sequence lengths and variant tags */
5cd6d0e5 5142 ret = ctf_trace_class_resolve_field_classes(ctx->ctf_tc);
44c440bc
PP
5143 if (ret) {
5144 ret = -EINVAL;
5145 goto end;
5146 }
5147
5cd6d0e5 5148 /* Update "in IR" for field classes */
44c440bc
PP
5149 ret = ctf_trace_class_update_in_ir(ctx->ctf_tc);
5150 if (ret) {
5151 ret = -EINVAL;
5152 goto end;
5153 }
5154
5155 /* Update saved value indexes */
5156 ret = ctf_trace_class_update_value_storing_indexes(ctx->ctf_tc);
e98a2d6e 5157 if (ret) {
44c440bc
PP
5158 ret = -EINVAL;
5159 goto end;
5160 }
5161
5162 /* Validate what we have so far */
5163 ret = ctf_trace_class_validate(ctx->ctf_tc);
5164 if (ret) {
5165 ret = -EINVAL;
5166 goto end;
5167 }
5168
5169 /* Copy new CTF metadata -> new IR metadata */
5170 ret = ctf_trace_class_translate(ctx->trace, ctx->ctf_tc);
5171 if (ret) {
5172 ret = -EINVAL;
5173 goto end;
e98a2d6e
PP
5174 }
5175
1e649dff 5176end:
e98a2d6e
PP
5177 return ret;
5178}
This page took 0.346236 seconds and 4 git commands to generate.