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