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