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