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