* Based on older ctf-visitor-generate-io-struct.c.
*
* Copyright 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- * Copyright 2015-2016 - Philippe Proulx <philippe.proulx@efficios.com>
+ * Copyright 2015-2018 - Philippe Proulx <philippe.proulx@efficios.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* SOFTWARE.
*/
+#define BT_LOG_TAG "PLUGIN-CTF-METADATA-IR-VISITOR"
+#include "logging.h"
+
#include <stdio.h>
#include <unistd.h>
#include <string.h>
+#include <stdbool.h>
#include <stdlib.h>
#include <ctype.h>
-#include <assert.h>
+#include <babeltrace/assert-internal.h>
#include <glib.h>
#include <inttypes.h>
#include <errno.h>
-#include <babeltrace/compat/uuid.h>
-#include <babeltrace/endian.h>
-#include <babeltrace/ref.h>
-#include <babeltrace/ctf-ir/trace.h>
-#include <babeltrace/ctf-ir/stream-class.h>
-#include <babeltrace/ctf-ir/event.h>
-#include <babeltrace/ctf-ir/event-class.h>
-#include <babeltrace/ctf-ir/field-types.h>
-#include <babeltrace/ctf-ir/field-types-internal.h>
-#include <babeltrace/ctf-ir/clock-class.h>
+#include <babeltrace/common-internal.h>
+#include <babeltrace/compat/uuid-internal.h>
+#include <babeltrace/endian-internal.h>
+#include <babeltrace/babeltrace.h>
#include "scanner.h"
#include "parser.h"
#include "ast.h"
+#include "decoder.h"
+#include "ctf-meta.h"
+#include "ctf-meta-visitors.h"
/* Bit value (left shift) */
#define _BV(_val) (1 << (_val))
/* Set bit in a set of bits */
#define _SET(_set, _mask) (*(_set) |= (_mask))
+/* Try to push scope, or go to the `error` label */
+#define _TRY_PUSH_SCOPE_OR_GOTO_ERROR() \
+ do { \
+ ret = ctx_push_scope(ctx); \
+ if (ret) { \
+ BT_LOGE_STR("Cannot push scope."); \
+ goto error; \
+ } \
+ } while (0)
+
/* Bits for verifying existing attributes in various declarations */
enum {
_CLOCK_NAME_SET = _BV(0),
_EVENT_ID_SET = _BV(1),
_EVENT_MODEL_EMF_URI_SET = _BV(2),
_EVENT_STREAM_ID_SET = _BV(3),
- _EVENT_LOGLEVEL_SET = _BV(4),
+ _EVENT_LOG_LEVEL_SET = _BV(4),
_EVENT_CONTEXT_SET = _BV(5),
_EVENT_FIELDS_SET = _BV(6),
};
enum loglevel {
- LOGLEVEL_EMERG = 0,
- LOGLEVEL_ALERT = 1,
- LOGLEVEL_CRIT = 2,
- LOGLEVEL_ERR = 3,
- LOGLEVEL_WARNING = 4,
- LOGLEVEL_NOTICE = 5,
- LOGLEVEL_INFO = 6,
- LOGLEVEL_DEBUG_SYSTEM = 7,
- LOGLEVEL_DEBUG_PROGRAM = 8,
- LOGLEVEL_DEBUG_PROCESS = 9,
- LOGLEVEL_DEBUG_MODULE = 10,
- LOGLEVEL_DEBUG_UNIT = 11,
- LOGLEVEL_DEBUG_FUNCTION = 12,
- LOGLEVEL_DEBUG_LINE = 13,
- LOGLEVEL_DEBUG = 14,
+ LOG_LEVEL_EMERG = 0,
+ LOG_LEVEL_ALERT = 1,
+ LOG_LEVEL_CRIT = 2,
+ LOG_LEVEL_ERR = 3,
+ LOG_LEVEL_WARNING = 4,
+ LOG_LEVEL_NOTICE = 5,
+ LOG_LEVEL_INFO = 6,
+ LOG_LEVEL_DEBUG_SYSTEM = 7,
+ LOG_LEVEL_DEBUG_PROGRAM = 8,
+ LOG_LEVEL_DEBUG_PROCESS = 9,
+ LOG_LEVEL_DEBUG_MODULE = 10,
+ LOG_LEVEL_DEBUG_UNIT = 11,
+ LOG_LEVEL_DEBUG_FUNCTION = 12,
+ LOG_LEVEL_DEBUG_LINE = 13,
+ LOG_LEVEL_DEBUG = 14,
_NR_LOGLEVELS = 15,
};
-/* Prefixes of type aliases */
+/* Prefixes of class aliases */
#define _PREFIX_ALIAS 'a'
#define _PREFIX_ENUM 'e'
#define _PREFIX_STRUCT 's'
#define _PREFIX_VARIANT 'v'
/* First entry in a BT list */
-#define _BT_LIST_FIRST_ENTRY(_ptr, _type, _member) \
- bt_list_entry((_ptr)->next, _type, _member)
-
-#define _BT_CTF_FIELD_TYPE_INIT(_name) struct bt_ctf_field_type *_name = NULL;
+#define _BT_LIST_FIRST_ENTRY(_ptr, _class, _member) \
+ bt_list_entry((_ptr)->next, _class, _member)
-/* Error printing wrappers */
-#define _PERROR(_fmt, ...) \
- do { \
- fprintf(ctx->efd, "[error] %s: " _fmt "\n", \
- __func__, __VA_ARGS__); \
- } while (0)
-
-#define _PWARNING(_fmt, ...) \
- do { \
- fprintf(ctx->efd, "[warning] %s: " _fmt "\n", \
- __func__, __VA_ARGS__); \
- } while (0)
+#define _BT_LOGE_DUP_ATTR(_node, _attr, _entity) \
+ _BT_LOGE_LINENO((_node)->lineno, \
+ "Duplicate attribute in %s: attr-name=\"%s\"", \
+ _entity, _attr)
-#define _FPERROR(_stream, _fmt, ...) \
- do { \
- fprintf(_stream, "[error] %s: " _fmt "\n", \
- __func__, __VA_ARGS__); \
- } while (0)
+#define _BT_LOGE_NODE(_node, _msg, args...) \
+ _BT_LOGE_LINENO((_node)->lineno, _msg, ## args)
-#define _FPWARNING(_stream, _fmt, ...) \
- do { \
- fprintf(_stream, "[warning] %s: " _fmt "\n", \
- __func__, __VA_ARGS__); \
- } while (0)
+#define _BT_LOGW_NODE(_node, _msg, args...) \
+ _BT_LOGW_LINENO((_node)->lineno, _msg, ## args)
-#define _PERROR_DUP_ATTR(_attr, _entity) \
- do { \
- fprintf(ctx->efd, \
- "[error] %s: duplicate attribute \"" \
- _attr "\" in " _entity "\n", __func__); \
- } while (0)
+#define _BT_LOGV_NODE(_node, _msg, args...) \
+ _BT_LOGV_LINENO((_node)->lineno, _msg, ## args)
/*
* Declaration scope of a visitor context. This represents a TSDL
*/
struct ctx_decl_scope {
/*
- * Alias name to field type.
+ * Alias name to field class.
*
- * GQuark -> struct bt_ctf_field_type *
+ * GQuark -> struct ctf_field_class * (owned by this)
*/
GHashTable *decl_map;
};
/*
- * Visitor context.
+ * Visitor context (private).
*/
struct ctx {
- /* Trace being filled (weak ref.) */
- struct bt_ctf_trace *trace;
+ /* Trace IR trace class being filled (owned by this) */
+ bt_trace_class *trace_class;
- /* Error stream to use during visit */
- FILE *efd;
+ /* CTF meta trace being filled (owned by this) */
+ struct ctf_trace_class *ctf_tc;
- /* Current declaration scope (top of the stack) */
+ /* Current declaration scope (top of the stack) (owned by this) */
struct ctx_decl_scope *current_scope;
- /* 1 if trace declaration is visited */
- int is_trace_visited;
+ /* True if trace declaration is visited */
+ bool is_trace_visited;
- /* Trace attributes */
- uint64_t trace_major;
- uint64_t trace_minor;
- unsigned char trace_uuid[BABELTRACE_UUID_LEN];
-
- /*
- * Stream IDs to stream classes.
- *
- * int64_t -> struct bt_ctf_stream_class *
- */
- GHashTable *stream_classes;
-};
+ /* True if this is an LTTng trace */
+ bool is_lttng;
-static
-const char *loglevel_str [] = {
- [ LOGLEVEL_EMERG ] = "TRACE_EMERG",
- [ LOGLEVEL_ALERT ] = "TRACE_ALERT",
- [ LOGLEVEL_CRIT ] = "TRACE_CRIT",
- [ LOGLEVEL_ERR ] = "TRACE_ERR",
- [ LOGLEVEL_WARNING ] = "TRACE_WARNING",
- [ LOGLEVEL_NOTICE ] = "TRACE_NOTICE",
- [ LOGLEVEL_INFO ] = "TRACE_INFO",
- [ LOGLEVEL_DEBUG_SYSTEM ] = "TRACE_DEBUG_SYSTEM",
- [ LOGLEVEL_DEBUG_PROGRAM ] = "TRACE_DEBUG_PROGRAM",
- [ LOGLEVEL_DEBUG_PROCESS ] = "TRACE_DEBUG_PROCESS",
- [ LOGLEVEL_DEBUG_MODULE ] = "TRACE_DEBUG_MODULE",
- [ LOGLEVEL_DEBUG_UNIT ] = "TRACE_DEBUG_UNIT",
- [ LOGLEVEL_DEBUG_FUNCTION ] = "TRACE_DEBUG_FUNCTION",
- [ LOGLEVEL_DEBUG_LINE ] = "TRACE_DEBUG_LINE",
- [ LOGLEVEL_DEBUG ] = "TRACE_DEBUG",
+ /* Config passed by the user */
+ struct ctf_metadata_decoder_config decoder_config;
};
-static
-const char *print_loglevel(int64_t value)
-{
- if (value < 0) {
- return NULL;
- }
- if (value >= _NR_LOGLEVELS) {
- return "<<UNKNOWN>>";
- }
- return loglevel_str[value];
-}
+/*
+ * Visitor (public).
+ */
+struct ctf_visitor_generate_ir;
/**
* Creates a new declaration scope.
scope = g_new(struct ctx_decl_scope, 1);
if (!scope) {
+ BT_LOGE_STR("Failed to allocate one declaration scope.");
goto end;
}
scope->decl_map = g_hash_table_new_full(g_direct_hash, g_direct_equal,
- NULL, (GDestroyNotify) bt_ctf_field_type_put);
+ NULL, (GDestroyNotify) ctf_field_class_destroy);
scope->parent_scope = par_scope;
end:
{
GQuark qname = 0;
- assert(name);
+ BT_ASSERT(name);
/* Prefix character + original string + '\0' */
char *prname = g_new(char, strlen(name) + 2);
if (!prname) {
+ BT_LOGE_STR("Failed to allocate a string.");
goto end;
}
}
/**
- * Looks up a prefixed type alias within a declaration scope.
+ * Looks up a prefixed class alias within a declaration scope.
*
* @param scope Declaration scope
* @param prefix Prefix character
* @param name Alias name
- * @param level Number of levels to dig (-1 means infinite)
- * @returns Declaration, or NULL if not found
+ * @param levels Number of levels to dig into (-1 means infinite)
+ * @param copy True to return a copy
+ * @returns Declaration (owned by caller if \p copy is true),
+ * or NULL if not found
*/
static
-struct bt_ctf_field_type *ctx_decl_scope_lookup_prefix_alias(
- struct ctx_decl_scope *scope, char prefix,
- const char *name, int levels)
+struct ctf_field_class *ctx_decl_scope_lookup_prefix_alias(
+ struct ctx_decl_scope *scope, char prefix, const char *name,
+ int levels, bool copy)
{
GQuark qname = 0;
int cur_levels = 0;
- _BT_CTF_FIELD_TYPE_INIT(decl);
+ struct ctf_field_class *decl = NULL;
struct ctx_decl_scope *cur_scope = scope;
- assert(scope);
- assert(name);
+ BT_ASSERT(scope);
+ BT_ASSERT(name);
qname = get_prefixed_named_quark(prefix, name);
if (!qname) {
- goto error;
+ goto end;
}
if (levels < 0) {
while (cur_scope && cur_levels < levels) {
decl = g_hash_table_lookup(cur_scope->decl_map,
- (gconstpointer) (unsigned long) qname);
+ (gconstpointer) GUINT_TO_POINTER(qname));
if (decl) {
/* Caller's reference */
- bt_get(decl);
- break;
+ if (copy) {
+ decl = ctf_field_class_copy(decl);
+ BT_ASSERT(decl);
+ }
+
+ goto end;
}
cur_scope = cur_scope->parent_scope;
cur_levels++;
}
+end:
return decl;
-
-error:
- return NULL;
}
/**
- * Looks up a type alias within a declaration scope.
+ * Looks up a class alias within a declaration scope.
*
* @param scope Declaration scope
* @param name Alias name
- * @param level Number of levels to dig (-1 means infinite)
- * @returns Declaration, or NULL if not found
+ * @param levels Number of levels to dig into (-1 means infinite)
+ * @param copy True to return a copy
+ * @returns Declaration (owned by caller if \p copy is true),
+ * or NULL if not found
*/
static
-struct bt_ctf_field_type *ctx_decl_scope_lookup_alias(
- struct ctx_decl_scope *scope, const char *name, int levels)
+struct ctf_field_class *ctx_decl_scope_lookup_alias(
+ struct ctx_decl_scope *scope, const char *name, int levels,
+ bool copy)
{
return ctx_decl_scope_lookup_prefix_alias(scope, _PREFIX_ALIAS,
- name, levels);
+ name, levels, copy);
}
/**
*
* @param scope Declaration scope
* @param name Enumeration name
- * @param level Number of levels to dig (-1 means infinite)
- * @returns Declaration, or NULL if not found
+ * @param levels Number of levels to dig into (-1 means infinite)
+ * @param copy True to return a copy
+ * @returns Declaration (owned by caller if \p copy is true),
+ * or NULL if not found
*/
static
-struct bt_ctf_field_type *ctx_decl_scope_lookup_enum(
- struct ctx_decl_scope *scope, const char *name, int levels)
+struct ctf_field_class_enum *ctx_decl_scope_lookup_enum(
+ struct ctx_decl_scope *scope, const char *name, int levels,
+ bool copy)
{
- return ctx_decl_scope_lookup_prefix_alias(scope, _PREFIX_ENUM,
- name, levels);
+ return (void *) ctx_decl_scope_lookup_prefix_alias(scope, _PREFIX_ENUM,
+ name, levels, copy);
}
/**
*
* @param scope Declaration scope
* @param name Structure name
- * @param level Number of levels to dig (-1 means infinite)
- * @returns Declaration, or NULL if not found
+ * @param levels Number of levels to dig into (-1 means infinite)
+ * @param copy True to return a copy
+ * @returns Declaration (owned by caller if \p copy is true),
+ * or NULL if not found
*/
static
-struct bt_ctf_field_type *ctx_decl_scope_lookup_struct(
- struct ctx_decl_scope *scope, const char *name, int levels)
+struct ctf_field_class_struct *ctx_decl_scope_lookup_struct(
+ struct ctx_decl_scope *scope, const char *name, int levels,
+ bool copy)
{
- return ctx_decl_scope_lookup_prefix_alias(scope, _PREFIX_STRUCT,
- name, levels);
+ return (void *) ctx_decl_scope_lookup_prefix_alias(scope,
+ _PREFIX_STRUCT, name, levels, copy);
}
/**
*
* @param scope Declaration scope
* @param name Variant name
- * @param level Number of levels to dig (-1 means infinite)
- * @returns Declaration, or NULL if not found
+ * @param levels Number of levels to dig into (-1 means infinite)
+ * @param copy True to return a copy
+ * @returns Declaration (owned by caller if \p copy is true),
+ * or NULL if not found
*/
static
-struct bt_ctf_field_type *ctx_decl_scope_lookup_variant(
- struct ctx_decl_scope *scope, const char *name, int levels)
+struct ctf_field_class_variant *ctx_decl_scope_lookup_variant(
+ struct ctx_decl_scope *scope, const char *name, int levels,
+ bool copy)
{
- return ctx_decl_scope_lookup_prefix_alias(scope, _PREFIX_VARIANT,
- name, levels);
+ return (void *) ctx_decl_scope_lookup_prefix_alias(scope,
+ _PREFIX_VARIANT, name, levels, copy);
}
/**
- * Registers a prefixed type alias within a declaration scope.
+ * Registers a prefixed class alias within a declaration scope.
*
* @param scope Declaration scope
* @param prefix Prefix character
* @param name Alias name (non-NULL)
- * @param decl Declaration to register
+ * @param decl Field class to register (copied)
* @returns 0 if registration went okay, negative value otherwise
*/
static
int ctx_decl_scope_register_prefix_alias(struct ctx_decl_scope *scope,
- char prefix, const char *name, struct bt_ctf_field_type *decl)
+ char prefix, const char *name, struct ctf_field_class *decl)
{
int ret = 0;
GQuark qname = 0;
- _BT_CTF_FIELD_TYPE_INIT(edecl);
- assert(scope);
- assert(name);
- assert(decl);
+ BT_ASSERT(scope);
+ BT_ASSERT(name);
+ BT_ASSERT(decl);
qname = get_prefixed_named_quark(prefix, name);
if (!qname) {
ret = -ENOMEM;
- goto error;
+ goto end;
}
/* Make sure alias does not exist in local scope */
- edecl = ctx_decl_scope_lookup_prefix_alias(scope, prefix, name, 1);
- if (edecl) {
- BT_PUT(edecl);
+ if (ctx_decl_scope_lookup_prefix_alias(scope, prefix, name, 1,
+ false)) {
ret = -EEXIST;
- goto error;
+ goto end;
}
- g_hash_table_insert(scope->decl_map,
- (gpointer) (unsigned long) qname, decl);
-
- /* Hash table's reference */
- bt_get(decl);
-
- return 0;
+ decl = ctf_field_class_copy(decl);
+ BT_ASSERT(decl);
+ g_hash_table_insert(scope->decl_map, GUINT_TO_POINTER(qname), decl);
-error:
+end:
return ret;
}
/**
- * Registers a type alias within a declaration scope.
+ * Registers a class alias within a declaration scope.
*
* @param scope Declaration scope
* @param name Alias name (non-NULL)
- * @param decl Declaration to register
+ * @param decl Field class to register (copied)
* @returns 0 if registration went okay, negative value otherwise
*/
static
int ctx_decl_scope_register_alias(struct ctx_decl_scope *scope,
- const char *name, struct bt_ctf_field_type *decl)
+ const char *name, struct ctf_field_class *decl)
{
return ctx_decl_scope_register_prefix_alias(scope, _PREFIX_ALIAS,
- name, decl);
+ name, (void *) decl);
}
/**
*
* @param scope Declaration scope
* @param name Enumeration name (non-NULL)
- * @param decl Enumeration declaration to register
+ * @param decl Enumeration field class to register (copied)
* @returns 0 if registration went okay, negative value otherwise
*/
static
int ctx_decl_scope_register_enum(struct ctx_decl_scope *scope,
- const char *name, struct bt_ctf_field_type *decl)
+ const char *name, struct ctf_field_class_enum *decl)
{
return ctx_decl_scope_register_prefix_alias(scope, _PREFIX_ENUM,
- name, decl);
+ name, (void *) decl);
}
/**
*
* @param scope Declaration scope
* @param name Structure name (non-NULL)
- * @param decl Structure declaration to register
+ * @param decl Structure field class to register (copied)
* @returns 0 if registration went okay, negative value otherwise
*/
static
int ctx_decl_scope_register_struct(struct ctx_decl_scope *scope,
- const char *name, struct bt_ctf_field_type *decl)
+ const char *name, struct ctf_field_class_struct *decl)
{
return ctx_decl_scope_register_prefix_alias(scope, _PREFIX_STRUCT,
- name, decl);
+ name, (void *) decl);
}
/**
*
* @param scope Declaration scope
* @param name Variant name (non-NULL)
- * @param decl Variant declaration to register
+ * @param decl Variant field class to register
* @returns 0 if registration went okay, negative value otherwise
*/
static
int ctx_decl_scope_register_variant(struct ctx_decl_scope *scope,
- const char *name, struct bt_ctf_field_type *decl)
+ const char *name, struct ctf_field_class_variant *decl)
{
return ctx_decl_scope_register_prefix_alias(scope, _PREFIX_VARIANT,
- name, decl);
+ name, (void *) decl);
}
/**
- * Creates a new visitor context.
+ * Destroys a visitor context.
*
- * @param trace Associated trace
- * @param efd Error stream
- * @returns New visitor context, or NULL on error
+ * @param ctx Visitor context to destroy
*/
static
-struct ctx *ctx_create(struct bt_ctf_trace *trace, FILE *efd)
+void ctx_destroy(struct ctx *ctx)
{
- struct ctx *ctx = NULL;
- struct ctx_decl_scope *scope = NULL;
+ struct ctx_decl_scope *scope;
- ctx = g_new(struct ctx, 1);
if (!ctx) {
- goto error;
+ goto end;
}
- /* Root declaration scope */
- scope = ctx_decl_scope_create(NULL);
- if (!scope) {
- goto error;
- }
+ scope = ctx->current_scope;
- ctx->stream_classes = g_hash_table_new_full(g_direct_hash,
- g_direct_equal, NULL, (GDestroyNotify) bt_put);
- if (!ctx->stream_classes) {
- goto error;
+ /*
+ * Destroy all scopes, from current one to the root scope.
+ */
+ while (scope) {
+ struct ctx_decl_scope *parent_scope = scope->parent_scope;
+
+ ctx_decl_scope_destroy(scope);
+ scope = parent_scope;
}
- ctx->trace = trace;
- ctx->efd = efd;
- ctx->current_scope = scope;
- ctx->is_trace_visited = FALSE;
+ bt_trace_class_put_ref(ctx->trace_class);
- return ctx;
+ if (ctx->ctf_tc) {
+ ctf_trace_class_destroy(ctx->ctf_tc);
+ }
-error:
g_free(ctx);
- ctx_decl_scope_destroy(scope);
- return NULL;
+end:
+ return;
}
/**
- * Destroys a visitor context.
+ * Creates a new visitor context.
*
- * @param ctx Visitor context to destroy
+ * @param trace Associated trace
+ * @returns New visitor context, or NULL on error
*/
static
-void ctx_destroy(struct ctx *ctx)
+struct ctx *ctx_create(bt_self_component_source *self_comp,
+ const struct ctf_metadata_decoder_config *decoder_config)
{
- struct ctx_decl_scope *scope;
- /*
- * Destroy all scopes, from current one to the root scope.
- */
+ struct ctx *ctx = NULL;
+
+ BT_ASSERT(decoder_config);
+ ctx = g_new0(struct ctx, 1);
if (!ctx) {
- goto end;
+ BT_LOGE_STR("Failed to allocate one visitor context.");
+ goto error;
}
- scope = ctx->current_scope;
+ if (self_comp) {
+ ctx->trace_class = bt_trace_class_create(
+ bt_self_component_source_as_self_component(self_comp));
+ if (!ctx->trace_class) {
+ BT_LOGE_STR("Cannot create empty trace class.");
+ goto error;
+ }
+ }
- while (scope) {
- struct ctx_decl_scope *parent_scope = scope->parent_scope;
+ ctx->ctf_tc = ctf_trace_class_create();
+ if (!ctx->ctf_tc) {
+ BT_LOGE_STR("Cannot create CTF trace class.");
+ goto error;
+ }
- ctx_decl_scope_destroy(scope);
- scope = parent_scope;
+ /* Root declaration scope */
+ ctx->current_scope = ctx_decl_scope_create(NULL);
+ if (!ctx->current_scope) {
+ BT_LOGE_STR("Cannot create declaration scope.");
+ goto error;
}
- g_hash_table_destroy(ctx->stream_classes);
- g_free(ctx);
+ ctx->decoder_config = *decoder_config;
+ goto end;
+
+error:
+ ctx_destroy(ctx);
+ ctx = NULL;
end:
- return;
+ return ctx;
}
/**
int ret = 0;
struct ctx_decl_scope *new_scope;
- assert(ctx);
+ BT_ASSERT(ctx);
new_scope = ctx_decl_scope_create(ctx->current_scope);
if (!new_scope) {
+ BT_LOGE_STR("Cannot create declaration scope.");
ret = -ENOMEM;
goto end;
}
{
struct ctx_decl_scope *parent_scope = NULL;
- assert(ctx);
+ BT_ASSERT(ctx);
if (!ctx->current_scope) {
goto end;
}
static
-int visit_type_specifier_list(struct ctx *ctx, struct ctf_node *ts_list,
- struct bt_ctf_field_type **decl);
+int visit_field_class_specifier_list(struct ctx *ctx, struct ctf_node *ts_list,
+ struct ctf_field_class **decl);
+
+static
+char *remove_underscores_from_field_ref(const char *field_ref)
+{
+ const char *in_ch;
+ char *out_ch;
+ char *ret;
+ enum {
+ UNDERSCORE_REMOVE_STATE_REMOVE_NEXT_UNDERSCORE,
+ UNDERSCORE_REMOVE_STATE_DO_NOT_REMOVE_NEXT_UNDERSCORE,
+ } state = UNDERSCORE_REMOVE_STATE_REMOVE_NEXT_UNDERSCORE;
+
+ BT_ASSERT(field_ref);
+ ret = calloc(strlen(field_ref) + 1, 1);
+ if (!ret) {
+ BT_LOGE("Failed to allocate a string: size=%zu",
+ strlen(field_ref) + 1);
+ goto end;
+ }
+
+ in_ch = field_ref;
+ out_ch = ret;
+
+ while (*in_ch != '\0') {
+ switch (*in_ch) {
+ case ' ':
+ case '\t':
+ /* Remove whitespace */
+ in_ch++;
+ continue;
+ case '_':
+ if (state == UNDERSCORE_REMOVE_STATE_REMOVE_NEXT_UNDERSCORE) {
+ in_ch++;
+ state = UNDERSCORE_REMOVE_STATE_DO_NOT_REMOVE_NEXT_UNDERSCORE;
+ continue;
+ }
+
+ goto copy;
+ case '.':
+ state = UNDERSCORE_REMOVE_STATE_REMOVE_NEXT_UNDERSCORE;
+ goto copy;
+ default:
+ state = UNDERSCORE_REMOVE_STATE_DO_NOT_REMOVE_NEXT_UNDERSCORE;
+ goto copy;
+ }
+
+copy:
+ *out_ch = *in_ch;
+ in_ch++;
+ out_ch++;
+ }
+
+end:
+ return ret;
+}
static
int is_unary_string(struct bt_list_head *head)
struct ctf_node *node;
str = g_string_new(NULL);
+ BT_ASSERT(str);
bt_list_for_each_entry(node, head, siblings) {
char *src_string;
int ret = 0;
struct ctf_node *node;
+ *value = 0;
+
+ if (bt_list_empty(head)) {
+ ret = -1;
+ goto end;
+ }
+
bt_list_for_each_entry(node, head, siblings) {
int uexpr_type = node->u.unary_expression.type;
int uexpr_link = node->u.unary_expression.link;
uexpr_type != UNARY_UNSIGNED_CONSTANT ||
uexpr_link != UNARY_LINK_UNKNOWN || i != 0;
if (cond) {
+ _BT_LOGE_NODE(node, "Invalid constant unsigned integer.");
ret = -EINVAL;
goto end;
}
int uexpr_type = node->u.unary_expression.type;
int uexpr_link = node->u.unary_expression.link;
int cond = node->type != NODE_UNARY_EXPRESSION ||
- (uexpr_type != UNARY_UNSIGNED_CONSTANT) ||
(uexpr_type != UNARY_UNSIGNED_CONSTANT &&
uexpr_type != UNARY_SIGNED_CONSTANT) ||
uexpr_link != UNARY_LINK_UNKNOWN || i != 0;
goto end;
}
- switch (node->u.unary_expression.type) {
+ switch (uexpr_type) {
case UNARY_UNSIGNED_CONSTANT:
*value = (int64_t)
node->u.unary_expression.u.unsigned_constant;
src_string = node->u.unary_expression.u.string;
ret = bt_uuid_parse(src_string, uuid);
if (ret) {
+ _BT_LOGE_NODE(node,
+ "Cannot parse UUID: uuid=\"%s\"", src_string);
goto end;
}
}
}
static
-int get_boolean(FILE *efd, struct ctf_node *unary_expr)
+int get_boolean(struct ctf_node *unary_expr)
{
int ret = 0;
if (unary_expr->type != NODE_UNARY_EXPRESSION) {
- _FPERROR(efd, "%s", "expecting unary expression");
+ _BT_LOGE_NODE(unary_expr,
+ "Expecting unary expression: node-type=%d",
+ unary_expr->type);
ret = -EINVAL;
goto end;
}
} else if (!strcmp(str, "false") || !strcmp(str, "FALSE")) {
ret = FALSE;
} else {
- _FPERROR(efd, "unexpected string \"%s\"", str);
+ _BT_LOGE_NODE(unary_expr,
+ "Unexpected boolean value: value=\"%s\"", str);
ret = -EINVAL;
goto end;
}
break;
}
default:
- _FPERROR(efd, "%s", "unexpected unary expression type");
+ _BT_LOGE_NODE(unary_expr,
+ "Unexpected unary expression type: node-type=%d",
+ unary_expr->u.unary_expression.type);
ret = -EINVAL;
goto end;
}
}
static
-enum bt_ctf_byte_order byte_order_from_unary_expr(FILE *efd,
- struct ctf_node *unary_expr)
+enum ctf_byte_order byte_order_from_unary_expr(struct ctf_node *unary_expr)
{
const char *str;
- enum bt_ctf_byte_order bo = BT_CTF_BYTE_ORDER_UNKNOWN;
+ enum ctf_byte_order bo = -1;
if (unary_expr->u.unary_expression.type != UNARY_STRING) {
- _FPERROR(efd, "%s",
- "\"byte_order\" attribute: expecting string");
+ _BT_LOGE_NODE(unary_expr,
+ "\"byte_order\" attribute: expecting `be`, `le`, `network`, or `native`.");
goto end;
}
str = unary_expr->u.unary_expression.u.string;
if (!strcmp(str, "be") || !strcmp(str, "network")) {
- bo = BT_CTF_BYTE_ORDER_BIG_ENDIAN;
+ bo = CTF_BYTE_ORDER_BIG;
} else if (!strcmp(str, "le")) {
- bo = BT_CTF_BYTE_ORDER_LITTLE_ENDIAN;
+ bo = CTF_BYTE_ORDER_LITTLE;
} else if (!strcmp(str, "native")) {
- bo = BT_CTF_BYTE_ORDER_NATIVE;
+ bo = CTF_BYTE_ORDER_DEFAULT;
} else {
- _FPERROR(efd, "unexpected \"byte_order\" attribute value \"%s\"; should be \"be\", \"le\", \"network\", or \"native\"",
+ _BT_LOGE_NODE(unary_expr,
+ "Unexpected \"byte_order\" attribute value: "
+ "expecting `be`, `le`, `network`, or `native`: value=\"%s\"",
str);
goto end;
}
}
static
-enum bt_ctf_byte_order get_real_byte_order(struct ctx *ctx,
- struct ctf_node *uexpr)
+enum ctf_byte_order get_real_byte_order(struct ctx *ctx,
+ struct ctf_node *uexpr)
{
- enum bt_ctf_byte_order bo = byte_order_from_unary_expr(ctx->efd, uexpr);
+ enum ctf_byte_order bo = byte_order_from_unary_expr(uexpr);
- if (bo == BT_CTF_BYTE_ORDER_NATIVE) {
- bo = bt_ctf_trace_get_byte_order(ctx->trace);
+ if (bo == CTF_BYTE_ORDER_DEFAULT) {
+ bo = ctx->ctf_tc->default_byte_order;
}
return bo;
static
int is_align_valid(uint64_t align)
{
- return (align != 0) && !(align & (align - 1));
+ return (align != 0) && !(align & (align - UINT64_C(1)));
}
static
-int get_type_specifier_name(struct ctx *ctx, struct ctf_node *type_specifier,
- GString *str)
+int get_class_specifier_name(struct ctx *ctx, struct ctf_node *cls_specifier,
+ GString *str)
{
int ret = 0;
- if (type_specifier->type != NODE_TYPE_SPECIFIER) {
+ if (cls_specifier->type != NODE_TYPE_SPECIFIER) {
+ _BT_LOGE_NODE(cls_specifier,
+ "Unexpected node type: node-type=%d",
+ cls_specifier->type);
ret = -EINVAL;
goto end;
}
- switch (type_specifier->u.type_specifier.type) {
+ switch (cls_specifier->u.field_class_specifier.type) {
case TYPESPEC_VOID:
g_string_append(str, "void");
break;
g_string_append(str, "const");
break;
case TYPESPEC_ID_TYPE:
- if (type_specifier->u.type_specifier.id_type) {
+ if (cls_specifier->u.field_class_specifier.id_type) {
g_string_append(str,
- type_specifier->u.type_specifier.id_type);
+ cls_specifier->u.field_class_specifier.id_type);
}
break;
case TYPESPEC_STRUCT:
{
- struct ctf_node *node = type_specifier->u.type_specifier.node;
+ struct ctf_node *node = cls_specifier->u.field_class_specifier.node;
if (!node->u._struct.name) {
- _PERROR("%s", "unexpected empty structure name");
+ _BT_LOGE_NODE(node, "Unexpected empty structure field class name.");
ret = -EINVAL;
goto end;
}
}
case TYPESPEC_VARIANT:
{
- struct ctf_node *node = type_specifier->u.type_specifier.node;
+ struct ctf_node *node = cls_specifier->u.field_class_specifier.node;
if (!node->u.variant.name) {
- _PERROR("%s", "unexpected empty variant name");
+ _BT_LOGE_NODE(node, "Unexpected empty variant field class name.");
ret = -EINVAL;
goto end;
}
}
case TYPESPEC_ENUM:
{
- struct ctf_node *node = type_specifier->u.type_specifier.node;
+ struct ctf_node *node = cls_specifier->u.field_class_specifier.node;
if (!node->u._enum.enum_id) {
- _PERROR("%s", "unexpected empty enum name");
+ _BT_LOGE_NODE(node,
+ "Unexpected empty enumeration field class (`enum`) name.");
ret = -EINVAL;
goto end;
}
case TYPESPEC_INTEGER:
case TYPESPEC_STRING:
default:
- _PERROR("%s", "unknown specifier");
+ _BT_LOGE_NODE(cls_specifier->u.field_class_specifier.node,
+ "Unexpected field class specifier type: %d",
+ cls_specifier->u.field_class_specifier.type);
ret = -EINVAL;
goto end;
}
}
static
-int get_type_specifier_list_name(struct ctx *ctx,
- struct ctf_node *type_specifier_list, GString *str)
+int get_class_specifier_list_name(struct ctx *ctx,
+ struct ctf_node *cls_specifier_list, GString *str)
{
- int ret;
+ int ret = 0;
struct ctf_node *iter;
int alias_item_nr = 0;
struct bt_list_head *head =
- &type_specifier_list->u.type_specifier_list.head;
+ &cls_specifier_list->u.field_class_specifier_list.head;
bt_list_for_each_entry(iter, head, siblings) {
if (alias_item_nr != 0) {
}
alias_item_nr++;
- ret = get_type_specifier_name(ctx, iter, str);
+ ret = get_class_specifier_name(ctx, iter, str);
if (ret) {
goto end;
}
}
static
-GQuark create_typealias_identifier(struct ctx *ctx,
- struct ctf_node *type_specifier_list,
- struct ctf_node *node_type_declarator)
+GQuark create_class_alias_identifier(struct ctx *ctx,
+ struct ctf_node *cls_specifier_list,
+ struct ctf_node *node_field_class_declarator)
{
int ret;
char *str_c;
GQuark qalias = 0;
struct ctf_node *iter;
struct bt_list_head *pointers =
- &node_type_declarator->u.type_declarator.pointers;
+ &node_field_class_declarator->u.field_class_declarator.pointers;
str = g_string_new("");
- ret = get_type_specifier_list_name(ctx, type_specifier_list, str);
+ ret = get_class_specifier_list_name(ctx, cls_specifier_list, str);
if (ret) {
g_string_free(str, TRUE);
goto end;
}
static
-int visit_type_declarator(struct ctx *ctx, struct ctf_node *type_specifier_list,
- GQuark *field_name, struct ctf_node *node_type_declarator,
- struct bt_ctf_field_type **field_decl,
- struct bt_ctf_field_type *nested_decl)
+int visit_field_class_declarator(struct ctx *ctx,
+ struct ctf_node *cls_specifier_list,
+ GQuark *field_name, struct ctf_node *node_field_class_declarator,
+ struct ctf_field_class **field_decl,
+ struct ctf_field_class *nested_decl)
{
/*
* During this whole function, nested_decl is always OURS,
* whereas field_decl is an output which we create, but
* belongs to the caller (it is moved).
*/
-
int ret = 0;
*field_decl = NULL;
- /* Validate type declarator node */
- if (node_type_declarator) {
- if (node_type_declarator->u.type_declarator.type ==
+ /* Validate field class declarator node */
+ if (node_field_class_declarator) {
+ if (node_field_class_declarator->u.field_class_declarator.type ==
TYPEDEC_UNKNOWN) {
+ _BT_LOGE_NODE(node_field_class_declarator,
+ "Unexpected field class declarator type: type=%d",
+ node_field_class_declarator->u.field_class_declarator.type);
ret = -EINVAL;
goto error;
}
/* TODO: GCC bitfields not supported yet */
- if (node_type_declarator->u.type_declarator.bitfield_len !=
+ if (node_field_class_declarator->u.field_class_declarator.bitfield_len !=
NULL) {
- _PERROR("%s", "GCC bitfields are not supported as of this version");
+ _BT_LOGE_NODE(node_field_class_declarator,
+ "GCC bitfields are not supported as of this version.");
ret = -EPERM;
goto error;
}
/* Find the right nested declaration if not provided */
if (!nested_decl) {
struct bt_list_head *pointers =
- &node_type_declarator->u.type_declarator.pointers;
+ &node_field_class_declarator->u.field_class_declarator.pointers;
- if (node_type_declarator && !bt_list_empty(pointers)) {
+ if (node_field_class_declarator && !bt_list_empty(pointers)) {
GQuark qalias;
- _BT_CTF_FIELD_TYPE_INIT(nested_decl_copy);
/*
* If we have a pointer declarator, it HAS to
- * be present in the typealiases (else fail).
+ * be present in the field class aliases (else
+ * fail).
*/
- qalias = create_typealias_identifier(ctx,
- type_specifier_list, node_type_declarator);
+ qalias = create_class_alias_identifier(ctx,
+ cls_specifier_list, node_field_class_declarator);
nested_decl =
ctx_decl_scope_lookup_alias(ctx->current_scope,
- g_quark_to_string(qalias), -1);
+ g_quark_to_string(qalias), -1, true);
if (!nested_decl) {
- _PERROR("cannot find typealias \"%s\"",
+ _BT_LOGE_NODE(node_field_class_declarator,
+ "Cannot find class alias: name=\"%s\"",
g_quark_to_string(qalias));
ret = -EINVAL;
goto error;
}
- /* Make a copy of it */
- nested_decl_copy = bt_ctf_field_type_copy(nested_decl);
- BT_PUT(nested_decl);
- if (!nested_decl_copy) {
- _PERROR("%s", "cannot copy nested declaration");
- ret = -EINVAL;
- goto error;
- }
-
- BT_MOVE(nested_decl, nested_decl_copy);
+ if (nested_decl->type == CTF_FIELD_CLASS_TYPE_INT) {
+ /* Pointer: force integer's base to 16 */
+ struct ctf_field_class_int *int_fc =
+ (void *) nested_decl;
- /* Force integer's base to 16 since it's a pointer */
- if (bt_ctf_field_type_is_integer(nested_decl)) {
- bt_ctf_field_type_integer_set_base(nested_decl,
- BT_CTF_INTEGER_BASE_HEXADECIMAL);
+ int_fc->disp_base =
+ BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL;
}
} else {
- ret = visit_type_specifier_list(ctx,
- type_specifier_list, &nested_decl);
+ ret = visit_field_class_specifier_list(ctx,
+ cls_specifier_list, &nested_decl);
if (ret) {
- assert(!nested_decl);
+ BT_ASSERT(!nested_decl);
goto error;
}
}
}
- assert(nested_decl);
+ BT_ASSERT(nested_decl);
- if (!node_type_declarator) {
- BT_MOVE(*field_decl, nested_decl);
+ if (!node_field_class_declarator) {
+ *field_decl = nested_decl;
+ nested_decl = NULL;
goto end;
}
- if (node_type_declarator->u.type_declarator.type == TYPEDEC_ID) {
- if (node_type_declarator->u.type_declarator.u.id) {
+ if (node_field_class_declarator->u.field_class_declarator.type == TYPEDEC_ID) {
+ if (node_field_class_declarator->u.field_class_declarator.u.id) {
const char *id =
- node_type_declarator->u.type_declarator.u.id;
+ node_field_class_declarator->u.field_class_declarator.u.id;
+
+ if (id[0] == '_') {
+ id++;
+ }
*field_name = g_quark_from_string(id);
} else {
*field_name = 0;
}
- BT_MOVE(*field_decl, nested_decl);
+ *field_decl = nested_decl;
+ nested_decl = NULL;
goto end;
} else {
struct ctf_node *first;
- _BT_CTF_FIELD_TYPE_INIT(decl);
- _BT_CTF_FIELD_TYPE_INIT(outer_field_decl);
+ struct ctf_field_class *decl = NULL;
+ struct ctf_field_class *outer_field_decl = NULL;
struct bt_list_head *length =
- &node_type_declarator->
- u.type_declarator.u.nested.length;
+ &node_field_class_declarator->
+ u.field_class_declarator.u.nested.length;
/* Create array/sequence, pass nested_decl as child */
if (bt_list_empty(length)) {
- _PERROR("%s",
- "expecting length field reference or value");
+ _BT_LOGE_NODE(node_field_class_declarator,
+ "Expecting length field reference or value.");
ret = -EINVAL;
goto error;
}
first = _BT_LIST_FIRST_ENTRY(length, struct ctf_node, siblings);
if (first->type != NODE_UNARY_EXPRESSION) {
+ _BT_LOGE_NODE(first,
+ "Unexpected node type: node-type=%d",
+ first->type);
ret = -EINVAL;
goto error;
}
switch (first->u.unary_expression.type) {
case UNARY_UNSIGNED_CONSTANT:
{
- size_t len;
- _BT_CTF_FIELD_TYPE_INIT(array_decl);
-
- len = first->u.unary_expression.u.unsigned_constant;
- array_decl = bt_ctf_field_type_array_create(nested_decl,
- len);
- BT_PUT(nested_decl);
- if (!array_decl) {
- _PERROR("%s",
- "cannot create array declaration");
- ret = -ENOMEM;
- goto error;
- }
-
- BT_MOVE(decl, array_decl);
+ struct ctf_field_class_array *array_decl = NULL;
+
+ array_decl = ctf_field_class_array_create();
+ BT_ASSERT(array_decl);
+ array_decl->length =
+ first->u.unary_expression.u.unsigned_constant;
+ array_decl->base.elem_fc = nested_decl;
+ nested_decl = NULL;
+ decl = (void *) array_decl;
break;
}
case UNARY_STRING:
{
/* Lookup unsigned integer definition, create seq. */
- _BT_CTF_FIELD_TYPE_INIT(seq_decl);
+ struct ctf_field_class_sequence *seq_decl = NULL;
char *length_name = concatenate_unary_strings(length);
if (!length_name) {
+ _BT_LOGE_NODE(node_field_class_declarator,
+ "Cannot concatenate unary strings.");
ret = -EINVAL;
goto error;
}
- seq_decl = bt_ctf_field_type_sequence_create(
- nested_decl, length_name);
- g_free(length_name);
- BT_PUT(nested_decl);
- if (!seq_decl) {
- _PERROR("%s",
- "cannot create sequence declaration");
- ret = -ENOMEM;
- goto error;
+ if (strncmp(length_name, "env.", 4) == 0) {
+ /* This is, in fact, an array */
+ const char *env_entry_name = &length_name[4];
+ struct ctf_trace_class_env_entry *env_entry =
+ ctf_trace_class_borrow_env_entry_by_name(
+ ctx->ctf_tc, env_entry_name);
+ struct ctf_field_class_array *array_decl;
+
+ if (!env_entry) {
+ _BT_LOGE_NODE(node_field_class_declarator,
+ "Cannot find environment entry: "
+ "name=\"%s\"", env_entry_name);
+ ret = -EINVAL;
+ goto error;
+ }
+
+ if (env_entry->type != CTF_TRACE_CLASS_ENV_ENTRY_TYPE_INT) {
+ _BT_LOGE_NODE(node_field_class_declarator,
+ "Wrong environment entry type "
+ "(expecting integer): "
+ "name=\"%s\"", env_entry_name);
+ ret = -EINVAL;
+ goto error;
+ }
+
+ if (env_entry->value.i < 0) {
+ _BT_LOGE_NODE(node_field_class_declarator,
+ "Invalid, negative array length: "
+ "env-entry-name=\"%s\", "
+ "value=%" PRId64,
+ env_entry_name,
+ env_entry->value.i);
+ ret = -EINVAL;
+ goto error;
+ }
+
+ array_decl = ctf_field_class_array_create();
+ BT_ASSERT(array_decl);
+ array_decl->length =
+ (uint64_t) env_entry->value.i;
+ array_decl->base.elem_fc = nested_decl;
+ nested_decl = NULL;
+ decl = (void *) array_decl;
+ } else {
+ char *length_name_no_underscore =
+ remove_underscores_from_field_ref(
+ length_name);
+ if (!length_name_no_underscore) {
+ /*
+ * remove_underscores_from_field_ref()
+ * logs errors
+ */
+ ret = -EINVAL;
+ goto error;
+ }
+ seq_decl = ctf_field_class_sequence_create();
+ BT_ASSERT(seq_decl);
+ seq_decl->base.elem_fc = nested_decl;
+ nested_decl = NULL;
+ g_string_assign(seq_decl->length_ref,
+ length_name_no_underscore);
+ free(length_name_no_underscore);
+ decl = (void *) seq_decl;
}
- BT_MOVE(decl, seq_decl);
+ g_free(length_name);
break;
}
default:
goto error;
}
- assert(!nested_decl);
- assert(decl);
- assert(!*field_decl);
+ BT_ASSERT(!nested_decl);
+ BT_ASSERT(decl);
+ BT_ASSERT(!*field_decl);
/*
* At this point, we found the next nested declaration.
* nested declaration as the content of the outer
* container, MOVING its ownership.
*/
- ret = visit_type_declarator(ctx, type_specifier_list,
+ ret = visit_field_class_declarator(ctx, cls_specifier_list,
field_name,
- node_type_declarator->
- u.type_declarator.u.nested.type_declarator,
+ node_field_class_declarator->
+ u.field_class_declarator.u.nested.field_class_declarator,
&outer_field_decl, decl);
decl = NULL;
if (ret) {
- assert(!outer_field_decl);
+ BT_ASSERT(!outer_field_decl);
ret = -EINVAL;
goto error;
}
- assert(outer_field_decl);
- BT_MOVE(*field_decl, outer_field_decl);
+ BT_ASSERT(outer_field_decl);
+ *field_decl = outer_field_decl;
+ outer_field_decl = NULL;
}
-end:
- BT_PUT(nested_decl);
- assert(*field_decl);
-
- return 0;
+ BT_ASSERT(*field_decl);
+ goto end;
error:
- BT_PUT(nested_decl);
- BT_PUT(*field_decl);
+ ctf_field_class_destroy(*field_decl);
+ *field_decl = NULL;
+
+ if (ret >= 0) {
+ ret = -1;
+ }
+end:
+ ctf_field_class_destroy(nested_decl);
+ nested_decl = NULL;
return ret;
}
static
int visit_struct_decl_field(struct ctx *ctx,
- struct bt_ctf_field_type *struct_decl,
- struct ctf_node *type_specifier_list,
- struct bt_list_head *type_declarators)
+ struct ctf_field_class_struct *struct_decl,
+ struct ctf_node *cls_specifier_list,
+ struct bt_list_head *field_class_declarators)
{
int ret = 0;
struct ctf_node *iter;
- _BT_CTF_FIELD_TYPE_INIT(field_decl);
+ struct ctf_field_class *field_decl = NULL;
- bt_list_for_each_entry(iter, type_declarators, siblings) {
+ bt_list_for_each_entry(iter, field_class_declarators, siblings) {
field_decl = NULL;
GQuark qfield_name;
const char *field_name;
- _BT_CTF_FIELD_TYPE_INIT(efield_decl);
- ret = visit_type_declarator(ctx, type_specifier_list,
+ ret = visit_field_class_declarator(ctx, cls_specifier_list,
&qfield_name, iter, &field_decl, NULL);
if (ret) {
- assert(!field_decl);
- _PERROR("%s", "unable to find structure field declaration type");
+ BT_ASSERT(!field_decl);
+ _BT_LOGE_NODE(cls_specifier_list,
+ "Cannot visit field class declarator: ret=%d", ret);
goto error;
}
- assert(field_decl);
+ BT_ASSERT(field_decl);
field_name = g_quark_to_string(qfield_name);
/* Check if field with same name already exists */
- efield_decl =
- bt_ctf_field_type_structure_get_field_type_by_name(
- struct_decl, field_name);
- if (efield_decl) {
- BT_PUT(efield_decl);
- _PERROR("duplicate field \"%s\" in structure",
- field_name);
+ if (ctf_field_class_struct_borrow_member_by_name(
+ struct_decl, field_name)) {
+ _BT_LOGE_NODE(cls_specifier_list,
+ "Duplicate field in structure field class: "
+ "field-name=\"%s\"", field_name);
ret = -EINVAL;
goto error;
}
/* Add field to structure */
- ret = bt_ctf_field_type_structure_add_field(struct_decl,
- field_decl, field_name);
- BT_PUT(field_decl);
- if (ret) {
- _PERROR("cannot add field \"%s\" to structure",
- g_quark_to_string(qfield_name));
- goto error;
- }
+ ctf_field_class_struct_append_member(struct_decl,
+ field_name, field_decl);
+ field_decl = NULL;
}
return 0;
error:
- BT_PUT(field_decl);
-
+ ctf_field_class_destroy(field_decl);
+ field_decl = NULL;
return ret;
}
static
int visit_variant_decl_field(struct ctx *ctx,
- struct bt_ctf_field_type *variant_decl,
- struct ctf_node *type_specifier_list,
- struct bt_list_head *type_declarators)
+ struct ctf_field_class_variant *variant_decl,
+ struct ctf_node *cls_specifier_list,
+ struct bt_list_head *field_class_declarators)
{
int ret = 0;
struct ctf_node *iter;
- _BT_CTF_FIELD_TYPE_INIT(field_decl);
+ struct ctf_field_class *field_decl = NULL;
- bt_list_for_each_entry(iter, type_declarators, siblings) {
+ bt_list_for_each_entry(iter, field_class_declarators, siblings) {
field_decl = NULL;
GQuark qfield_name;
const char *field_name;
- _BT_CTF_FIELD_TYPE_INIT(efield_decl);
- ret = visit_type_declarator(ctx, type_specifier_list,
+ ret = visit_field_class_declarator(ctx, cls_specifier_list,
&qfield_name, iter, &field_decl, NULL);
if (ret) {
- assert(!field_decl);
- _PERROR("%s",
- "unable to find variant field declaration type");
+ BT_ASSERT(!field_decl);
+ _BT_LOGE_NODE(cls_specifier_list,
+ "Cannot visit field class declarator: ret=%d", ret);
goto error;
}
- assert(field_decl);
+ BT_ASSERT(field_decl);
field_name = g_quark_to_string(qfield_name);
/* Check if field with same name already exists */
- efield_decl =
- bt_ctf_field_type_variant_get_field_type_by_name(
- variant_decl, field_name);
- if (efield_decl) {
- BT_PUT(efield_decl);
- _PERROR("duplicate field \"%s\" in variant",
- field_name);
+ if (ctf_field_class_variant_borrow_option_by_name(
+ variant_decl, field_name)) {
+ _BT_LOGE_NODE(cls_specifier_list,
+ "Duplicate field in variant field class: "
+ "field-name=\"%s\"", field_name);
ret = -EINVAL;
goto error;
}
/* Add field to structure */
- ret = bt_ctf_field_type_variant_add_field(variant_decl,
- field_decl, field_name);
- BT_PUT(field_decl);
- if (ret) {
- _PERROR("cannot add field \"%s\" to variant",
- g_quark_to_string(qfield_name));
- goto error;
- }
+ ctf_field_class_variant_append_option(variant_decl,
+ field_name, field_decl);
+ field_decl = NULL;
}
return 0;
error:
- BT_PUT(field_decl);
-
+ ctf_field_class_destroy(field_decl);
+ field_decl = NULL;
return ret;
}
static
-int visit_typedef(struct ctx *ctx, struct ctf_node *type_specifier_list,
- struct bt_list_head *type_declarators)
+int visit_field_class_def(struct ctx *ctx, struct ctf_node *cls_specifier_list,
+ struct bt_list_head *field_class_declarators)
{
int ret = 0;
GQuark qidentifier;
struct ctf_node *iter;
- _BT_CTF_FIELD_TYPE_INIT(type_decl);
+ struct ctf_field_class *class_decl = NULL;
- bt_list_for_each_entry(iter, type_declarators, siblings) {
- ret = visit_type_declarator(ctx, type_specifier_list,
- &qidentifier, iter, &type_decl, NULL);
+ bt_list_for_each_entry(iter, field_class_declarators, siblings) {
+ ret = visit_field_class_declarator(ctx, cls_specifier_list,
+ &qidentifier, iter, &class_decl, NULL);
if (ret) {
- _PERROR("%s", "problem creating type declaration");
+ _BT_LOGE_NODE(iter,
+ "Cannot visit field class declarator: ret=%d", ret);
ret = -EINVAL;
goto end;
}
- /* Do not allow typedef and typealias of untagged variants */
- if (bt_ctf_field_type_is_variant(type_decl)) {
- if (bt_ctf_field_type_variant_get_tag_name(type_decl)) {
- _PERROR("%s", "typedef of untagged variant is not allowed");
+ /* Do not allow field class def and alias of untagged variants */
+ if (class_decl->type == CTF_FIELD_CLASS_TYPE_VARIANT) {
+ struct ctf_field_class_variant *var_fc =
+ (void *) class_decl;
+
+ if (var_fc->tag_path.path->len == 0) {
+ _BT_LOGE_NODE(iter,
+ "Type definition of untagged variant field class is not allowed.");
ret = -EPERM;
goto end;
}
}
ret = ctx_decl_scope_register_alias(ctx->current_scope,
- g_quark_to_string(qidentifier), type_decl);
+ g_quark_to_string(qidentifier), class_decl);
if (ret) {
- _PERROR("cannot register typedef \"%s\"",
+ _BT_LOGE_NODE(iter,
+ "Cannot register field class alias: name=\"%s\"",
g_quark_to_string(qidentifier));
goto end;
}
}
end:
- BT_PUT(type_decl);
-
+ ctf_field_class_destroy(class_decl);
+ class_decl = NULL;
return ret;
}
static
-int visit_typealias(struct ctx *ctx, struct ctf_node *target,
- struct ctf_node *alias)
+int visit_field_class_alias(struct ctx *ctx, struct ctf_node *target,
+ struct ctf_node *alias)
{
int ret = 0;
GQuark qalias;
struct ctf_node *node;
GQuark qdummy_field_name;
- _BT_CTF_FIELD_TYPE_INIT(type_decl);
+ struct ctf_field_class *class_decl = NULL;
- /* Create target type declaration */
- if (bt_list_empty(&target->u.typealias_target.type_declarators)) {
+ /* Create target field class */
+ if (bt_list_empty(&target->u.field_class_alias_target.field_class_declarators)) {
node = NULL;
} else {
node = _BT_LIST_FIRST_ENTRY(
- &target->u.typealias_target.type_declarators,
+ &target->u.field_class_alias_target.field_class_declarators,
struct ctf_node, siblings);
}
- ret = visit_type_declarator(ctx,
- target->u.typealias_target.type_specifier_list,
- &qdummy_field_name, node, &type_decl, NULL);
+ ret = visit_field_class_declarator(ctx,
+ target->u.field_class_alias_target.field_class_specifier_list,
+ &qdummy_field_name, node, &class_decl, NULL);
if (ret) {
- assert(!type_decl);
- _PERROR("%s", "problem creating type declaration");
+ BT_ASSERT(!class_decl);
+ _BT_LOGE_NODE(node,
+ "Cannot visit field class declarator: ret=%d", ret);
goto end;
}
- /* Do not allow typedef and typealias of untagged variants */
- if (bt_ctf_field_type_is_variant(type_decl)) {
- if (bt_ctf_field_type_variant_get_tag_name(type_decl)) {
- _PERROR("%s",
- "typealias of untagged variant is not allowed");
+ /* Do not allow field class def and alias of untagged variants */
+ if (class_decl->type == CTF_FIELD_CLASS_TYPE_VARIANT) {
+ struct ctf_field_class_variant *var_fc = (void *) class_decl;
+
+ if (var_fc->tag_path.path->len == 0) {
+ _BT_LOGE_NODE(target,
+ "Type definition of untagged variant field class is not allowed.");
ret = -EPERM;
goto end;
}
* abstract or not (if it has an identifier). Check it here.
*/
if (qdummy_field_name != 0) {
- _PERROR("%s", "expecting empty identifier");
+ _BT_LOGE_NODE(target,
+ "Expecting empty identifier: id=\"%s\"",
+ g_quark_to_string(qdummy_field_name));
ret = -EINVAL;
goto end;
}
/* Create alias identifier */
- node = _BT_LIST_FIRST_ENTRY(&alias->u.typealias_alias.type_declarators,
+ node = _BT_LIST_FIRST_ENTRY(&alias->u.field_class_alias_name.field_class_declarators,
struct ctf_node, siblings);
- qalias = create_typealias_identifier(ctx,
- alias->u.typealias_alias.type_specifier_list, node);
+ qalias = create_class_alias_identifier(ctx,
+ alias->u.field_class_alias_name.field_class_specifier_list, node);
ret = ctx_decl_scope_register_alias(ctx->current_scope,
- g_quark_to_string(qalias), type_decl);
+ g_quark_to_string(qalias), class_decl);
if (ret) {
- _PERROR("cannot register typealias \"%s\"",
+ _BT_LOGE_NODE(node,
+ "Cannot register class alias: name=\"%s\"",
g_quark_to_string(qalias));
goto end;
}
end:
- BT_PUT(type_decl);
-
+ ctf_field_class_destroy(class_decl);
+ class_decl = NULL;
return ret;
}
static
int visit_struct_decl_entry(struct ctx *ctx, struct ctf_node *entry_node,
- struct bt_ctf_field_type *struct_decl)
+ struct ctf_field_class_struct *struct_decl)
{
int ret = 0;
switch (entry_node->type) {
case NODE_TYPEDEF:
- ret = visit_typedef(ctx,
- entry_node->u._typedef.type_specifier_list,
- &entry_node->u._typedef.type_declarators);
+ ret = visit_field_class_def(ctx,
+ entry_node->u.field_class_def.field_class_specifier_list,
+ &entry_node->u.field_class_def.field_class_declarators);
if (ret) {
- _PERROR("%s",
- "cannot add typedef in \"struct\" declaration");
+ _BT_LOGE_NODE(entry_node,
+ "Cannot add field class found in structure field class: ret=%d",
+ ret);
goto end;
}
break;
case NODE_TYPEALIAS:
- ret = visit_typealias(ctx, entry_node->u.typealias.target,
- entry_node->u.typealias.alias);
+ ret = visit_field_class_alias(ctx, entry_node->u.field_class_alias.target,
+ entry_node->u.field_class_alias.alias);
if (ret) {
- _PERROR("%s",
- "cannot add typealias in \"struct\" declaration");
+ _BT_LOGE_NODE(entry_node,
+ "Cannot add field class alias found in structure field class: ret=%d",
+ ret);
goto end;
}
break;
/* Field */
ret = visit_struct_decl_field(ctx, struct_decl,
entry_node->u.struct_or_variant_declaration.
- type_specifier_list,
+ field_class_specifier_list,
&entry_node->u.struct_or_variant_declaration.
- type_declarators);
+ field_class_declarators);
if (ret) {
goto end;
}
break;
default:
- _PERROR("unexpected node type: %d", (int) entry_node->type);
+ _BT_LOGE_NODE(entry_node,
+ "Unexpected node type: node-type=%d", entry_node->type);
ret = -EINVAL;
goto end;
}
static
int visit_variant_decl_entry(struct ctx *ctx, struct ctf_node *entry_node,
- struct bt_ctf_field_type *variant_decl)
+ struct ctf_field_class_variant *variant_decl)
{
int ret = 0;
switch (entry_node->type) {
case NODE_TYPEDEF:
- ret = visit_typedef(ctx,
- entry_node->u._typedef.type_specifier_list,
- &entry_node->u._typedef.type_declarators);
+ ret = visit_field_class_def(ctx,
+ entry_node->u.field_class_def.field_class_specifier_list,
+ &entry_node->u.field_class_def.field_class_declarators);
if (ret) {
- _PERROR("%s",
- "cannot add typedef in \"variant\" declaration");
+ _BT_LOGE_NODE(entry_node,
+ "Cannot add field class found in variant field class: ret=%d",
+ ret);
goto end;
}
break;
case NODE_TYPEALIAS:
- ret = visit_typealias(ctx, entry_node->u.typealias.target,
- entry_node->u.typealias.alias);
+ ret = visit_field_class_alias(ctx, entry_node->u.field_class_alias.target,
+ entry_node->u.field_class_alias.alias);
if (ret) {
- _PERROR("%s",
- "cannot add typealias in \"variant\" declaration");
+ _BT_LOGE_NODE(entry_node,
+ "Cannot add field class alias found in variant field class: ret=%d",
+ ret);
goto end;
}
break;
/* Field */
ret = visit_variant_decl_field(ctx, variant_decl,
entry_node->u.struct_or_variant_declaration.
- type_specifier_list,
+ field_class_specifier_list,
&entry_node->u.struct_or_variant_declaration.
- type_declarators);
+ field_class_declarators);
if (ret) {
goto end;
}
break;
default:
- _PERROR("unexpected node type: %d", (int) entry_node->type);
+ _BT_LOGE_NODE(entry_node,
+ "Unexpected node type: node-type=%d",
+ entry_node->type);
ret = -EINVAL;
goto end;
}
static
int visit_struct_decl(struct ctx *ctx, const char *name,
- struct bt_list_head *decl_list, int has_body,
- struct bt_list_head *min_align,
- struct bt_ctf_field_type **struct_decl)
+ struct bt_list_head *decl_list, int has_body,
+ struct bt_list_head *min_align,
+ struct ctf_field_class_struct **struct_decl)
{
int ret = 0;
+ BT_ASSERT(struct_decl);
*struct_decl = NULL;
/* For named struct (without body), lookup in declaration scope */
if (!has_body) {
- _BT_CTF_FIELD_TYPE_INIT(struct_decl_copy);
-
if (!name) {
+ BT_LOGE_STR("Bodyless structure field class: missing name.");
ret = -EPERM;
goto error;
}
*struct_decl = ctx_decl_scope_lookup_struct(ctx->current_scope,
- name, -1);
+ name, -1, true);
if (!*struct_decl) {
- _PERROR("cannot find \"struct %s\"", name);
- ret = -EINVAL;
- goto error;
- }
-
- /* Make a copy of it */
- struct_decl_copy = bt_ctf_field_type_copy(*struct_decl);
- if (!struct_decl_copy) {
- _PERROR("%s",
- "cannot create copy of structure declaration");
+ BT_LOGE("Cannot find structure field class: name=\"struct %s\"",
+ name);
ret = -EINVAL;
goto error;
}
-
- BT_MOVE(*struct_decl, struct_decl_copy);
} else {
struct ctf_node *entry_node;
uint64_t min_align_value = 0;
if (name) {
- _BT_CTF_FIELD_TYPE_INIT(estruct_decl);
-
- estruct_decl = ctx_decl_scope_lookup_struct(
- ctx->current_scope, name, 1);
- if (estruct_decl) {
- BT_PUT(estruct_decl);
- _PERROR("\"struct %s\" already declared in local scope",
- name);
+ if (ctx_decl_scope_lookup_struct(
+ ctx->current_scope, name, 1, false)) {
+ BT_LOGE("Structure field class already declared in local scope: "
+ "name=\"struct %s\"", name);
ret = -EINVAL;
goto error;
}
if (!bt_list_empty(min_align)) {
ret = get_unary_unsigned(min_align, &min_align_value);
if (ret) {
- _PERROR("%s", "unexpected unary expression for structure declaration's \"align\" attribute");
+ BT_LOGE("Unexpected unary expression for structure field class's `align` attribute: "
+ "ret=%d", ret);
goto error;
}
}
- *struct_decl = bt_ctf_field_type_structure_create();
- if (!*struct_decl) {
- _PERROR("%s", "cannot create structure declaration");
- ret = -ENOMEM;
- goto error;
- }
+ *struct_decl = ctf_field_class_struct_create();
+ BT_ASSERT(*struct_decl);
if (min_align_value != 0) {
- ret = bt_ctf_field_type_set_alignment(*struct_decl,
- min_align_value);
- if (ret) {
- _PERROR("%s", "failed to set structure's minimal alignment");
- goto error;
- }
+ (*struct_decl)->base.alignment = min_align_value;
}
- ret = ctx_push_scope(ctx);
- if (ret) {
- _PERROR("%s", "cannot push scope");
- goto error;
- }
+ _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
bt_list_for_each_entry(entry_node, decl_list, siblings) {
ret = visit_struct_decl_entry(ctx, entry_node,
*struct_decl);
if (ret) {
+ _BT_LOGE_NODE(entry_node,
+ "Cannot visit structure field class entry: "
+ "ret=%d", ret);
ctx_pop_scope(ctx);
goto error;
}
ret = ctx_decl_scope_register_struct(ctx->current_scope,
name, *struct_decl);
if (ret) {
- _PERROR("cannot register \"struct %s\" in declaration scope",
- name);
+ BT_LOGE("Cannot register structure field class in declaration scope: "
+ "name=\"struct %s\", ret=%d", name, ret);
goto error;
}
}
return 0;
error:
- BT_PUT(*struct_decl);
-
+ ctf_field_class_destroy((void *) *struct_decl);
+ *struct_decl = NULL;
return ret;
}
static
int visit_variant_decl(struct ctx *ctx, const char *name,
const char *tag, struct bt_list_head *decl_list,
- int has_body, struct bt_ctf_field_type **variant_decl)
+ int has_body, struct ctf_field_class_variant **variant_decl)
{
int ret = 0;
- _BT_CTF_FIELD_TYPE_INIT(untagged_variant_decl);
+ struct ctf_field_class_variant *untagged_variant_decl = NULL;
+ BT_ASSERT(variant_decl);
*variant_decl = NULL;
/* For named variant (without body), lookup in declaration scope */
if (!has_body) {
- _BT_CTF_FIELD_TYPE_INIT(variant_decl_copy);
-
if (!name) {
+ BT_LOGE_STR("Bodyless variant field class: missing name.");
ret = -EPERM;
goto error;
}
untagged_variant_decl =
ctx_decl_scope_lookup_variant(ctx->current_scope,
- name, -1);
+ name, -1, true);
if (!untagged_variant_decl) {
- _PERROR("cannot find \"variant %s\"", name);
- ret = -EINVAL;
- goto error;
- }
-
- /* Make a copy of it */
- variant_decl_copy = bt_ctf_field_type_copy(
- untagged_variant_decl);
- if (!variant_decl_copy) {
- _PERROR("%s",
- "cannot create copy of structure declaration");
+ BT_LOGE("Cannot find variant field class: name=\"variant %s\"",
+ name);
ret = -EINVAL;
goto error;
}
-
- BT_MOVE(untagged_variant_decl, variant_decl_copy);
} else {
struct ctf_node *entry_node;
if (name) {
- struct bt_ctf_field_type *evariant_decl =
- ctx_decl_scope_lookup_struct(ctx->current_scope,
- name, 1);
-
- if (evariant_decl) {
- BT_PUT(evariant_decl);
- _PERROR("\"variant %s\" already declared in local scope",
- name);
+ if (ctx_decl_scope_lookup_variant(ctx->current_scope,
+ name, 1, false)) {
+ BT_LOGE("Variant field class already declared in local scope: "
+ "name=\"variant %s\"", name);
ret = -EINVAL;
goto error;
}
}
- untagged_variant_decl = bt_ctf_field_type_variant_create(NULL,
- NULL);
- if (!untagged_variant_decl) {
- _PERROR("%s", "cannot create variant declaration");
- ret = -ENOMEM;
- goto error;
- }
-
- ret = ctx_push_scope(ctx);
- if (ret) {
- _PERROR("%s", "cannot push scope");
- goto error;
- }
+ untagged_variant_decl = ctf_field_class_variant_create();
+ BT_ASSERT(untagged_variant_decl);
+ _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
bt_list_for_each_entry(entry_node, decl_list, siblings) {
ret = visit_variant_decl_entry(ctx, entry_node,
untagged_variant_decl);
if (ret) {
+ _BT_LOGE_NODE(entry_node,
+ "Cannot visit variant field class entry: "
+ "ret=%d", ret);
ctx_pop_scope(ctx);
goto error;
}
ctx->current_scope, name,
untagged_variant_decl);
if (ret) {
- _PERROR("cannot register \"variant %s\" in declaration scope",
- name);
+ BT_LOGE("Cannot register variant field class in declaration scope: "
+ "name=\"variant %s\", ret=%d", name, ret);
goto error;
}
}
* return untagged variant.
*/
if (!tag) {
- BT_MOVE(*variant_decl, untagged_variant_decl);
+ *variant_decl = untagged_variant_decl;
+ untagged_variant_decl = NULL;
} else {
/*
* At this point, we have a fresh untagged variant; nobody
* else owns it. Set its tag now.
*/
- ret = bt_ctf_field_type_variant_set_tag_name(
- untagged_variant_decl, tag);
- if (ret) {
+ char *tag_no_underscore =
+ remove_underscores_from_field_ref(tag);
+
+ if (!tag_no_underscore) {
+ /* remove_underscores_from_field_ref() logs errors */
goto error;
}
- BT_MOVE(*variant_decl, untagged_variant_decl);
+ g_string_assign(untagged_variant_decl->tag_ref,
+ tag_no_underscore);
+ free(tag_no_underscore);
+ *variant_decl = untagged_variant_decl;
+ untagged_variant_decl = NULL;
}
- assert(!untagged_variant_decl);
- assert(*variant_decl);
-
+ BT_ASSERT(!untagged_variant_decl);
+ BT_ASSERT(*variant_decl);
return 0;
error:
- BT_PUT(untagged_variant_decl);
- BT_PUT(*variant_decl);
-
+ ctf_field_class_destroy((void *) untagged_variant_decl);
+ untagged_variant_decl = NULL;
+ ctf_field_class_destroy((void *) *variant_decl);
+ *variant_decl = NULL;
return ret;
}
+struct uori {
+ bool is_signed;
+ union {
+ uint64_t u;
+ uint64_t i;
+ } value;
+};
+
static
int visit_enum_decl_entry(struct ctx *ctx, struct ctf_node *enumerator,
- struct bt_ctf_field_type *enum_decl, int64_t *last, int is_signed)
+ struct ctf_field_class_enum *enum_decl, struct uori *last)
{
int ret = 0;
int nr_vals = 0;
struct ctf_node *iter;
- int64_t start = 0, end = 0;
+ struct uori start = {
+ .is_signed = false,
+ .value.u = 0,
+ };
+ struct uori end = {
+ .is_signed = false,
+ .value.u = 0,
+ };
const char *label = enumerator->u.enumerator.id;
+ const char *effective_label = label;
struct bt_list_head *values = &enumerator->u.enumerator.values;
bt_list_for_each_entry(iter, values, siblings) {
- int64_t *target;
+ struct uori *target;
if (iter->type != NODE_UNARY_EXPRESSION) {
- _PERROR("wrong unary expression for enumeration label \"%s\"",
+ _BT_LOGE_NODE(iter,
+ "Wrong expression for enumeration field class label: "
+ "node-type=%d, label=\"%s\"", iter->type,
label);
ret = -EINVAL;
goto error;
switch (iter->u.unary_expression.type) {
case UNARY_SIGNED_CONSTANT:
- *target = iter->u.unary_expression.u.signed_constant;
+ target->is_signed = true;
+ target->value.i =
+ iter->u.unary_expression.u.signed_constant;
break;
case UNARY_UNSIGNED_CONSTANT:
- *target = (int64_t)
+ target->is_signed = false;
+ target->value.u =
iter->u.unary_expression.u.unsigned_constant;
break;
default:
- _PERROR("invalid enumeration entry: \"%s\"",
- label);
+ _BT_LOGE_NODE(iter,
+ "Invalid enumeration field class entry: "
+ "expecting constant signed or unsigned integer: "
+ "node-type=%d, label=\"%s\"",
+ iter->u.unary_expression.type, label);
ret = -EINVAL;
goto error;
}
if (nr_vals > 1) {
- _PERROR("invalid enumeration entry: \"%s\"",
+ _BT_LOGE_NODE(iter,
+ "Invalid enumeration field class entry: label=\"%s\"",
label);
ret = -EINVAL;
goto error;
end = start;
}
- *last = end + 1;
-
- if (is_signed) {
- ret = bt_ctf_field_type_enumeration_add_mapping(enum_decl, label,
- start, end);
+ if (end.is_signed) {
+ last->value.i = end.value.i + 1;
} else {
- ret = bt_ctf_field_type_enumeration_add_mapping_unsigned(enum_decl,
- label, (uint64_t) start, (uint64_t) end);
+ last->value.u = end.value.u + 1;
}
- if (ret) {
- _PERROR("cannot add mapping to enumeration for label \"%s\"",
- label);
- goto error;
+
+ if (label[0] == '_') {
+ /*
+ * Strip the first underscore of any enumeration field
+ * class's label in case this enumeration FC is used as
+ * a variant FC tag later. The variant FC choice names
+ * could also start with `_`, in which case the prefix
+ * is removed, and it the resulting choice name needs to
+ * match tag labels.
+ */
+ effective_label = &label[1];
}
+ ctf_field_class_enum_append_mapping(enum_decl, effective_label,
+ start.value.u, end.value.u);
return 0;
error:
static
int visit_enum_decl(struct ctx *ctx, const char *name,
- struct ctf_node *container_type,
- struct bt_list_head *enumerator_list,
- int has_body,
- struct bt_ctf_field_type **enum_decl)
+ struct ctf_node *container_cls,
+ struct bt_list_head *enumerator_list,
+ int has_body, struct ctf_field_class_enum **enum_decl)
{
int ret = 0;
GQuark qdummy_id;
- _BT_CTF_FIELD_TYPE_INIT(integer_decl);
+ struct ctf_field_class_int *integer_decl = NULL;
+ BT_ASSERT(enum_decl);
*enum_decl = NULL;
/* For named enum (without body), lookup in declaration scope */
if (!has_body) {
- _BT_CTF_FIELD_TYPE_INIT(enum_decl_copy);
-
if (!name) {
+ BT_LOGE_STR("Bodyless enumeration field class: missing name.");
ret = -EPERM;
goto error;
}
*enum_decl = ctx_decl_scope_lookup_enum(ctx->current_scope,
- name, -1);
+ name, -1, true);
if (!*enum_decl) {
- _PERROR("cannot find \"enum %s\"", name);
- ret = -EINVAL;
- goto error;
- }
-
- /* Make a copy of it */
- enum_decl_copy = bt_ctf_field_type_copy(*enum_decl);
- if (!enum_decl_copy) {
- _PERROR("%s",
- "cannot create copy of enumeration declaration");
+ BT_LOGE("Cannot find enumeration field class: "
+ "name=\"enum %s\"", name);
ret = -EINVAL;
goto error;
}
-
- BT_PUT(*enum_decl);
- BT_MOVE(*enum_decl, enum_decl_copy);
} else {
struct ctf_node *iter;
- int64_t last_value = 0;
+ struct uori last_value = {
+ .is_signed = false,
+ .value.u = 0,
+ };
if (name) {
- _BT_CTF_FIELD_TYPE_INIT(eenum_decl);
-
- eenum_decl = ctx_decl_scope_lookup_enum(
- ctx->current_scope, name, 1);
- if (eenum_decl) {
- BT_PUT(eenum_decl);
- _PERROR("\"enum %s\" already declared in local scope",
- name);
+ if (ctx_decl_scope_lookup_enum(ctx->current_scope,
+ name, 1, false)) {
+ BT_LOGE("Enumeration field class already declared in local scope: "
+ "name=\"enum %s\"", name);
ret = -EINVAL;
goto error;
}
}
- if (!container_type) {
- integer_decl = ctx_decl_scope_lookup_alias(
- ctx->current_scope, "int", -1);
+ if (!container_cls) {
+ integer_decl = (void *) ctx_decl_scope_lookup_alias(
+ ctx->current_scope, "int", -1, true);
if (!integer_decl) {
- _PERROR("%s", "cannot find \"int\" type for enumeration");
+ BT_LOGE_STR("Cannot find implicit `int` field class alias for enumeration field class.");
ret = -EINVAL;
goto error;
}
} else {
- ret = visit_type_declarator(ctx, container_type,
- &qdummy_id, NULL, &integer_decl, NULL);
+ ret = visit_field_class_declarator(ctx, container_cls,
+ &qdummy_id, NULL, (void *) &integer_decl,
+ NULL);
if (ret) {
- assert(!integer_decl);
+ BT_ASSERT(!integer_decl);
ret = -EINVAL;
goto error;
}
}
- assert(integer_decl);
+ BT_ASSERT(integer_decl);
- if (!bt_ctf_field_type_is_integer(integer_decl)) {
- _PERROR("%s", "container type for enumeration is not an integer");
+ if (integer_decl->base.base.type != CTF_FIELD_CLASS_TYPE_INT) {
+ BT_LOGE("Container field class for enumeration field class is not an integer field class: "
+ "fc-type=%d", integer_decl->base.base.type);
ret = -EINVAL;
goto error;
}
- *enum_decl = bt_ctf_field_type_enumeration_create(integer_decl);
- if (!*enum_decl) {
- _PERROR("%s", "cannot create enumeration declaration");
- ret = -ENOMEM;
- goto error;
- }
+ *enum_decl = ctf_field_class_enum_create();
+ BT_ASSERT(*enum_decl);
+ (*enum_decl)->base.base.base.alignment =
+ integer_decl->base.base.alignment;
+ ctf_field_class_int_copy_content((void *) *enum_decl,
+ (void *) integer_decl);
+ last_value.is_signed = (*enum_decl)->base.is_signed;
bt_list_for_each_entry(iter, enumerator_list, siblings) {
ret = visit_enum_decl_entry(ctx, iter, *enum_decl,
- &last_value,
- bt_ctf_field_type_integer_get_signed(integer_decl));
+ &last_value);
if (ret) {
+ _BT_LOGE_NODE(iter,
+ "Cannot visit enumeration field class entry: "
+ "ret=%d", ret);
goto error;
}
}
ret = ctx_decl_scope_register_enum(ctx->current_scope,
name, *enum_decl);
if (ret) {
+ BT_LOGE("Cannot register enumeration field class in declaration scope: "
+ "ret=%d", ret);
goto error;
}
}
}
- BT_PUT(integer_decl);
-
- return 0;
+ goto end;
error:
- BT_PUT(integer_decl);
- BT_PUT(*enum_decl);
+ ctf_field_class_destroy((void *) *enum_decl);
+ *enum_decl = NULL;
+end:
+ ctf_field_class_destroy((void *) integer_decl);
+ integer_decl = NULL;
return ret;
}
static
-int visit_type_specifier(struct ctx *ctx,
- struct ctf_node *type_specifier_list,
- struct bt_ctf_field_type **decl)
+int visit_field_class_specifier(struct ctx *ctx,
+ struct ctf_node *cls_specifier_list,
+ struct ctf_field_class **decl)
{
int ret = 0;
GString *str = NULL;
- _BT_CTF_FIELD_TYPE_INIT(decl_copy);
*decl = NULL;
str = g_string_new("");
- ret = get_type_specifier_list_name(ctx, type_specifier_list, str);
+ ret = get_class_specifier_list_name(ctx, cls_specifier_list, str);
if (ret) {
+ _BT_LOGE_NODE(cls_specifier_list,
+ "Cannot get field class specifier list's name: ret=%d", ret);
goto error;
}
- *decl = ctx_decl_scope_lookup_alias(ctx->current_scope, str->str, -1);
+ *decl = ctx_decl_scope_lookup_alias(ctx->current_scope, str->str, -1,
+ true);
if (!*decl) {
- _PERROR("cannot find type alias \"%s\"", str->str);
- ret = -EINVAL;
- goto error;
- }
-
- /* Make a copy of the type declaration */
- decl_copy = bt_ctf_field_type_copy(*decl);
- if (!decl_copy) {
- _PERROR("%s", "cannot create copy of type declaration");
+ _BT_LOGE_NODE(cls_specifier_list,
+ "Cannot find field class alias: name=\"%s\"", str->str);
ret = -EINVAL;
goto error;
}
- BT_MOVE(*decl, decl_copy);
- (void) g_string_free(str, TRUE);
- str = NULL;
-
- return 0;
+ goto end;
error:
+ ctf_field_class_destroy(*decl);
+ *decl = NULL;
+
+end:
if (str) {
- (void) g_string_free(str, TRUE);
+ g_string_free(str, TRUE);
}
- BT_PUT(*decl);
-
return ret;
}
static
int visit_integer_decl(struct ctx *ctx,
- struct bt_list_head *expressions,
- struct bt_ctf_field_type **integer_decl)
+ struct bt_list_head *expressions,
+ struct ctf_field_class_int **integer_decl)
{
int set = 0;
int ret = 0;
int signedness = 0;
struct ctf_node *expression;
uint64_t alignment = 0, size = 0;
- struct bt_ctf_clock_class *mapped_clock = NULL;
- enum bt_ctf_string_encoding encoding = BT_CTF_STRING_ENCODING_NONE;
- enum bt_ctf_integer_base base = BT_CTF_INTEGER_BASE_DECIMAL;
- enum bt_ctf_byte_order byte_order =
- bt_ctf_trace_get_byte_order(ctx->trace);
+ struct ctf_clock_class *mapped_clock_class = NULL;
+ enum ctf_encoding encoding = CTF_ENCODING_NONE;
+ bt_field_class_integer_preferred_display_base base =
+ BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL;
+ enum ctf_byte_order byte_order = ctx->ctf_tc->default_byte_order;
*integer_decl = NULL;
siblings);
if (left->u.unary_expression.type != UNARY_STRING) {
+ _BT_LOGE_NODE(left,
+ "Unexpected unary expression type: type=%d",
+ left->u.unary_expression.type);
ret = -EINVAL;
goto error;
}
if (!strcmp(left->u.unary_expression.u.string, "signed")) {
if (_IS_SET(&set, _INTEGER_SIGNED_SET)) {
- _PERROR_DUP_ATTR("signed",
- "integer declaration");
+ _BT_LOGE_DUP_ATTR(left, "signed",
+ "integer field class");
ret = -EPERM;
goto error;
}
- signedness = get_boolean(ctx->efd, right);
+ signedness = get_boolean(right);
if (signedness < 0) {
+ _BT_LOGE_NODE(right,
+ "Invalid boolean value for integer field class's `signed` attribute: "
+ "ret=%d", ret);
ret = -EINVAL;
goto error;
}
} else if (!strcmp(left->u.unary_expression.u.string,
"byte_order")) {
if (_IS_SET(&set, _INTEGER_BYTE_ORDER_SET)) {
- _PERROR_DUP_ATTR("byte_order",
- "integer declaration");
+ _BT_LOGE_DUP_ATTR(left, "byte_order",
+ "integer field class");
ret = -EPERM;
goto error;
}
byte_order = get_real_byte_order(ctx, right);
- if (byte_order == BT_CTF_BYTE_ORDER_UNKNOWN) {
- _PERROR("%s", "invalid \"byte_order\" attribute in integer declaration");
+ if (byte_order == -1) {
+ _BT_LOGE_NODE(right,
+ "Invalid `byte_order` attribute in integer field class: "
+ "ret=%d", ret);
ret = -EINVAL;
goto error;
}
_SET(&set, _INTEGER_BYTE_ORDER_SET);
} else if (!strcmp(left->u.unary_expression.u.string, "size")) {
if (_IS_SET(&set, _INTEGER_SIZE_SET)) {
- _PERROR_DUP_ATTR("size",
- "integer declaration");
+ _BT_LOGE_DUP_ATTR(left, "size",
+ "integer field class");
ret = -EPERM;
goto error;
}
if (right->u.unary_expression.type !=
UNARY_UNSIGNED_CONSTANT) {
- _PERROR("%s", "invalid \"size\" attribute in integer declaration: expecting unsigned constant");
+ _BT_LOGE_NODE(right,
+ "Invalid `size` attribute in integer field class: "
+ "expecting unsigned constant integer: "
+ "node-type=%d",
+ right->u.unary_expression.type);
ret = -EINVAL;
goto error;
}
size = right->u.unary_expression.u.unsigned_constant;
if (size == 0) {
- _PERROR("%s", "invalid \"size\" attribute in integer declaration: expecting positive constant");
+ _BT_LOGE_NODE(right,
+ "Invalid `size` attribute in integer field class: "
+ "expecting positive constant integer: "
+ "size=%" PRIu64, size);
ret = -EINVAL;
goto error;
} else if (size > 64) {
- _PERROR("%s", "invalid \"size\" attribute in integer declaration: integers over 64-bit are not supported as of this version");
+ _BT_LOGE_NODE(right,
+ "Invalid `size` attribute in integer field class: "
+ "integer fields over 64 bits are not supported as of this version: "
+ "size=%" PRIu64, size);
ret = -EINVAL;
goto error;
}
} else if (!strcmp(left->u.unary_expression.u.string,
"align")) {
if (_IS_SET(&set, _INTEGER_ALIGN_SET)) {
- _PERROR_DUP_ATTR("align",
- "integer declaration");
+ _BT_LOGE_DUP_ATTR(left, "align",
+ "integer field class");
ret = -EPERM;
goto error;
}
if (right->u.unary_expression.type !=
UNARY_UNSIGNED_CONSTANT) {
- _PERROR("%s", "invalid \"align\" attribute in integer declaration: expecting unsigned constant");
+ _BT_LOGE_NODE(right,
+ "Invalid `align` attribute in integer field class: "
+ "expecting unsigned constant integer: "
+ "node-type=%d",
+ right->u.unary_expression.type);
ret = -EINVAL;
goto error;
}
alignment =
right->u.unary_expression.u.unsigned_constant;
if (!is_align_valid(alignment)) {
- _PERROR("%s", "invalid \"align\" attribute in integer declaration: expecting power of two");
+ _BT_LOGE_NODE(right,
+ "Invalid `align` attribute in integer field class: "
+ "expecting power of two: "
+ "align=%" PRIu64, alignment);
ret = -EINVAL;
goto error;
}
_SET(&set, _INTEGER_ALIGN_SET);
} else if (!strcmp(left->u.unary_expression.u.string, "base")) {
if (_IS_SET(&set, _INTEGER_BASE_SET)) {
- _PERROR_DUP_ATTR("base", "integer declaration");
+ _BT_LOGE_DUP_ATTR(left, "base",
+ "integer field class");
ret = -EPERM;
goto error;
}
switch (constant) {
case 2:
- base = BT_CTF_INTEGER_BASE_BINARY;
+ base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY;
break;
case 8:
- base = BT_CTF_INTEGER_BASE_OCTAL;
+ base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL;
break;
case 10:
- base = BT_CTF_INTEGER_BASE_DECIMAL;
+ base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL;
break;
case 16:
- base = BT_CTF_INTEGER_BASE_HEXADECIMAL;
+ base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL;
break;
default:
- _PERROR("invalid \"base\" attribute in integer declaration: %" PRIu64,
+ _BT_LOGE_NODE(right,
+ "Invalid `base` attribute in integer field class: "
+ "base=%" PRIu64,
right->u.unary_expression.u.unsigned_constant);
ret = -EINVAL;
goto error;
char *s_right = concatenate_unary_strings(
&expression->u.ctf_expression.right);
if (!s_right) {
- _PERROR("%s", "unexpected unary expression for integer declaration's \"base\" attribute");
+ _BT_LOGE_NODE(right,
+ "Unexpected unary expression for integer field class's `base` attribute.");
ret = -EINVAL;
goto error;
}
!strcmp(s_right, "d") ||
!strcmp(s_right, "i") ||
!strcmp(s_right, "u")) {
- base = BT_CTF_INTEGER_BASE_DECIMAL;
+ base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL;
} else if (!strcmp(s_right, "hexadecimal") ||
!strcmp(s_right, "hex") ||
!strcmp(s_right, "x") ||
!strcmp(s_right, "X") ||
!strcmp(s_right, "p")) {
- base = BT_CTF_INTEGER_BASE_HEXADECIMAL;
+ base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL;
} else if (!strcmp(s_right, "octal") ||
!strcmp(s_right, "oct") ||
!strcmp(s_right, "o")) {
- base = BT_CTF_INTEGER_BASE_OCTAL;
+ base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL;
} else if (!strcmp(s_right, "binary") ||
!strcmp(s_right, "b")) {
- base = BT_CTF_INTEGER_BASE_BINARY;
+ base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY;
} else {
- _PERROR("unexpected unary expression for integer declaration's \"base\" attribute: \"%s\"",
- s_right);
+ _BT_LOGE_NODE(right,
+ "Unexpected unary expression for integer field class's `base` attribute: "
+ "base=\"%s\"", s_right);
g_free(s_right);
ret = -EINVAL;
goto error;
break;
}
default:
- _PERROR("%s", "invalid \"base\" attribute in integer declaration: expecting unsigned constant or unary string");
+ _BT_LOGE_NODE(right,
+ "Invalid `base` attribute in integer field class: "
+ "expecting unsigned constant integer or unary string.");
ret = -EINVAL;
goto error;
}
char *s_right;
if (_IS_SET(&set, _INTEGER_ENCODING_SET)) {
- _PERROR_DUP_ATTR("encoding",
- "integer declaration");
+ _BT_LOGE_DUP_ATTR(left, "encoding",
+ "integer field class");
ret = -EPERM;
goto error;
}
if (right->u.unary_expression.type != UNARY_STRING) {
- _PERROR("%s", "invalid \"encoding\" attribute in integer declaration: expecting unary string");
+ _BT_LOGE_NODE(right,
+ "Invalid `encoding` attribute in integer field class: "
+ "expecting unary string.");
ret = -EINVAL;
goto error;
}
s_right = concatenate_unary_strings(
&expression->u.ctf_expression.right);
if (!s_right) {
- _PERROR("%s", "unexpected unary expression for integer declaration's \"encoding\" attribute");
+ _BT_LOGE_NODE(right,
+ "Unexpected unary expression for integer field class's `encoding` attribute.");
ret = -EINVAL;
goto error;
}
if (!strcmp(s_right, "UTF8") ||
!strcmp(s_right, "utf8") ||
!strcmp(s_right, "utf-8") ||
- !strcmp(s_right, "UTF-8")) {
- encoding = BT_CTF_STRING_ENCODING_UTF8;
- } else if (!strcmp(s_right, "ASCII") ||
+ !strcmp(s_right, "UTF-8") ||
+ !strcmp(s_right, "ASCII") ||
!strcmp(s_right, "ascii")) {
- encoding = BT_CTF_STRING_ENCODING_ASCII;
+ encoding = CTF_ENCODING_UTF8;
} else if (!strcmp(s_right, "none")) {
- encoding = BT_CTF_STRING_ENCODING_NONE;
+ encoding = CTF_ENCODING_NONE;
} else {
- _PERROR("invalid \"encoding\" attribute in integer declaration: unknown encoding \"%s\"",
+ _BT_LOGE_NODE(right,
+ "Invalid `encoding` attribute in integer field class: "
+ "unknown encoding: encoding=\"%s\"",
s_right);
g_free(s_right);
ret = -EINVAL;
const char *clock_name;
if (_IS_SET(&set, _INTEGER_MAP_SET)) {
- _PERROR_DUP_ATTR("map", "integer declaration");
+ _BT_LOGE_DUP_ATTR(left, "map",
+ "integer field class");
ret = -EPERM;
goto error;
}
if (right->u.unary_expression.type != UNARY_STRING) {
- _PERROR("%s", "invalid \"map\" attribute in integer declaration: expecting unary string");
+ _BT_LOGE_NODE(right,
+ "Invalid `map` attribute in integer field class: "
+ "expecting unary string.");
ret = -EINVAL;
goto error;
}
&expression->u.ctf_expression.right);
if (!s_right) {
- _PERROR("%s", "unexpected unary expression for integer declaration's \"map\" attribute");
+ _BT_LOGE_NODE(right,
+ "Unexpected unary expression for integer field class's `map` attribute.");
ret = -EINVAL;
goto error;
}
- _PWARNING("invalid \"map\" attribute in integer declaration: unknown clock: \"%s\"",
+ _BT_LOGE_NODE(right,
+ "Invalid `map` attribute in integer field class: "
+ "cannot find clock class at this point: name=\"%s\"",
s_right);
_SET(&set, _INTEGER_MAP_SET);
g_free(s_right);
continue;
}
- mapped_clock = bt_ctf_trace_get_clock_class_by_name(
- ctx->trace, clock_name);
- if (!mapped_clock) {
- _PERROR("invalid \"map\" attribute in integer declaration: cannot find clock \"%s\"",
+ mapped_clock_class =
+ ctf_trace_class_borrow_clock_class_by_name(
+ ctx->ctf_tc, clock_name);
+ if (!mapped_clock_class) {
+ _BT_LOGE_NODE(right,
+ "Invalid `map` attribute in integer field class: "
+ "cannot find clock class at this point: name=\"%s\"",
clock_name);
ret = -EINVAL;
goto error;
_SET(&set, _INTEGER_MAP_SET);
} else {
- _PWARNING("unknown attribute \"%s\" in integer declaration",
+ _BT_LOGW_NODE(left,
+ "Unknown attribute in integer field class: "
+ "attr-name=\"%s\"",
left->u.unary_expression.u.string);
}
}
if (!_IS_SET(&set, _INTEGER_SIZE_SET)) {
- _PERROR("%s",
- "missing \"size\" attribute in integer declaration");
+ BT_LOGE_STR("Missing `size` attribute in integer field class.");
ret = -EPERM;
goto error;
}
}
}
- *integer_decl = bt_ctf_field_type_integer_create((unsigned int) size);
- if (!*integer_decl) {
- _PERROR("%s", "cannot create integer declaration");
- ret = -ENOMEM;
- goto error;
- }
+ *integer_decl = ctf_field_class_int_create();
+ BT_ASSERT(*integer_decl);
+ (*integer_decl)->base.base.alignment = alignment;
+ (*integer_decl)->base.byte_order = byte_order;
+ (*integer_decl)->base.size = size;
+ (*integer_decl)->is_signed = (signedness > 0);
+ (*integer_decl)->disp_base = base;
+ (*integer_decl)->encoding = encoding;
+ (*integer_decl)->mapped_clock_class = mapped_clock_class;
+ return 0;
- ret = bt_ctf_field_type_integer_set_signed(*integer_decl, signedness);
- ret |= bt_ctf_field_type_integer_set_base(*integer_decl, base);
- ret |= bt_ctf_field_type_integer_set_encoding(*integer_decl, encoding);
- ret |= bt_ctf_field_type_set_alignment(*integer_decl,
- (unsigned int) alignment);
- ret |= bt_ctf_field_type_set_byte_order(*integer_decl, byte_order);
-
- if (mapped_clock) {
- /* Move clock */
- ret |= bt_ctf_field_type_integer_set_mapped_clock_class(
- *integer_decl, mapped_clock);
- bt_put(mapped_clock);
- mapped_clock = NULL;
- }
-
- if (ret) {
- _PERROR("%s", "cannot configure integer declaration");
- ret = -EINVAL;
- goto error;
- }
-
- return 0;
-
-error:
- if (mapped_clock) {
- bt_put(mapped_clock);
- }
-
- BT_PUT(*integer_decl);
-
- return ret;
-}
+error:
+ ctf_field_class_destroy((void *) *integer_decl);
+ *integer_decl = NULL;
+ return ret;
+}
static
int visit_floating_point_number_decl(struct ctx *ctx,
- struct bt_list_head *expressions,
- struct bt_ctf_field_type **float_decl)
+ struct bt_list_head *expressions,
+ struct ctf_field_class_float **float_decl)
{
int set = 0;
int ret = 0;
struct ctf_node *expression;
uint64_t alignment = 1, exp_dig = 0, mant_dig = 0;
- enum bt_ctf_byte_order byte_order =
- bt_ctf_trace_get_byte_order(ctx->trace);
+ enum ctf_byte_order byte_order = ctx->ctf_tc->default_byte_order;
*float_decl = NULL;
siblings);
if (left->u.unary_expression.type != UNARY_STRING) {
+ _BT_LOGE_NODE(left,
+ "Unexpected unary expression type: type=%d",
+ left->u.unary_expression.type);
ret = -EINVAL;
goto error;
}
if (!strcmp(left->u.unary_expression.u.string, "byte_order")) {
if (_IS_SET(&set, _FLOAT_BYTE_ORDER_SET)) {
- _PERROR_DUP_ATTR("byte_order",
- "floating point number declaration");
+ _BT_LOGE_DUP_ATTR(left, "byte_order",
+ "floating point number field class");
ret = -EPERM;
goto error;
}
byte_order = get_real_byte_order(ctx, right);
- if (byte_order == BT_CTF_BYTE_ORDER_UNKNOWN) {
- _PERROR("%s", "invalid \"byte_order\" attribute in floating point number declaration");
+ if (byte_order == -1) {
+ _BT_LOGE_NODE(right,
+ "Invalid `byte_order` attribute in floating point number field class: "
+ "ret=%d", ret);
ret = -EINVAL;
goto error;
}
} else if (!strcmp(left->u.unary_expression.u.string,
"exp_dig")) {
if (_IS_SET(&set, _FLOAT_EXP_DIG_SET)) {
- _PERROR_DUP_ATTR("exp_dig",
- "floating point number declaration");
+ _BT_LOGE_DUP_ATTR(left, "exp_dig",
+ "floating point number field class");
ret = -EPERM;
goto error;
}
if (right->u.unary_expression.type !=
UNARY_UNSIGNED_CONSTANT) {
- _PERROR("%s", "invalid \"exp_dig\" attribute in floating point number declaration: expecting unsigned constant");
+ _BT_LOGE_NODE(right,
+ "Invalid `exp_dig` attribute in floating point number field class: "
+ "expecting unsigned constant integer: "
+ "node-type=%d",
+ right->u.unary_expression.type);
ret = -EINVAL;
goto error;
}
} else if (!strcmp(left->u.unary_expression.u.string,
"mant_dig")) {
if (_IS_SET(&set, _FLOAT_MANT_DIG_SET)) {
- _PERROR_DUP_ATTR("mant_dig",
- "floating point number declaration");
+ _BT_LOGE_DUP_ATTR(left, "mant_dig",
+ "floating point number field class");
ret = -EPERM;
goto error;
}
if (right->u.unary_expression.type !=
UNARY_UNSIGNED_CONSTANT) {
- _PERROR("%s", "invalid \"mant_dig\" attribute in floating point number declaration: expecting unsigned constant");
+ _BT_LOGE_NODE(right,
+ "Invalid `mant_dig` attribute in floating point number field class: "
+ "expecting unsigned constant integer: "
+ "node-type=%d",
+ right->u.unary_expression.type);
ret = -EINVAL;
goto error;
}
} else if (!strcmp(left->u.unary_expression.u.string,
"align")) {
if (_IS_SET(&set, _FLOAT_ALIGN_SET)) {
- _PERROR_DUP_ATTR("align",
- "floating point number declaration");
+ _BT_LOGE_DUP_ATTR(left, "align",
+ "floating point number field class");
ret = -EPERM;
goto error;
}
if (right->u.unary_expression.type !=
UNARY_UNSIGNED_CONSTANT) {
- _PERROR("%s", "invalid \"align\" attribute in floating point number declaration: expecting unsigned constant");
+ _BT_LOGE_NODE(right,
+ "Invalid `align` attribute in floating point number field class: "
+ "expecting unsigned constant integer: "
+ "node-type=%d",
+ right->u.unary_expression.type);
ret = -EINVAL;
goto error;
}
unsigned_constant;
if (!is_align_valid(alignment)) {
- _PERROR("%s", "invalid \"align\" attribute in floating point number declaration: expecting power of two");
+ _BT_LOGE_NODE(right,
+ "Invalid `align` attribute in floating point number field class: "
+ "expecting power of two: "
+ "align=%" PRIu64, alignment);
ret = -EINVAL;
goto error;
}
_SET(&set, _FLOAT_ALIGN_SET);
} else {
- _PWARNING("unknown attribute \"%s\" in floating point number declaration",
+ _BT_LOGW_NODE(left,
+ "Unknown attribute in floating point number field class: "
+ "attr-name=\"%s\"",
left->u.unary_expression.u.string);
}
}
if (!_IS_SET(&set, _FLOAT_MANT_DIG_SET)) {
- _PERROR("%s", "missing \"mant_dig\" attribute in floating point number declaration");
+ BT_LOGE_STR("Missing `mant_dig` attribute in floating point number field class.");
ret = -EPERM;
goto error;
}
if (!_IS_SET(&set, _FLOAT_EXP_DIG_SET)) {
- _PERROR("%s", "missing \"exp_dig\" attribute in floating point number declaration");
+ BT_LOGE_STR("Missing `exp_dig` attribute in floating point number field class.");
+ ret = -EPERM;
+ goto error;
+ }
+
+ if (mant_dig != 24 && mant_dig != 53) {
+ BT_LOGE_STR("`mant_dig` attribute: expecting 24 or 53.");
+ ret = -EPERM;
+ goto error;
+ }
+
+ if (mant_dig == 24 && exp_dig != 8) {
+ BT_LOGE_STR("`exp_dig` attribute: expecting 8 because `mant_dig` is 24.");
+ ret = -EPERM;
+ goto error;
+ }
+
+ if (mant_dig == 53 && exp_dig != 11) {
+ BT_LOGE_STR("`exp_dig` attribute: expecting 11 because `mant_dig` is 53.");
ret = -EPERM;
goto error;
}
}
}
- *float_decl = bt_ctf_field_type_floating_point_create();
- if (!*float_decl) {
- _PERROR("%s",
- "cannot create floating point number declaration");
- ret = -ENOMEM;
- goto error;
- }
-
- ret = bt_ctf_field_type_floating_point_set_exponent_digits(
- *float_decl, exp_dig);
- ret |= bt_ctf_field_type_floating_point_set_mantissa_digits(
- *float_decl, mant_dig);
- ret |= bt_ctf_field_type_set_byte_order(*float_decl, byte_order);
- ret |= bt_ctf_field_type_set_alignment(*float_decl, alignment);
- if (ret) {
- _PERROR("%s",
- "cannot configure floating point number declaration");
- ret = -EINVAL;
- goto error;
- }
-
+ *float_decl = ctf_field_class_float_create();
+ BT_ASSERT(*float_decl);
+ (*float_decl)->base.base.alignment = alignment;
+ (*float_decl)->base.byte_order = byte_order;
+ (*float_decl)->base.size = mant_dig + exp_dig;
return 0;
error:
- BT_PUT(*float_decl);
-
+ ctf_field_class_destroy((void *) *float_decl);
+ *float_decl = NULL;
return ret;
}
static
int visit_string_decl(struct ctx *ctx,
- struct bt_list_head *expressions,
- struct bt_ctf_field_type **string_decl)
+ struct bt_list_head *expressions,
+ struct ctf_field_class_string **string_decl)
{
int set = 0;
int ret = 0;
struct ctf_node *expression;
- enum bt_ctf_string_encoding encoding = BT_CTF_STRING_ENCODING_UTF8;
+ enum ctf_encoding encoding = CTF_ENCODING_UTF8;
*string_decl = NULL;
siblings);
if (left->u.unary_expression.type != UNARY_STRING) {
+ _BT_LOGE_NODE(left,
+ "Unexpected unary expression type: type=%d",
+ left->u.unary_expression.type);
ret = -EINVAL;
goto error;
}
char *s_right;
if (_IS_SET(&set, _STRING_ENCODING_SET)) {
- _PERROR_DUP_ATTR("encoding",
- "string declaration");
+ _BT_LOGE_DUP_ATTR(left, "encoding",
+ "string field class");
ret = -EPERM;
goto error;
}
if (right->u.unary_expression.type != UNARY_STRING) {
- _PERROR("%s", "invalid \"encoding\" attribute in string declaration: expecting unary string");
+ _BT_LOGE_NODE(right,
+ "Invalid `encoding` attribute in string field class: "
+ "expecting unary string.");
ret = -EINVAL;
goto error;
}
s_right = concatenate_unary_strings(
&expression->u.ctf_expression.right);
if (!s_right) {
- _PERROR("%s", "unexpected unary expression for string declaration's \"encoding\" attribute");
+ _BT_LOGE_NODE(right,
+ "Unexpected unary expression for string field class's `encoding` attribute.");
ret = -EINVAL;
goto error;
}
if (!strcmp(s_right, "UTF8") ||
!strcmp(s_right, "utf8") ||
!strcmp(s_right, "utf-8") ||
- !strcmp(s_right, "UTF-8")) {
- encoding = BT_CTF_STRING_ENCODING_UTF8;
- } else if (!strcmp(s_right, "ASCII") ||
+ !strcmp(s_right, "UTF-8") ||
+ !strcmp(s_right, "ASCII") ||
!strcmp(s_right, "ascii")) {
- encoding = BT_CTF_STRING_ENCODING_ASCII;
+ encoding = CTF_ENCODING_UTF8;
} else if (!strcmp(s_right, "none")) {
- encoding = BT_CTF_STRING_ENCODING_NONE;
+ encoding = CTF_ENCODING_NONE;
} else {
- _PERROR("invalid \"encoding\" attribute in string declaration: unknown encoding \"%s\"",
+ _BT_LOGE_NODE(right,
+ "Invalid `encoding` attribute in string field class: "
+ "unknown encoding: encoding=\"%s\"",
s_right);
g_free(s_right);
ret = -EINVAL;
g_free(s_right);
_SET(&set, _STRING_ENCODING_SET);
} else {
- _PWARNING("unknown attribute \"%s\" in string declaration",
+ _BT_LOGW_NODE(left,
+ "Unknown attribute in string field class: "
+ "attr-name=\"%s\"",
left->u.unary_expression.u.string);
}
}
- *string_decl = bt_ctf_field_type_string_create();
- if (!*string_decl) {
- _PERROR("%s", "cannot create string declaration");
- ret = -ENOMEM;
- goto error;
- }
-
- ret = bt_ctf_field_type_string_set_encoding(*string_decl, encoding);
- if (ret) {
- _PERROR("%s", "cannot configure string declaration");
- ret = -EINVAL;
- goto error;
- }
-
+ *string_decl = ctf_field_class_string_create();
+ BT_ASSERT(*string_decl);
+ (*string_decl)->encoding = encoding;
return 0;
error:
- BT_PUT(*string_decl);
-
+ ctf_field_class_destroy((void *) *string_decl);
+ *string_decl = NULL;
return ret;
}
static
-int visit_type_specifier_list(struct ctx *ctx,
- struct ctf_node *ts_list,
- struct bt_ctf_field_type **decl)
+int visit_field_class_specifier_list(struct ctx *ctx,
+ struct ctf_node *ts_list, struct ctf_field_class **decl)
{
int ret = 0;
struct ctf_node *first, *node;
*decl = NULL;
if (ts_list->type != NODE_TYPE_SPECIFIER_LIST) {
+ _BT_LOGE_NODE(ts_list,
+ "Unexpected node type: node-type=%d", ts_list->type);
ret = -EINVAL;
goto error;
}
- first = _BT_LIST_FIRST_ENTRY(&ts_list->u.type_specifier_list.head,
+ first = _BT_LIST_FIRST_ENTRY(&ts_list->u.field_class_specifier_list.head,
struct ctf_node, siblings);
if (first->type != NODE_TYPE_SPECIFIER) {
+ _BT_LOGE_NODE(first,
+ "Unexpected node type: node-type=%d", first->type);
ret = -EINVAL;
goto error;
}
- node = first->u.type_specifier.node;
+ node = first->u.field_class_specifier.node;
- switch (first->u.type_specifier.type) {
+ switch (first->u.field_class_specifier.type) {
case TYPESPEC_INTEGER:
ret = visit_integer_decl(ctx, &node->u.integer.expressions,
- decl);
+ (void *) decl);
if (ret) {
- assert(!*decl);
+ BT_ASSERT(!*decl);
goto error;
}
break;
case TYPESPEC_FLOATING_POINT:
ret = visit_floating_point_number_decl(ctx,
- &node->u.floating_point.expressions, decl);
+ &node->u.floating_point.expressions, (void *) decl);
if (ret) {
- assert(!*decl);
+ BT_ASSERT(!*decl);
goto error;
}
break;
case TYPESPEC_STRING:
ret = visit_string_decl(ctx,
- &node->u.string.expressions, decl);
+ &node->u.string.expressions, (void *) decl);
if (ret) {
- assert(!*decl);
+ BT_ASSERT(!*decl);
goto error;
}
break;
ret = visit_struct_decl(ctx, node->u._struct.name,
&node->u._struct.declaration_list,
node->u._struct.has_body,
- &node->u._struct.min_align, decl);
+ &node->u._struct.min_align, (void *) decl);
if (ret) {
- assert(!*decl);
+ BT_ASSERT(!*decl);
goto error;
}
break;
ret = visit_variant_decl(ctx, node->u.variant.name,
node->u.variant.choice,
&node->u.variant.declaration_list,
- node->u.variant.has_body, decl);
+ node->u.variant.has_body, (void *) decl);
if (ret) {
- assert(!*decl);
+ BT_ASSERT(!*decl);
goto error;
}
break;
case TYPESPEC_ENUM:
ret = visit_enum_decl(ctx, node->u._enum.enum_id,
- node->u._enum.container_type,
+ node->u._enum.container_field_class,
&node->u._enum.enumerator_list,
- node->u._enum.has_body, decl);
+ node->u._enum.has_body, (void *) decl);
if (ret) {
- assert(!*decl);
+ BT_ASSERT(!*decl);
goto error;
}
break;
case TYPESPEC_IMAGINARY:
case TYPESPEC_CONST:
case TYPESPEC_ID_TYPE:
- ret = visit_type_specifier(ctx, ts_list, decl);
+ ret = visit_field_class_specifier(ctx, ts_list, decl);
if (ret) {
- assert(!*decl);
+ _BT_LOGE_NODE(first,
+ "Cannot visit field class specifier: ret=%d",
+ ret);
+ BT_ASSERT(!*decl);
goto error;
}
break;
default:
- _PERROR("unexpected node type: %d",
- (int) first->u.type_specifier.type);
+ _BT_LOGE_NODE(first,
+ "Unexpected field class specifier type: node-type=%d",
+ first->u.field_class_specifier.type);
ret = -EINVAL;
goto error;
}
- assert(*decl);
-
+ BT_ASSERT(*decl);
return 0;
error:
- BT_PUT(*decl);
-
+ ctf_field_class_destroy((void *) *decl);
+ *decl = NULL;
return ret;
}
static
int visit_event_decl_entry(struct ctx *ctx, struct ctf_node *node,
- struct bt_ctf_event_class *event_class, int64_t *stream_id,
- int *set)
+ struct ctf_event_class *event_class, uint64_t *stream_id,
+ int *set)
{
int ret = 0;
char *left = NULL;
- _BT_CTF_FIELD_TYPE_INIT(decl);
switch (node->type) {
case NODE_TYPEDEF:
- ret = visit_typedef(ctx, node->u._typedef.type_specifier_list,
- &node->u._typedef.type_declarators);
+ ret = visit_field_class_def(ctx, node->u.field_class_def.field_class_specifier_list,
+ &node->u.field_class_def.field_class_declarators);
if (ret) {
- _PERROR("%s",
- "cannot add typedef in \"event\" declaration");
+ _BT_LOGE_NODE(node,
+ "Cannot add field class found in event class.");
goto error;
}
break;
case NODE_TYPEALIAS:
- ret = visit_typealias(ctx, node->u.typealias.target,
- node->u.typealias.alias);
+ ret = visit_field_class_alias(ctx, node->u.field_class_alias.target,
+ node->u.field_class_alias.alias);
if (ret) {
- _PERROR("%s", "cannot add typealias in \"event\" declaration");
+ _BT_LOGE_NODE(node,
+ "Cannot add field class alias found in event class.");
goto error;
}
break;
{
left = concatenate_unary_strings(&node->u.ctf_expression.left);
if (!left) {
+ _BT_LOGE_NODE(node, "Cannot concatenate unary strings.");
ret = -EINVAL;
goto error;
}
if (!strcmp(left, "name")) {
/* This is already known at this stage */
if (_IS_SET(set, _EVENT_NAME_SET)) {
- _PERROR_DUP_ATTR("name", "event declaration");
+ _BT_LOGE_DUP_ATTR(node, "name", "event class");
ret = -EPERM;
goto error;
}
_SET(set, _EVENT_NAME_SET);
} else if (!strcmp(left, "id")) {
- int64_t id;
+ int64_t id = -1;
if (_IS_SET(set, _EVENT_ID_SET)) {
- _PERROR_DUP_ATTR("id", "event declaration");
+ _BT_LOGE_DUP_ATTR(node, "id", "event class");
ret = -EPERM;
goto error;
}
ret = get_unary_unsigned(&node->u.ctf_expression.right,
(uint64_t *) &id);
- if (ret || id < 0) {
- _PERROR("%s", "unexpected unary expression for event declaration's \"id\" attribute");
+ /* Only read "id" if get_unary_unsigned() succeeded. */
+ if (ret || (!ret && id < 0)) {
+ _BT_LOGE_NODE(node,
+ "Unexpected unary expression for event class's `id` attribute.");
ret = -EINVAL;
goto error;
}
- ret = bt_ctf_event_class_set_id(event_class, id);
- if (ret) {
- _PERROR("%s",
- "cannot set event declaration's ID");
- goto error;
- }
-
+ event_class->id = id;
_SET(set, _EVENT_ID_SET);
} else if (!strcmp(left, "stream_id")) {
if (_IS_SET(set, _EVENT_STREAM_ID_SET)) {
- _PERROR_DUP_ATTR("stream_id",
- "event declaration");
+ _BT_LOGE_DUP_ATTR(node, "stream_id",
+ "event class");
ret = -EPERM;
goto error;
}
ret = get_unary_unsigned(&node->u.ctf_expression.right,
- (uint64_t *) stream_id);
- if (ret || *stream_id < 0) {
- _PERROR("%s", "unexpected unary expression for event declaration's \"stream_id\" attribute");
+ stream_id);
+
+ /*
+ * Only read "stream_id" if get_unary_unsigned()
+ * succeeded.
+ */
+ if (ret || (!ret && *stream_id < 0)) {
+ _BT_LOGE_NODE(node,
+ "Unexpected unary expression for event class's `stream_id` attribute.");
ret = -EINVAL;
goto error;
}
_SET(set, _EVENT_STREAM_ID_SET);
} else if (!strcmp(left, "context")) {
if (_IS_SET(set, _EVENT_CONTEXT_SET)) {
- _PERROR("%s", "duplicate \"context\" entry in event declaration");
+ _BT_LOGE_NODE(node,
+ "Duplicate `context` entry in event class.");
ret = -EPERM;
goto error;
}
- ret = visit_type_specifier_list(ctx,
+ ret = visit_field_class_specifier_list(ctx,
_BT_LIST_FIRST_ENTRY(
&node->u.ctf_expression.right,
struct ctf_node, siblings),
- &decl);
- if (ret) {
- _PERROR("%s", "cannot create event context declaration");
- goto error;
- }
-
- assert(decl);
- ret = bt_ctf_event_class_set_context_type(
- event_class, decl);
- BT_PUT(decl);
+ &event_class->spec_context_fc);
if (ret) {
- _PERROR("%s", "cannot set event's context declaration");
+ _BT_LOGE_NODE(node,
+ "Cannot create event class's context field class.");
goto error;
}
+ BT_ASSERT(event_class->spec_context_fc);
_SET(set, _EVENT_CONTEXT_SET);
} else if (!strcmp(left, "fields")) {
if (_IS_SET(set, _EVENT_FIELDS_SET)) {
- _PERROR("%s", "duplicate \"fields\" entry in event declaration");
+ _BT_LOGE_NODE(node,
+ "Duplicate `fields` entry in event class.");
ret = -EPERM;
goto error;
}
- ret = visit_type_specifier_list(ctx,
+ ret = visit_field_class_specifier_list(ctx,
_BT_LIST_FIRST_ENTRY(
&node->u.ctf_expression.right,
struct ctf_node, siblings),
- &decl);
- if (ret) {
- _PERROR("%s", "cannot create event payload declaration");
- goto error;
- }
-
- assert(decl);
- ret = bt_ctf_event_class_set_payload_type(
- event_class, decl);
- BT_PUT(decl);
+ &event_class->payload_fc);
if (ret) {
- _PERROR("%s", "cannot set event's payload declaration");
+ _BT_LOGE_NODE(node,
+ "Cannot create event class's payload field class.");
goto error;
}
+ BT_ASSERT(event_class->payload_fc);
_SET(set, _EVENT_FIELDS_SET);
} else if (!strcmp(left, "loglevel")) {
uint64_t loglevel_value;
- const char *loglevel_str;
- struct bt_value *value_obj, *str_obj;
+ bt_event_class_log_level log_level = -1;
- if (_IS_SET(set, _EVENT_LOGLEVEL_SET)) {
- _PERROR_DUP_ATTR("loglevel",
- "event declaration");
+ if (_IS_SET(set, _EVENT_LOG_LEVEL_SET)) {
+ _BT_LOGE_DUP_ATTR(node, "loglevel",
+ "event class");
ret = -EPERM;
goto error;
}
ret = get_unary_unsigned(&node->u.ctf_expression.right,
&loglevel_value);
if (ret) {
- _PERROR("%s", "unexpected unary expression for event declaration's \"loglevel\" attribute");
+ _BT_LOGE_NODE(node,
+ "Unexpected unary expression for event class's `loglevel` attribute.");
ret = -EINVAL;
goto error;
}
- value_obj = bt_value_integer_create_init(loglevel_value);
- if (!value_obj) {
- _PERROR("%s", "cannot allocate memory for loglevel value object");
- ret = -ENOMEM;
- goto error;
- }
- if (bt_ctf_event_class_set_attribute(event_class,
- "loglevel", value_obj) != BT_VALUE_STATUS_OK) {
- _PERROR("%s", "cannot set loglevel value");
- ret = -EINVAL;
- bt_put(value_obj);
- goto error;
+
+ switch (loglevel_value) {
+ case 0:
+ log_level = BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY;
+ break;
+ case 1:
+ log_level = BT_EVENT_CLASS_LOG_LEVEL_ALERT;
+ break;
+ case 2:
+ log_level = BT_EVENT_CLASS_LOG_LEVEL_CRITICAL;
+ break;
+ case 3:
+ log_level = BT_EVENT_CLASS_LOG_LEVEL_ERROR;
+ break;
+ case 4:
+ log_level = BT_EVENT_CLASS_LOG_LEVEL_WARNING;
+ break;
+ case 5:
+ log_level = BT_EVENT_CLASS_LOG_LEVEL_NOTICE;
+ break;
+ case 6:
+ log_level = BT_EVENT_CLASS_LOG_LEVEL_INFO;
+ break;
+ case 7:
+ log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM;
+ break;
+ case 8:
+ log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM;
+ break;
+ case 9:
+ log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS;
+ break;
+ case 10:
+ log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE;
+ break;
+ case 11:
+ log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT;
+ break;
+ case 12:
+ log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION;
+ break;
+ case 13:
+ log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE;
+ break;
+ case 14:
+ log_level = BT_EVENT_CLASS_LOG_LEVEL_DEBUG;
+ break;
+ default:
+ _BT_LOGW_NODE(node, "Not setting event class's log level because its value is unknown: "
+ "log-level=%" PRIu64, loglevel_value);
}
- loglevel_str = print_loglevel(loglevel_value);
- if (loglevel_str) {
- str_obj = bt_value_string_create_init(loglevel_str);
- if (bt_ctf_event_class_set_attribute(event_class,
- "loglevel_string", str_obj) != BT_VALUE_STATUS_OK) {
- _PERROR("%s", "cannot set loglevel string");
- ret = -EINVAL;
- bt_put(str_obj);
- goto error;
- }
- bt_put(str_obj);
+
+ if (log_level != -1) {
+ event_class->log_level = log_level;
}
- bt_put(value_obj);
- _SET(set, _EVENT_LOGLEVEL_SET);
+
+ _SET(set, _EVENT_LOG_LEVEL_SET);
} else if (!strcmp(left, "model.emf.uri")) {
char *right;
if (_IS_SET(set, _EVENT_MODEL_EMF_URI_SET)) {
- _PERROR_DUP_ATTR("model.emf.uri",
- "event declaration");
+ _BT_LOGE_DUP_ATTR(node, "model.emf.uri",
+ "event class");
ret = -EPERM;
goto error;
}
right = concatenate_unary_strings(
&node->u.ctf_expression.right);
if (!right) {
- _PERROR("%s", "unexpected unary expression for event declaration's \"model.emf.uri\" attribute");
+ _BT_LOGE_NODE(node,
+ "Unexpected unary expression for event class's `model.emf.uri` attribute.");
ret = -EINVAL;
goto error;
}
- // TODO: FIXME: set model EMF URI here
+ if (strlen(right) == 0) {
+ _BT_LOGW_NODE(node,
+ "Not setting event class's EMF URI because it's empty.");
+ } else {
+ g_string_assign(event_class->emf_uri,
+ right);
+ }
g_free(right);
_SET(set, _EVENT_MODEL_EMF_URI_SET);
} else {
- _PWARNING("unknown attribute \"%s\" in event declaration",
- left);
+ _BT_LOGW_NODE(node,
+ "Unknown attribute in event class: "
+ "attr-name=\"%s\"", left);
}
g_free(left);
goto error;
}
- return 0;
+ goto end;
error:
if (left) {
g_free(left);
}
- BT_PUT(decl);
-
+end:
return ret;
}
left = concatenate_unary_strings(&iter->u.ctf_expression.left);
if (!left) {
+ _BT_LOGE_NODE(iter,
+ "Cannot concatenate unary strings.");
goto error;
}
name = concatenate_unary_strings(
&iter->u.ctf_expression.right);
if (!name) {
- _PERROR("%s", "unexpected unary expression for event declaration's \"name\" attribute");
+ _BT_LOGE_NODE(iter,
+ "Unexpected unary expression for event class's `name` attribute.");
goto error;
}
}
error:
g_free(left);
-
- return NULL;
-}
-
-static
-int reset_event_decl_types(struct ctx *ctx,
- struct bt_ctf_event_class *event_class)
-{
- int ret = 0;
-
- /* Context type. */
- ret = bt_ctf_event_class_set_context_type(event_class, NULL);
- if (ret) {
- _PERROR("%s", "cannot set initial NULL event context");
- goto end;
- }
-
- /* Event payload. */
- ret = bt_ctf_event_class_set_payload_type(event_class, NULL);
- if (ret) {
- _PERROR("%s", "cannot set initial NULL event payload");
- goto end;
- }
-end:
- return ret;
-}
-
-static
-int reset_stream_decl_types(struct ctx *ctx,
- struct bt_ctf_stream_class *stream_class)
-{
- int ret = 0;
-
- /* Packet context. */
- ret = bt_ctf_stream_class_set_packet_context_type(stream_class, NULL);
- if (ret) {
- _PERROR("%s", "cannot set initial empty packet context");
- goto end;
- }
-
- /* Event header. */
- ret = bt_ctf_stream_class_set_event_header_type(stream_class, NULL);
- if (ret) {
- _PERROR("%s", "cannot set initial empty event header");
- goto end;
- }
-
- /* Event context. */
- ret = bt_ctf_stream_class_set_event_context_type(stream_class, NULL);
- if (ret) {
- _PERROR("%s", "cannot set initial empty stream event context");
- goto end;
- }
-end:
- return ret;
-}
-
-static
-struct bt_ctf_stream_class *create_reset_stream_class(struct ctx *ctx)
-{
- int ret;
- struct bt_ctf_stream_class *stream_class;
-
- stream_class = bt_ctf_stream_class_create(NULL);
- if (!stream_class) {
- _PERROR("%s", "cannot create stream class");
- goto error;
- }
-
- /*
- * Set packet context, event header, and event context to NULL to
- * override the default ones.
- */
- ret = reset_stream_decl_types(ctx, stream_class);
- if (ret) {
- goto error;
- }
-
- return stream_class;
-
-error:
- BT_PUT(stream_class);
-
return NULL;
}
{
int ret = 0;
int set = 0;
- int64_t event_id;
struct ctf_node *iter;
- int64_t stream_id = -1;
+ uint64_t stream_id = 0;
char *event_name = NULL;
- struct bt_ctf_event_class *event_class = NULL;
- struct bt_ctf_event_class *eevent_class;
- struct bt_ctf_stream_class *stream_class;
+ struct ctf_event_class *event_class = NULL;
+ struct ctf_stream_class *stream_class = NULL;
struct bt_list_head *decl_list = &node->u.event.declaration_list;
+ bool pop_scope = false;
if (node->visited) {
goto end;
node->visited = TRUE;
event_name = get_event_decl_name(ctx, node);
if (!event_name) {
- _PERROR("%s",
- "missing \"name\" attribute in event declaration");
+ _BT_LOGE_NODE(node,
+ "Missing `name` attribute in event class.");
ret = -EPERM;
goto error;
}
- event_class = bt_ctf_event_class_create(event_name);
-
- /*
- * Unset context and fields to override the default ones.
- */
- ret = reset_event_decl_types(ctx, event_class);
- if (ret) {
- goto error;
- }
-
-
- ret = ctx_push_scope(ctx);
- if (ret) {
- _PERROR("%s", "cannot push scope");
- goto error;
- }
+ event_class = ctf_event_class_create();
+ BT_ASSERT(event_class);
+ g_string_assign(event_class->name, event_name);
+ _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
+ pop_scope = true;
bt_list_for_each_entry(iter, decl_list, siblings) {
ret = visit_event_decl_entry(ctx, iter, event_class,
&stream_id, &set);
if (ret) {
+ _BT_LOGE_NODE(iter, "Cannot visit event class's entry: "
+ "ret=%d", ret);
goto error;
}
}
if (!_IS_SET(&set, _EVENT_STREAM_ID_SET)) {
- GList *keys = NULL;
- struct bt_ctf_stream_class *new_stream_class;
-
- /* Allow missing stream_id if there is only a single stream */
- switch (g_hash_table_size(ctx->stream_classes)) {
+ /*
+ * Allow missing stream_id if there is only a single
+ * stream class.
+ */
+ switch (ctx->ctf_tc->stream_classes->len) {
case 0:
- /* Create stream if there's none */
- new_stream_class = create_reset_stream_class(ctx);
- if (!new_stream_class) {
- ret = -EINVAL;
- goto error;
- }
-
- ret = bt_ctf_stream_class_set_id(new_stream_class, 0);
- if (ret) {
- _PERROR("%s", "cannot set stream's ID");
- BT_PUT(new_stream_class);
- goto error;
- }
-
+ /* Create implicit stream class if there's none */
stream_id = 0;
-
- /* Move reference to visitor's context */
- g_hash_table_insert(ctx->stream_classes,
- (gpointer) stream_id, new_stream_class);
- new_stream_class = NULL;
-
+ stream_class = ctf_stream_class_create();
+ BT_ASSERT(stream_class);
+ stream_class->id = stream_id;
+ g_ptr_array_add(ctx->ctf_tc->stream_classes,
+ stream_class);
+ stream_class = stream_class;
break;
case 1:
- /* Single stream: get its ID */
- keys = g_hash_table_get_keys(ctx->stream_classes);
- stream_id = (int64_t) keys->data;
- g_list_free(keys);
- keys = NULL;
+ /* Single stream class: get its ID */
+ stream_class = ctx->ctf_tc->stream_classes->pdata[0];
+ stream_id = stream_class->id;
break;
default:
- _PERROR("%s", "missing \"stream_id\" attribute in event declaration");
+ _BT_LOGE_NODE(node,
+ "Missing `stream_id` attribute in event class.");
ret = -EPERM;
goto error;
}
}
-
-
- assert(stream_id >= 0);
-
- /* We have the stream ID now; borrow the stream class if found */
- stream_class = g_hash_table_lookup(ctx->stream_classes,
- (gpointer) stream_id);
+ /* We have the stream ID now; get the stream class if found */
if (!stream_class) {
- _PERROR("cannot find stream class with ID %" PRId64,
- stream_id);
- ret = -EINVAL;
- goto error;
+ stream_class = ctf_trace_class_borrow_stream_class_by_id(
+ ctx->ctf_tc, stream_id);
+ if (!stream_class) {
+ _BT_LOGE_NODE(node,
+ "Cannot find stream class at this point: "
+ "id=%" PRId64, stream_id);
+ ret = -EINVAL;
+ goto error;
+ }
}
+ BT_ASSERT(stream_class);
+
if (!_IS_SET(&set, _EVENT_ID_SET)) {
/* Allow only one event without ID per stream */
- if (bt_ctf_stream_class_get_event_class_count(stream_class) !=
- 0) {
- _PERROR("%s",
- "missing \"id\" field in event declaration");
+ if (stream_class->event_classes->len != 0) {
+ _BT_LOGE_NODE(node,
+ "Missing `id` attribute in event class.");
ret = -EPERM;
goto error;
}
/* Automatic ID */
- ret = bt_ctf_event_class_set_id(event_class, 0);
- if (ret) {
- _PERROR("%s", "cannot set event's ID");
- goto error;
- }
+ event_class->id = 0;
}
- event_id = bt_ctf_event_class_get_id(event_class);
- if (event_id < 0) {
- _PERROR("%s", "cannot get event's ID");
- ret = -EINVAL;
+ if (ctf_stream_class_borrow_event_class_by_id(stream_class,
+ event_class->id)) {
+ _BT_LOGE_NODE(node,
+ "Duplicate event class (same ID) in the same stream class: "
+ "id=%" PRId64, event_class->id);
+ ret = -EEXIST;
goto error;
}
- eevent_class = bt_ctf_stream_class_get_event_class_by_id(stream_class,
- event_id);
- if (eevent_class) {
- BT_PUT(eevent_class);
- _PERROR("%s", "duplicate event with ID %" PRId64 " in same stream");
- ret = -EEXIST;
- goto error;
+ ctf_stream_class_append_event_class(stream_class, event_class);
+ event_class = NULL;
+ goto end;
+
+error:
+ ctf_event_class_destroy(event_class);
+ event_class = NULL;
+
+ if (ret >= 0) {
+ ret = -1;
}
- eevent_class = bt_ctf_stream_class_get_event_class_by_name(stream_class,
- event_name);
- if (eevent_class) {
- BT_PUT(eevent_class);
- eevent_class = NULL;
- _PERROR("%s",
- "duplicate event with name \"%s\" in same stream");
- ret = -EEXIST;
- goto error;
+end:
+ if (pop_scope) {
+ ctx_pop_scope(ctx);
}
- g_free(event_name);
- ret = bt_ctf_stream_class_add_event_class(stream_class, event_class);
- BT_PUT(event_class);
- event_class = NULL;
+ if (event_name) {
+ g_free(event_name);
+ }
- if (ret) {
- _PERROR("%s", "cannot add event class to stream class");
- goto error;
+ return ret;
+}
+
+static
+int auto_map_field_to_trace_clock_class(struct ctx *ctx,
+ struct ctf_field_class *fc)
+{
+ struct ctf_clock_class *clock_class_to_map_to = NULL;
+ struct ctf_field_class_int *int_fc = (void *) fc;
+ int ret = 0;
+ uint64_t clock_class_count;
+
+ if (!fc) {
+ goto end;
+ }
+
+ if (fc->type != CTF_FIELD_CLASS_TYPE_INT &&
+ fc->type != CTF_FIELD_CLASS_TYPE_ENUM) {
+ goto end;
}
+ if (int_fc->mapped_clock_class) {
+ /* Already mapped */
+ goto end;
+ }
+
+ clock_class_count = ctx->ctf_tc->clock_classes->len;
+
+ switch (clock_class_count) {
+ case 0:
+ /*
+ * No clock class exists in the trace at this point. Create an
+ * implicit one at 1 GHz, named `default`, and use this clock
+ * class.
+ */
+ clock_class_to_map_to = ctf_clock_class_create();
+ BT_ASSERT(clock_class_to_map_to);
+ clock_class_to_map_to->frequency = UINT64_C(1000000000);
+ g_string_assign(clock_class_to_map_to->name, "default");
+ BT_ASSERT(ret == 0);
+ g_ptr_array_add(ctx->ctf_tc->clock_classes,
+ clock_class_to_map_to);
+ break;
+ case 1:
+ /*
+ * Only one clock class exists in the trace at this point: use
+ * this one.
+ */
+ clock_class_to_map_to = ctx->ctf_tc->clock_classes->pdata[0];
+ break;
+ default:
+ /*
+ * Timestamp field not mapped to a clock class and there's more
+ * than one clock class in the trace: this is an error.
+ */
+ BT_LOGE_STR("Timestamp field found with no mapped clock class, "
+ "but there's more than one clock class in the trace at this point.");
+ ret = -1;
+ goto end;
+ }
+
+ BT_ASSERT(clock_class_to_map_to);
+ int_fc->mapped_clock_class = clock_class_to_map_to;
+
end:
- return 0;
+ return ret;
+}
-error:
- g_free(event_name);
- BT_PUT(event_class);
+static
+int auto_map_fields_to_trace_clock_class(struct ctx *ctx,
+ struct ctf_field_class *root_fc, const char *field_name)
+{
+ int ret = 0;
+ uint64_t i, count;
+ struct ctf_field_class_struct *struct_fc = (void *) root_fc;
+ struct ctf_field_class_variant *var_fc = (void *) root_fc;
+
+ if (!root_fc) {
+ goto end;
+ }
+
+ if (root_fc->type != CTF_FIELD_CLASS_TYPE_STRUCT &&
+ root_fc->type != CTF_FIELD_CLASS_TYPE_VARIANT) {
+ goto end;
+ }
+
+ if (root_fc->type == CTF_FIELD_CLASS_TYPE_STRUCT) {
+ count = struct_fc->members->len;
+ } else {
+ count = var_fc->options->len;
+ }
+
+ for (i = 0; i < count; i++) {
+ struct ctf_named_field_class *named_fc = NULL;
+
+ if (root_fc->type == CTF_FIELD_CLASS_TYPE_STRUCT) {
+ named_fc = ctf_field_class_struct_borrow_member_by_index(
+ struct_fc, i);
+ } else if (root_fc->type == CTF_FIELD_CLASS_TYPE_VARIANT) {
+ named_fc = ctf_field_class_variant_borrow_option_by_index(
+ var_fc, i);
+ }
- /* stream_class is borrowed; it still belongs to the hash table */
+ if (strcmp(named_fc->name->str, field_name) == 0) {
+ ret = auto_map_field_to_trace_clock_class(ctx,
+ named_fc->fc);
+ if (ret) {
+ BT_LOGE("Cannot automatically map field to trace's clock class: "
+ "field-name=\"%s\"", field_name);
+ goto end;
+ }
+ }
+
+ ret = auto_map_fields_to_trace_clock_class(ctx, named_fc->fc,
+ field_name);
+ if (ret) {
+ BT_LOGE("Cannot automatically map structure or variant field class's fields to trace's clock class: "
+ "field-name=\"%s\", root-field-name=\"%s\"",
+ field_name, named_fc->name->str);
+ goto end;
+ }
+ }
+end:
return ret;
}
static
int visit_stream_decl_entry(struct ctx *ctx, struct ctf_node *node,
- struct bt_ctf_stream_class *stream_class, int *set)
+ struct ctf_stream_class *stream_class, int *set)
{
int ret = 0;
char *left = NULL;
- _BT_CTF_FIELD_TYPE_INIT(decl);
switch (node->type) {
case NODE_TYPEDEF:
- ret = visit_typedef(ctx, node->u._typedef.type_specifier_list,
- &node->u._typedef.type_declarators);
+ ret = visit_field_class_def(ctx, node->u.field_class_def.field_class_specifier_list,
+ &node->u.field_class_def.field_class_declarators);
if (ret) {
- _PERROR("%s",
- "cannot add typedef in \"stream\" declaration");
+ _BT_LOGE_NODE(node,
+ "Cannot add field class found in stream class.");
goto error;
}
break;
case NODE_TYPEALIAS:
- ret = visit_typealias(ctx, node->u.typealias.target,
- node->u.typealias.alias);
+ ret = visit_field_class_alias(ctx, node->u.field_class_alias.target,
+ node->u.field_class_alias.alias);
if (ret) {
- _PERROR("%s", "cannot add typealias in \"stream\" declaration");
+ _BT_LOGE_NODE(node,
+ "Cannot add field class alias found in stream class.");
goto error;
}
break;
{
left = concatenate_unary_strings(&node->u.ctf_expression.left);
if (!left) {
+ _BT_LOGE_NODE(node, "Cannot concatenate unary strings.");
ret = -EINVAL;
goto error;
}
if (!strcmp(left, "id")) {
int64_t id;
- gpointer ptr;
if (_IS_SET(set, _STREAM_ID_SET)) {
- _PERROR_DUP_ATTR("id", "stream declaration");
+ _BT_LOGE_DUP_ATTR(node, "id",
+ "stream declaration");
ret = -EPERM;
goto error;
}
ret = get_unary_unsigned(&node->u.ctf_expression.right,
(uint64_t *) &id);
- if (ret || id < 0) {
- _PERROR("%s", "unexpected unary expression for stream declaration's \"id\" attribute");
+
+ /* Only read "id" if get_unary_unsigned() succeeded. */
+ if (ret || (!ret && id < 0)) {
+ _BT_LOGE_NODE(node,
+ "Unexpected unary expression for stream class's `id` attribute.");
ret = -EINVAL;
goto error;
}
- ptr = g_hash_table_lookup(ctx->stream_classes,
- (gpointer) id);
- if (ptr) {
- _PERROR("duplicate stream with ID %" PRId64,
+ if (ctf_trace_class_borrow_stream_class_by_id(
+ ctx->ctf_tc, id)) {
+ _BT_LOGE_NODE(node,
+ "Duplicate stream class (same ID): id=%" PRId64,
id);
ret = -EEXIST;
goto error;
}
- ret = bt_ctf_stream_class_set_id(stream_class, id);
- if (ret) {
- _PERROR("%s",
- "cannot set stream declaration's ID");
- goto error;
- }
-
+ stream_class->id = id;
_SET(set, _STREAM_ID_SET);
} else if (!strcmp(left, "event.header")) {
if (_IS_SET(set, _STREAM_EVENT_HEADER_SET)) {
- _PERROR("%s", "duplicate \"event.header\" entry in stream declaration");
+ _BT_LOGE_NODE(node,
+ "Duplicate `event.header` entry in stream class.");
ret = -EPERM;
goto error;
}
- ret = visit_type_specifier_list(ctx,
+ ret = visit_field_class_specifier_list(ctx,
_BT_LIST_FIRST_ENTRY(
&node->u.ctf_expression.right,
struct ctf_node, siblings),
- &decl);
+ &stream_class->event_header_fc);
if (ret) {
- _PERROR("%s", "cannot create event header declaration");
+ _BT_LOGE_NODE(node,
+ "Cannot create stream class's event header field class.");
goto error;
}
- assert(decl);
-
- ret = bt_ctf_stream_class_set_event_header_type(
- stream_class, decl);
- BT_PUT(decl);
+ BT_ASSERT(stream_class->event_header_fc);
+ ret = auto_map_fields_to_trace_clock_class(ctx,
+ stream_class->event_header_fc, "timestamp");
if (ret) {
- _PERROR("%s", "cannot set stream's event header declaration");
+ _BT_LOGE_NODE(node,
+ "Cannot automatically map specific event header field class fields named `timestamp` to trace's clock class.");
goto error;
}
_SET(set, _STREAM_EVENT_HEADER_SET);
} else if (!strcmp(left, "event.context")) {
if (_IS_SET(set, _STREAM_EVENT_CONTEXT_SET)) {
- _PERROR("%s", "duplicate \"event.context\" entry in stream declaration");
+ _BT_LOGE_NODE(node,
+ "Duplicate `event.context` entry in stream class.");
ret = -EPERM;
goto error;
}
- ret = visit_type_specifier_list(ctx,
+ ret = visit_field_class_specifier_list(ctx,
_BT_LIST_FIRST_ENTRY(
&node->u.ctf_expression.right,
struct ctf_node, siblings),
- &decl);
- if (ret) {
- _PERROR("%s", "cannot create stream event context declaration");
- goto error;
- }
-
- assert(decl);
-
- ret = bt_ctf_stream_class_set_event_context_type(
- stream_class, decl);
- BT_PUT(decl);
+ &stream_class->event_common_context_fc);
if (ret) {
- _PERROR("%s", "cannot set stream's event context declaration");
+ _BT_LOGE_NODE(node,
+ "Cannot create stream class's event context field class.");
goto error;
}
+ BT_ASSERT(stream_class->event_common_context_fc);
_SET(set, _STREAM_EVENT_CONTEXT_SET);
} else if (!strcmp(left, "packet.context")) {
if (_IS_SET(set, _STREAM_PACKET_CONTEXT_SET)) {
- _PERROR("%s", "duplicate \"packet.context\" entry in stream declaration");
+ _BT_LOGE_NODE(node,
+ "Duplicate `packet.context` entry in stream class.");
ret = -EPERM;
goto error;
}
- ret = visit_type_specifier_list(ctx,
+ ret = visit_field_class_specifier_list(ctx,
_BT_LIST_FIRST_ENTRY(
&node->u.ctf_expression.right,
struct ctf_node, siblings),
- &decl);
+ &stream_class->packet_context_fc);
if (ret) {
- _PERROR("%s", "cannot create packet context declaration");
+ _BT_LOGE_NODE(node,
+ "Cannot create stream class's packet context field class.");
goto error;
}
- assert(decl);
+ BT_ASSERT(stream_class->packet_context_fc);
+ ret = auto_map_fields_to_trace_clock_class(ctx,
+ stream_class->packet_context_fc,
+ "timestamp_begin");
+ if (ret) {
+ _BT_LOGE_NODE(node,
+ "Cannot automatically map specific packet context field class fields named `timestamp_begin` to trace's clock class.");
+ goto error;
+ }
- ret = bt_ctf_stream_class_set_packet_context_type(
- stream_class, decl);
- BT_PUT(decl);
+ ret = auto_map_fields_to_trace_clock_class(ctx,
+ stream_class->packet_context_fc,
+ "timestamp_end");
if (ret) {
- _PERROR("%s", "cannot set stream's packet context declaration");
+ _BT_LOGE_NODE(node,
+ "Cannot automatically map specific packet context field class fields named `timestamp_end` to trace's clock class.");
goto error;
}
_SET(set, _STREAM_PACKET_CONTEXT_SET);
} else {
- _PWARNING("unknown attribute \"%s\" in stream declaration",
- left);
+ _BT_LOGW_NODE(node,
+ "Unknown attribute in stream class: "
+ "attr-name=\"%s\"", left);
}
g_free(left);
error:
g_free(left);
- BT_PUT(decl);
-
return ret;
}
static
int visit_stream_decl(struct ctx *ctx, struct ctf_node *node)
{
- int64_t id;
int set = 0;
int ret = 0;
struct ctf_node *iter;
- struct bt_ctf_stream_class *stream_class = NULL;
+ struct ctf_stream_class *stream_class = NULL;
struct bt_list_head *decl_list = &node->u.stream.declaration_list;
if (node->visited) {
}
node->visited = TRUE;
- stream_class = create_reset_stream_class(ctx);
- if (!stream_class) {
- ret = -EINVAL;
- goto error;
- }
-
- ret = ctx_push_scope(ctx);
- if (ret) {
- _PERROR("%s", "cannot push scope");
- goto error;
- }
+ stream_class = ctf_stream_class_create();
+ BT_ASSERT(stream_class);
+ _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
bt_list_for_each_entry(iter, decl_list, siblings) {
ret = visit_stream_decl_entry(ctx, iter, stream_class, &set);
if (ret) {
+ _BT_LOGE_NODE(iter,
+ "Cannot visit stream class's entry: "
+ "ret=%d", ret);
ctx_pop_scope(ctx);
goto error;
}
ctx_pop_scope(ctx);
if (_IS_SET(&set, _STREAM_ID_SET)) {
- /* Check that packet header has stream_id field */
- _BT_CTF_FIELD_TYPE_INIT(stream_id_decl);
- _BT_CTF_FIELD_TYPE_INIT(packet_header_decl);
-
- packet_header_decl =
- bt_ctf_trace_get_packet_header_type(ctx->trace);
- if (!packet_header_decl) {
- _PERROR("%s",
- "cannot get trace packet header declaration");
+ /* Check that packet header has `stream_id` field */
+ struct ctf_named_field_class *named_fc = NULL;
+
+ if (!ctx->ctf_tc->packet_header_fc) {
+ _BT_LOGE_NODE(node,
+ "Stream class has a `id` attribute, "
+ "but trace has no packet header field class.");
goto error;
}
- stream_id_decl =
- bt_ctf_field_type_structure_get_field_type_by_name(
- packet_header_decl, "stream_id");
- BT_PUT(packet_header_decl);
- if (!stream_id_decl) {
- _PERROR("%s", "missing \"stream_id\" field in packet header declaration, but \"id\" attribute is declared for stream");
+ named_fc = ctf_field_class_struct_borrow_member_by_name(
+ (void *) ctx->ctf_tc->packet_header_fc, "stream_id");
+ if (!named_fc) {
+ _BT_LOGE_NODE(node,
+ "Stream class has a `id` attribute, "
+ "but trace's packet header field class has no `stream_id` field.");
goto error;
}
- if (!bt_ctf_field_type_is_integer(stream_id_decl)) {
- BT_PUT(stream_id_decl);
- _PERROR("%s", "\"stream_id\" field in packet header declaration is not an integer");
+ if (named_fc->fc->type != CTF_FIELD_CLASS_TYPE_INT &&
+ named_fc->fc->type != CTF_FIELD_CLASS_TYPE_ENUM) {
+ _BT_LOGE_NODE(node,
+ "Stream class has a `id` attribute, "
+ "but trace's packet header field class's `stream_id` field is not an integer field class.");
goto error;
}
-
- BT_PUT(stream_id_decl);
} else {
/* Allow only _one_ ID-less stream */
- if (g_hash_table_size(ctx->stream_classes) != 0) {
- _PERROR("%s",
- "missing \"id\" field in stream declaration");
+ if (ctx->ctf_tc->stream_classes->len != 0) {
+ _BT_LOGE_NODE(node,
+ "Missing `id` attribute in stream class as there's more than one stream class in the trace.");
ret = -EPERM;
goto error;
}
/* Automatic ID: 0 */
- ret = bt_ctf_stream_class_set_id(stream_class, 0);
+ stream_class->id = 0;
}
- id = bt_ctf_stream_class_get_id(stream_class);
- if (id < 0) {
- _PERROR("wrong stream ID: %" PRId64, id);
+ /*
+ * Make sure that this stream class's ID is currently unique in
+ * the trace.
+ */
+ if (ctf_trace_class_borrow_stream_class_by_id(ctx->ctf_tc,
+ stream_class->id)) {
+ _BT_LOGE_NODE(node,
+ "Duplicate stream class (same ID): id=%" PRId64,
+ stream_class->id);
ret = -EINVAL;
goto error;
}
- /* Move reference to visitor's context */
- g_hash_table_insert(ctx->stream_classes, (gpointer) (int64_t) id,
- stream_class);
+ g_ptr_array_add(ctx->ctf_tc->stream_classes, stream_class);
stream_class = NULL;
-
-end:
- return 0;
+ goto end;
error:
- BT_PUT(stream_class);
+ ctf_stream_class_destroy(stream_class);
+ stream_class = NULL;
+end:
return ret;
}
{
int ret = 0;
char *left = NULL;
- _BT_CTF_FIELD_TYPE_INIT(packet_header_decl);
+ uint64_t val;
switch (node->type) {
case NODE_TYPEDEF:
- ret = visit_typedef(ctx, node->u._typedef.type_specifier_list,
- &node->u._typedef.type_declarators);
+ ret = visit_field_class_def(ctx, node->u.field_class_def.field_class_specifier_list,
+ &node->u.field_class_def.field_class_declarators);
if (ret) {
- _PERROR("%s",
- "cannot add typedef in \"trace\" declaration");
+ _BT_LOGE_NODE(node,
+ "Cannot add field class found in trace (`trace` block).");
goto error;
}
break;
case NODE_TYPEALIAS:
- ret = visit_typealias(ctx, node->u.typealias.target,
- node->u.typealias.alias);
+ ret = visit_field_class_alias(ctx, node->u.field_class_alias.target,
+ node->u.field_class_alias.alias);
if (ret) {
- _PERROR("%s",
- "cannot add typealias in \"trace\" declaration");
+ _BT_LOGE_NODE(node,
+ "Cannot add field class alias found in trace (`trace` block).");
goto error;
}
break;
{
left = concatenate_unary_strings(&node->u.ctf_expression.left);
if (!left) {
+ _BT_LOGE_NODE(node, "Cannot concatenate unary strings.");
ret = -EINVAL;
goto error;
}
if (!strcmp(left, "major")) {
if (_IS_SET(set, _TRACE_MAJOR_SET)) {
- _PERROR_DUP_ATTR("major", "trace declaration");
+ _BT_LOGE_DUP_ATTR(node, "major", "trace");
ret = -EPERM;
goto error;
}
ret = get_unary_unsigned(&node->u.ctf_expression.right,
- &ctx->trace_major);
+ &val);
if (ret) {
- _PERROR("%s", "unexpected unary expression for trace's \"major\" attribute");
+ _BT_LOGE_NODE(node,
+ "Unexpected unary expression for trace's `major` attribute.");
ret = -EINVAL;
goto error;
}
+ if (val != 1) {
+ _BT_LOGE_NODE(node,
+ "Invalid trace's `minor` attribute: expecting 1.");
+ goto error;
+ }
+
+ ctx->ctf_tc->major = val;
_SET(set, _TRACE_MAJOR_SET);
} else if (!strcmp(left, "minor")) {
if (_IS_SET(set, _TRACE_MINOR_SET)) {
- _PERROR_DUP_ATTR("minor", "trace declaration");
+ _BT_LOGE_DUP_ATTR(node, "minor", "trace");
ret = -EPERM;
goto error;
}
ret = get_unary_unsigned(&node->u.ctf_expression.right,
- &ctx->trace_minor);
+ &val);
if (ret) {
- _PERROR("%s", "unexpected unary expression for trace's \"minor\" attribute");
+ _BT_LOGE_NODE(node,
+ "Unexpected unary expression for trace's `minor` attribute.");
ret = -EINVAL;
goto error;
}
+ if (val != 8) {
+ _BT_LOGE_NODE(node,
+ "Invalid trace's `minor` attribute: expecting 8.");
+ goto error;
+ }
+
+ ctx->ctf_tc->minor = val;
_SET(set, _TRACE_MINOR_SET);
} else if (!strcmp(left, "uuid")) {
if (_IS_SET(set, _TRACE_UUID_SET)) {
- _PERROR_DUP_ATTR("uuid", "trace declaration");
+ _BT_LOGE_DUP_ATTR(node, "uuid", "trace");
ret = -EPERM;
goto error;
}
ret = get_unary_uuid(&node->u.ctf_expression.right,
- ctx->trace_uuid);
+ ctx->ctf_tc->uuid);
if (ret) {
- _PERROR("%s",
- "invalid trace declaration's UUID");
+ _BT_LOGE_NODE(node,
+ "Invalid trace's `uuid` attribute.");
goto error;
}
+ ctx->ctf_tc->is_uuid_set = true;
_SET(set, _TRACE_UUID_SET);
} else if (!strcmp(left, "byte_order")) {
- /* Native byte order is already known at this stage */
+ /* Default byte order is already known at this stage */
if (_IS_SET(set, _TRACE_BYTE_ORDER_SET)) {
- _PERROR_DUP_ATTR("byte_order",
- "trace declaration");
+ _BT_LOGE_DUP_ATTR(node, "byte_order",
+ "trace");
ret = -EPERM;
goto error;
}
+ BT_ASSERT(ctx->ctf_tc->default_byte_order != -1);
_SET(set, _TRACE_BYTE_ORDER_SET);
} else if (!strcmp(left, "packet.header")) {
if (_IS_SET(set, _TRACE_PACKET_HEADER_SET)) {
- _PERROR("%s", "duplicate \"packet.header\" entry in trace declaration");
+ _BT_LOGE_NODE(node,
+ "Duplicate `packet.header` entry in trace.");
ret = -EPERM;
goto error;
}
- ret = visit_type_specifier_list(ctx,
+ ret = visit_field_class_specifier_list(ctx,
_BT_LIST_FIRST_ENTRY(
&node->u.ctf_expression.right,
struct ctf_node, siblings),
- &packet_header_decl);
- if (ret) {
- _PERROR("%s", "cannot create packet header declaration");
- goto error;
- }
-
- assert(packet_header_decl);
- ret = bt_ctf_trace_set_packet_header_type(ctx->trace,
- packet_header_decl);
- BT_PUT(packet_header_decl);
+ &ctx->ctf_tc->packet_header_fc);
if (ret) {
- _PERROR("%s", "cannot set trace declaration's packet header declaration");
+ _BT_LOGE_NODE(node,
+ "Cannot create trace's packet header field class.");
goto error;
}
+ BT_ASSERT(ctx->ctf_tc->packet_header_fc);
_SET(set, _TRACE_PACKET_HEADER_SET);
} else {
- _PWARNING("%s", "unknown attribute \"%s\" in trace declaration");
+ _BT_LOGW_NODE(node,
+ "Unknown attribute in stream class: "
+ "attr-name=\"%s\"", left);
}
g_free(left);
break;
}
default:
- _PERROR("%s", "unknown expression in trace declaration");
+ _BT_LOGE_NODE(node, "Unknown expression in trace.");
ret = -EINVAL;
goto error;
}
error:
g_free(left);
- BT_PUT(packet_header_decl);
-
return ret;
}
node->visited = TRUE;
if (ctx->is_trace_visited) {
- _PERROR("%s", "duplicate \"trace\" block");
+ _BT_LOGE_NODE(node, "Duplicate trace (`trace` block).");
ret = -EEXIST;
goto error;
}
- ret = ctx_push_scope(ctx);
- if (ret) {
- _PERROR("%s", "cannot push scope");
- goto error;
- }
+ _TRY_PUSH_SCOPE_OR_GOTO_ERROR();
bt_list_for_each_entry(iter, decl_list, siblings) {
ret = visit_trace_decl_entry(ctx, iter, &set);
if (ret) {
+ _BT_LOGE_NODE(iter, "Cannot visit trace's entry (`trace` block): "
+ "ret=%d", ret);
ctx_pop_scope(ctx);
goto error;
}
ctx_pop_scope(ctx);
if (!_IS_SET(&set, _TRACE_MAJOR_SET)) {
- _PERROR("%s",
- "missing \"major\" attribute in trace declaration");
+ _BT_LOGE_NODE(node,
+ "Missing `major` attribute in trace (`trace` block).");
ret = -EPERM;
goto error;
}
if (!_IS_SET(&set, _TRACE_MINOR_SET)) {
- _PERROR("%s",
- "missing \"minor\" attribute in trace declaration");
+ _BT_LOGE_NODE(node,
+ "Missing `minor` attribute in trace (`trace` block).");
ret = -EPERM;
goto error;
}
if (!_IS_SET(&set, _TRACE_BYTE_ORDER_SET)) {
- _PERROR("%s", "missing \"byte_order\" attribute in trace declaration");
+ _BT_LOGE_NODE(node,
+ "Missing `byte_order` attribute in trace (`trace` block).");
ret = -EPERM;
goto error;
}
- ctx->is_trace_visited = TRUE;
+ ctx->is_trace_visited = true;
end:
return 0;
&entry_node->u.ctf_expression.right;
if (entry_node->type != NODE_CTF_EXPRESSION) {
- _PERROR("%s", "wrong expression in environment entry");
+ _BT_LOGE_NODE(entry_node,
+ "Wrong expression in environment entry: "
+ "node-type=%d", entry_node->type);
ret = -EPERM;
goto error;
}
left = concatenate_unary_strings(
&entry_node->u.ctf_expression.left);
if (!left) {
- _PERROR("%s", "cannot get environment entry name");
+ _BT_LOGE_NODE(entry_node,
+ "Cannot get environment entry's name.");
ret = -EINVAL;
goto error;
}
char *right = concatenate_unary_strings(right_head);
if (!right) {
- _PERROR("unexpected unary expression for environment entry's value (\"%s\")",
- left);
+ _BT_LOGE_NODE(entry_node,
+ "Unexpected unary expression for environment entry's value: "
+ "name=\"%s\"", left);
ret = -EINVAL;
goto error;
}
- printf_verbose("env.%s = \"%s\"\n", left, right);
- ret = bt_ctf_trace_set_environment_field_string(
- ctx->trace, left, right);
- g_free(right);
-
- if (ret) {
- _PERROR("environment: cannot add entry \"%s\" to trace",
- left);
- goto error;
+ if (strcmp(left, "tracer_name") == 0) {
+ if (strncmp(right, "lttng", 5) == 0) {
+ BT_LOGI("Detected LTTng trace from `%s` environment value: "
+ "tracer-name=\"%s\"",
+ left, right);
+ ctx->is_lttng = true;
+ }
}
+
+ ctf_trace_class_append_env_entry(ctx->ctf_tc,
+ left, CTF_TRACE_CLASS_ENV_ENTRY_TYPE_STR,
+ right, 0);
+ g_free(right);
} else if (is_unary_unsigned(right_head) ||
is_unary_signed(right_head)) {
int64_t v;
ret = get_unary_signed(right_head, &v);
}
if (ret) {
- _PERROR("unexpected unary expression for environment entry's value (\"%s\")",
- left);
+ _BT_LOGE_NODE(entry_node,
+ "Unexpected unary expression for environment entry's value: "
+ "name=\"%s\"", left);
ret = -EINVAL;
goto error;
}
- printf_verbose("env.%s = %" PRId64 "\n", left, v);
- ret = bt_ctf_trace_set_environment_field_integer(
- ctx->trace, left, v);
- if (ret) {
- _PERROR("environment: cannot add entry \"%s\" to trace",
- left);
- goto error;
- }
+ ctf_trace_class_append_env_entry(ctx->ctf_tc,
+ left, CTF_TRACE_CLASS_ENV_ENTRY_TYPE_INT,
+ NULL, v);
} else {
- printf_verbose("%s: environment entry \"%s\" has unknown type\n",
- __func__, left);
+ _BT_LOGW_NODE(entry_node,
+ "Environment entry has unknown type: "
+ "name=\"%s\"", left);
}
g_free(left);
error:
g_free(left);
-
return ret;
}
left = concatenate_unary_strings(
&node->u.ctf_expression.left);
if (!left) {
+ _BT_LOGE_NODE(node,
+ "Cannot concatenate unary strings.");
ret = -EINVAL;
goto error;
}
if (!strcmp(left, "byte_order")) {
- enum bt_ctf_byte_order bo;
+ enum ctf_byte_order bo;
if (_IS_SET(&set, _TRACE_BYTE_ORDER_SET)) {
- _PERROR_DUP_ATTR("byte_order",
- "trace declaration");
+ _BT_LOGE_DUP_ATTR(node, "byte_order",
+ "trace");
ret = -EPERM;
goto error;
}
right_node = _BT_LIST_FIRST_ENTRY(
&node->u.ctf_expression.right,
struct ctf_node, siblings);
- bo = byte_order_from_unary_expr(ctx->efd,
- right_node);
- if (bo == BT_CTF_BYTE_ORDER_UNKNOWN) {
- _PERROR("%s", "unknown \"byte_order\" attribute in trace declaration");
+ bo = byte_order_from_unary_expr(right_node);
+ if (bo == -1) {
+ _BT_LOGE_NODE(node,
+ "Invalid `byte_order` attribute in trace (`trace` block): "
+ "expecting `le`, `be`, or `network`.");
ret = -EINVAL;
goto error;
- } else if (bo == BT_CTF_BYTE_ORDER_NATIVE) {
- _PERROR("%s", "\"byte_order\" attribute cannot be set to \"native\" in trace declaration");
+ } else if (bo == CTF_BYTE_ORDER_DEFAULT) {
+ _BT_LOGE_NODE(node,
+ "Invalid `byte_order` attribute in trace (`trace` block): "
+ "cannot be set to `native` here.");
ret = -EPERM;
goto error;
}
- ret = bt_ctf_trace_set_byte_order(
- ctx->trace, bo);
- if (ret) {
- _PERROR("cannot set trace's byte order (%d)",
- ret);
- goto error;
- }
+ ctx->ctf_tc->default_byte_order = bo;
}
g_free(left);
}
if (!_IS_SET(&set, _TRACE_BYTE_ORDER_SET)) {
- _PERROR("%s", "missing \"byte_order\" attribute in trace declaration");
+ _BT_LOGE_NODE(trace_node,
+ "Missing `byte_order` attribute in trace (`trace` block).");
ret = -EINVAL;
goto error;
}
error:
g_free(left);
-
return ret;
}
static
int visit_clock_decl_entry(struct ctx *ctx, struct ctf_node *entry_node,
- struct bt_ctf_clock_class *clock, int *set)
+ struct ctf_clock_class *clock, int *set, int64_t *offset_seconds,
+ uint64_t *offset_cycles)
{
int ret = 0;
char *left = NULL;
if (entry_node->type != NODE_CTF_EXPRESSION) {
+ _BT_LOGE_NODE(entry_node,
+ "Unexpected node type: node-type=%d",
+ entry_node->type);
ret = -EPERM;
goto error;
}
left = concatenate_unary_strings(&entry_node->u.ctf_expression.left);
if (!left) {
+ _BT_LOGE_NODE(entry_node, "Cannot concatenate unary strings.");
ret = -EINVAL;
goto error;
}
char *right;
if (_IS_SET(set, _CLOCK_NAME_SET)) {
- _PERROR_DUP_ATTR("name", "clock declaration");
+ _BT_LOGE_DUP_ATTR(entry_node, "name", "clock class");
ret = -EPERM;
goto error;
}
right = concatenate_unary_strings(
&entry_node->u.ctf_expression.right);
if (!right) {
- _PERROR("%s", "unexpected unary expression for clock declaration's \"name\" attribute");
+ _BT_LOGE_NODE(entry_node,
+ "Unexpected unary expression for clock class's `name` attribute.");
ret = -EINVAL;
goto error;
}
- ret = bt_ctf_clock_class_set_name(clock, right);
- if (ret) {
- _PERROR("%s", "cannot set clock's name");
- g_free(right);
- goto error;
- }
-
+ g_string_assign(clock->name, right);
g_free(right);
_SET(set, _CLOCK_NAME_SET);
} else if (!strcmp(left, "uuid")) {
- unsigned char uuid[BABELTRACE_UUID_LEN];
+ uint8_t uuid[BABELTRACE_UUID_LEN];
if (_IS_SET(set, _CLOCK_UUID_SET)) {
- _PERROR_DUP_ATTR("uuid", "clock declaration");
+ _BT_LOGE_DUP_ATTR(entry_node, "uuid", "clock class");
ret = -EPERM;
goto error;
}
ret = get_unary_uuid(&entry_node->u.ctf_expression.right, uuid);
if (ret) {
- _PERROR("%s", "invalid clock UUID");
- goto error;
- }
-
- ret = bt_ctf_clock_class_set_uuid(clock, uuid);
- if (ret) {
- _PERROR("%s", "cannot set clock's UUID");
+ _BT_LOGE_NODE(entry_node,
+ "Invalid clock class's `uuid` attribute.");
goto error;
}
+ clock->has_uuid = true;
+ memcpy(&clock->uuid[0], uuid, 16);
_SET(set, _CLOCK_UUID_SET);
} else if (!strcmp(left, "description")) {
char *right;
if (_IS_SET(set, _CLOCK_DESCRIPTION_SET)) {
- _PERROR_DUP_ATTR("description", "clock declaration");
+ _BT_LOGE_DUP_ATTR(entry_node, "description",
+ "clock class");
ret = -EPERM;
goto error;
}
right = concatenate_unary_strings(
&entry_node->u.ctf_expression.right);
if (!right) {
- _PERROR("%s", "unexpected unary expression for clock's \"description\" attribute");
+ _BT_LOGE_NODE(entry_node,
+ "Unexpected unary expression for clock class's `description` attribute.");
ret = -EINVAL;
goto error;
}
- ret = bt_ctf_clock_class_set_description(clock, right);
- if (ret) {
- _PERROR("%s", "cannot set clock's description");
- g_free(right);
- goto error;
- }
-
+ g_string_assign(clock->description, right);
g_free(right);
_SET(set, _CLOCK_DESCRIPTION_SET);
} else if (!strcmp(left, "freq")) {
- uint64_t freq;
+ uint64_t freq = UINT64_C(-1);
if (_IS_SET(set, _CLOCK_FREQ_SET)) {
- _PERROR_DUP_ATTR("freq", "clock declaration");
+ _BT_LOGE_DUP_ATTR(entry_node, "freq", "clock class");
ret = -EPERM;
goto error;
}
ret = get_unary_unsigned(
&entry_node->u.ctf_expression.right, &freq);
if (ret) {
- _PERROR("%s", "unexpected unary expression for clock declaration's \"freq\" attribute");
+ _BT_LOGE_NODE(entry_node,
+ "Unexpected unary expression for clock class's `freq` attribute.");
ret = -EINVAL;
goto error;
}
- ret = bt_ctf_clock_class_set_frequency(clock, freq);
- if (ret) {
- _PERROR("%s", "cannot set clock's frequency");
+ if (freq == UINT64_C(-1) || freq == 0) {
+ _BT_LOGE_NODE(entry_node,
+ "Invalid clock class frequency: freq=%" PRIu64,
+ freq);
+ ret = -EINVAL;
goto error;
}
+ clock->frequency = freq;
_SET(set, _CLOCK_FREQ_SET);
} else if (!strcmp(left, "precision")) {
uint64_t precision;
if (_IS_SET(set, _CLOCK_PRECISION_SET)) {
- _PERROR_DUP_ATTR("precision", "clock declaration");
+ _BT_LOGE_DUP_ATTR(entry_node, "precision",
+ "clock class");
ret = -EPERM;
goto error;
}
ret = get_unary_unsigned(
&entry_node->u.ctf_expression.right, &precision);
if (ret) {
- _PERROR("%s", "unexpected unary expression for clock declaration's \"precision\" attribute");
+ _BT_LOGE_NODE(entry_node,
+ "Unexpected unary expression for clock class's `precision` attribute.");
ret = -EINVAL;
goto error;
}
- ret = bt_ctf_clock_class_set_precision(clock, precision);
- if (ret) {
- _PERROR("%s", "cannot set clock's precision");
- goto error;
- }
-
+ clock->precision = precision;
_SET(set, _CLOCK_PRECISION_SET);
} else if (!strcmp(left, "offset_s")) {
- uint64_t offset_s;
-
if (_IS_SET(set, _CLOCK_OFFSET_S_SET)) {
- _PERROR_DUP_ATTR("offset_s", "clock declaration");
+ _BT_LOGE_DUP_ATTR(entry_node, "offset_s",
+ "clock class");
ret = -EPERM;
goto error;
}
- ret = get_unary_unsigned(
- &entry_node->u.ctf_expression.right, &offset_s);
+ ret = get_unary_signed(
+ &entry_node->u.ctf_expression.right, offset_seconds);
if (ret) {
- _PERROR("%s", "unexpected unary expression for clock declaration's \"offset_s\" attribute");
+ _BT_LOGE_NODE(entry_node,
+ "Unexpected unary expression for clock class's `offset_s` attribute.");
ret = -EINVAL;
goto error;
}
- ret = bt_ctf_clock_class_set_offset_s(clock, offset_s);
- if (ret) {
- _PERROR("%s", "cannot set clock's offset in seconds");
- goto error;
- }
-
_SET(set, _CLOCK_OFFSET_S_SET);
} else if (!strcmp(left, "offset")) {
- uint64_t offset;
-
if (_IS_SET(set, _CLOCK_OFFSET_SET)) {
- _PERROR_DUP_ATTR("offset", "clock declaration");
+ _BT_LOGE_DUP_ATTR(entry_node, "offset", "clock class");
ret = -EPERM;
goto error;
}
ret = get_unary_unsigned(
- &entry_node->u.ctf_expression.right, &offset);
+ &entry_node->u.ctf_expression.right, offset_cycles);
if (ret) {
- _PERROR("%s", "unexpected unary expression for clock declaration's \"offset\" attribute");
+ _BT_LOGE_NODE(entry_node,
+ "Unexpected unary expression for clock class's `offset` attribute.");
ret = -EINVAL;
goto error;
}
- ret = bt_ctf_clock_class_set_offset_cycles(clock, offset);
- if (ret) {
- _PERROR("%s", "cannot set clock's offset in cycles");
- goto error;
- }
-
_SET(set, _CLOCK_OFFSET_SET);
} else if (!strcmp(left, "absolute")) {
struct ctf_node *right;
if (_IS_SET(set, _CLOCK_ABSOLUTE_SET)) {
- _PERROR_DUP_ATTR("absolute", "clock declaration");
+ _BT_LOGE_DUP_ATTR(entry_node, "absolute",
+ "clock class");
ret = -EPERM;
goto error;
}
right = _BT_LIST_FIRST_ENTRY(
&entry_node->u.ctf_expression.right,
struct ctf_node, siblings);
- ret = get_boolean(ctx->efd, right);
+ ret = get_boolean(right);
if (ret < 0) {
- _PERROR("%s", "unexpected unary expression for clock declaration's \"absolute\" attribute");
+ _BT_LOGE_NODE(entry_node,
+ "Unexpected unary expression for clock class's `absolute` attribute.");
ret = -EINVAL;
goto error;
}
- ret = bt_ctf_clock_class_set_is_absolute(clock, ret);
- if (ret) {
- _PERROR("%s", "cannot set clock's absolute option");
- goto error;
- }
-
+ clock->is_absolute = ret;
_SET(set, _CLOCK_ABSOLUTE_SET);
} else {
- _PWARNING("unknown attribute \"%s\" in clock declaration",
+ _BT_LOGW_NODE(entry_node,
+ "Unknown attribute in clock class: attr-name=\"%s\"",
left);
}
g_free(left);
left = NULL;
-
return 0;
error:
g_free(left);
-
return ret;
}
+static inline
+uint64_t cycles_from_ns(uint64_t frequency, uint64_t ns)
+{
+ uint64_t cycles;
+
+ /* 1GHz */
+ if (frequency == UINT64_C(1000000000)) {
+ cycles = ns;
+ } else {
+ cycles = (uint64_t) (((double) ns * (double) frequency) / 1e9);
+ }
+
+ return cycles;
+}
+
+static
+void calibrate_clock_class_offsets(int64_t *offset_seconds,
+ uint64_t *offset_cycles, uint64_t freq)
+{
+ if (*offset_cycles >= freq) {
+ const uint64_t s_in_offset_cycles = *offset_cycles / freq;
+
+ *offset_seconds += (int64_t) s_in_offset_cycles;
+ *offset_cycles -= (s_in_offset_cycles * freq);
+ }
+}
+
+static
+void apply_clock_class_offset(struct ctx *ctx,
+ struct ctf_clock_class *clock)
+{
+ uint64_t freq;
+ int64_t offset_s_to_apply = ctx->decoder_config.clock_class_offset_s;
+ uint64_t offset_ns_to_apply;
+ int64_t cur_offset_s;
+ uint64_t cur_offset_cycles;
+
+ if (ctx->decoder_config.clock_class_offset_s == 0 &&
+ ctx->decoder_config.clock_class_offset_ns == 0) {
+ goto end;
+ }
+
+ /* Transfer nanoseconds to seconds as much as possible */
+ if (ctx->decoder_config.clock_class_offset_ns < 0) {
+ const int64_t abs_ns = -ctx->decoder_config.clock_class_offset_ns;
+ const int64_t abs_extra_s = abs_ns / INT64_C(1000000000) + 1;
+ const int64_t extra_s = -abs_extra_s;
+ const int64_t offset_ns = ctx->decoder_config.clock_class_offset_ns -
+ (extra_s * INT64_C(1000000000));
+
+ BT_ASSERT(offset_ns > 0);
+ offset_ns_to_apply = (uint64_t) offset_ns;
+ offset_s_to_apply += extra_s;
+ } else {
+ const int64_t extra_s = ctx->decoder_config.clock_class_offset_ns /
+ INT64_C(1000000000);
+ const int64_t offset_ns = ctx->decoder_config.clock_class_offset_ns -
+ (extra_s * INT64_C(1000000000));
+
+ BT_ASSERT(offset_ns >= 0);
+ offset_ns_to_apply = (uint64_t) offset_ns;
+ offset_s_to_apply += extra_s;
+ }
+
+ freq = clock->frequency;
+ cur_offset_s = clock->offset_seconds;
+ cur_offset_cycles = clock->offset_cycles;
+
+ /* Apply offsets */
+ cur_offset_s += offset_s_to_apply;
+ cur_offset_cycles += cycles_from_ns(freq, offset_ns_to_apply);
+
+ /*
+ * Recalibrate offsets because the part in cycles can be greater
+ * than the frequency at this point.
+ */
+ calibrate_clock_class_offsets(&cur_offset_s, &cur_offset_cycles, freq);
+
+ /* Set final offsets */
+ clock->offset_seconds = cur_offset_s;
+ clock->offset_cycles = cur_offset_cycles;
+
+end:
+ return;
+}
+
static
int visit_clock_decl(struct ctx *ctx, struct ctf_node *clock_node)
{
int ret = 0;
int set = 0;
- struct bt_ctf_clock_class *clock;
+ struct ctf_clock_class *clock;
struct ctf_node *entry_node;
struct bt_list_head *decl_list = &clock_node->u.clock.declaration_list;
+ const char *clock_class_name;
+ int64_t offset_seconds = 0;
+ uint64_t offset_cycles = 0;
+ uint64_t freq;
if (clock_node->visited) {
return 0;
}
clock_node->visited = TRUE;
- clock = bt_ctf_clock_class_create(NULL);
+
+ /* CTF 1.8's default frequency for a clock class is 1 GHz */
+ clock = ctf_clock_class_create();
if (!clock) {
- _PERROR("%s", "cannot create clock");
+ _BT_LOGE_NODE(clock_node,
+ "Cannot create default clock class.");
ret = -ENOMEM;
- goto error;
+ goto end;
}
bt_list_for_each_entry(entry_node, decl_list, siblings) {
- ret = visit_clock_decl_entry(ctx, entry_node, clock, &set);
+ ret = visit_clock_decl_entry(ctx, entry_node, clock, &set,
+ &offset_seconds, &offset_cycles);
if (ret) {
- goto error;
+ _BT_LOGE_NODE(entry_node,
+ "Cannot visit clock class's entry: ret=%d",
+ ret);
+ goto end;
}
}
if (!_IS_SET(&set, _CLOCK_NAME_SET)) {
- _PERROR("%s",
- "missing \"name\" attribute in clock declaration");
+ _BT_LOGE_NODE(clock_node,
+ "Missing `name` attribute in clock class.");
ret = -EPERM;
- goto error;
+ goto end;
}
- if (bt_ctf_trace_get_clock_class_count(ctx->trace) != 0) {
- _PERROR("%s", "only CTF traces with a single clock declaration are supported as of this version");
- ret = -EINVAL;
- goto error;
+ clock_class_name = clock->name->str;
+ BT_ASSERT(clock_class_name);
+ if (ctx->is_lttng && strcmp(clock_class_name, "monotonic") == 0) {
+ /*
+ * Old versions of LTTng forgot to set its clock class
+ * as absolute, even if it is. This is important because
+ * it's a condition to be able to sort messages
+ * from different sources.
+ */
+ clock->is_absolute = true;
}
- ret = bt_ctf_trace_add_clock_class(ctx->trace, clock);
- if (ret) {
- _PERROR("%s", "cannot add clock to trace");
- goto error;
- }
+ /*
+ * Adjust offsets so that the part in cycles is less than the
+ * frequency (move to the part in seconds).
+ */
+ freq = clock->frequency;
+ calibrate_clock_class_offsets(&offset_seconds, &offset_cycles, freq);
+ BT_ASSERT(offset_cycles < clock->frequency);
+ clock->offset_seconds = offset_seconds;
+ clock->offset_cycles = offset_cycles;
+ apply_clock_class_offset(ctx, clock);
+ g_ptr_array_add(ctx->ctf_tc->clock_classes, clock);
+ clock = NULL;
-error:
- BT_PUT(clock);
+end:
+ if (clock) {
+ ctf_clock_class_destroy(clock);
+ }
return ret;
}
switch (root_decl_node->type) {
case NODE_TYPEDEF:
- ret = visit_typedef(ctx,
- root_decl_node->u._typedef.type_specifier_list,
- &root_decl_node->u._typedef.type_declarators);
+ ret = visit_field_class_def(ctx,
+ root_decl_node->u.field_class_def.field_class_specifier_list,
+ &root_decl_node->u.field_class_def.field_class_declarators);
if (ret) {
- _PERROR("%s", "cannot add typedef in root scope");
+ _BT_LOGE_NODE(root_decl_node,
+ "Cannot add field class found in root scope.");
goto end;
}
break;
case NODE_TYPEALIAS:
- ret = visit_typealias(ctx, root_decl_node->u.typealias.target,
- root_decl_node->u.typealias.alias);
+ ret = visit_field_class_alias(ctx, root_decl_node->u.field_class_alias.target,
+ root_decl_node->u.field_class_alias.alias);
if (ret) {
- _PERROR("%s", "cannot add typealias in root scope");
+ _BT_LOGE_NODE(root_decl_node,
+ "Cannot add field class alias found in root scope.");
goto end;
}
break;
case NODE_TYPE_SPECIFIER_LIST:
{
- _BT_CTF_FIELD_TYPE_INIT(decl);
+ struct ctf_field_class *decl = NULL;
/*
- * Just add the type specifier to the root
+ * Just add the field class specifier to the root
* declaration scope. Put local reference.
*/
- ret = visit_type_specifier_list(ctx, root_decl_node, &decl);
+ ret = visit_field_class_specifier_list(ctx, root_decl_node, &decl);
if (ret) {
- assert(!decl);
+ _BT_LOGE_NODE(root_decl_node,
+ "Cannot visit root scope's field class: "
+ "ret=%d", ret);
+ BT_ASSERT(!decl);
goto end;
}
- BT_PUT(decl);
+ ctf_field_class_destroy(decl);
+ decl = NULL;
break;
}
default:
+ _BT_LOGE_NODE(root_decl_node,
+ "Unexpected node type: node-type=%d",
+ root_decl_node->type);
ret = -EPERM;
goto end;
}
return ret;
}
-static
-int add_stream_classes_to_trace(struct ctx *ctx)
+BT_HIDDEN
+struct ctf_visitor_generate_ir *ctf_visitor_generate_ir_create(
+ bt_self_component_source *self_comp,
+ const struct ctf_metadata_decoder_config *decoder_config)
{
- int ret;
- GHashTableIter iter;
- gpointer key, stream_class;
-
- g_hash_table_iter_init(&iter, ctx->stream_classes);
+ struct ctx *ctx = NULL;
- while (g_hash_table_iter_next(&iter, &key, &stream_class)) {
- ret = bt_ctf_trace_add_stream_class(ctx->trace,
- stream_class);
- if (ret) {
- int64_t id = bt_ctf_stream_class_get_id(stream_class);
- _PERROR("cannot add stream class %" PRId64 " to trace",
- id);
- goto end;
- }
+ /* Create visitor's context */
+ ctx = ctx_create(self_comp, decoder_config);
+ if (!ctx) {
+ BT_LOGE_STR("Cannot create visitor's context.");
+ goto error;
}
+ goto end;
+
+error:
+ ctx_destroy(ctx);
+ ctx = NULL;
+
end:
- return ret;
+ return (void *) ctx;
}
-int ctf_visitor_generate_ir(FILE *efd, struct ctf_node *node,
- struct bt_ctf_trace **trace)
+BT_HIDDEN
+void ctf_visitor_generate_ir_destroy(struct ctf_visitor_generate_ir *visitor)
{
- int ret = 0;
- struct ctx *ctx = NULL;
+ ctx_destroy((void *) visitor);
+}
- printf_verbose("CTF visitor: AST -> CTF IR...\n");
+BT_HIDDEN
+bt_trace_class *ctf_visitor_generate_ir_get_ir_trace_class(
+ struct ctf_visitor_generate_ir *visitor)
+{
+ struct ctx *ctx = (void *) visitor;
- *trace = bt_ctf_trace_create();
- if (!*trace) {
- _FPERROR(efd, "%s", "cannot create trace");
- ret = -ENOMEM;
- goto error;
- }
+ BT_ASSERT(ctx);
- /* Set packet header to NULL to override the default one */
- ret = bt_ctf_trace_set_packet_header_type(*trace, NULL);
- if (ret) {
- _FPERROR(efd,
- "%s",
- "cannot set initial, empty packet header structure");
- goto error;
+ if (ctx->trace_class) {
+ bt_trace_class_get_ref(ctx->trace_class);
}
- ctx = ctx_create(*trace, efd);
- if (!ctx) {
- _FPERROR(efd, "%s", "cannot create visitor context");
- ret = -ENOMEM;
- goto error;
- }
+ return ctx->trace_class;
+}
+
+BT_HIDDEN
+struct ctf_trace_class *ctf_visitor_generate_ir_borrow_ctf_trace_class(
+ struct ctf_visitor_generate_ir *visitor)
+{
+ struct ctx *ctx = (void *) visitor;
+
+ BT_ASSERT(ctx);
+ BT_ASSERT(ctx->ctf_tc);
+ return ctx->ctf_tc;
+}
+
+BT_HIDDEN
+int ctf_visitor_generate_ir_visit_node(struct ctf_visitor_generate_ir *visitor,
+ struct ctf_node *node)
+{
+ int ret = 0;
+ struct ctx *ctx = (void *) visitor;
+
+ BT_LOGI_STR("Visiting metadata's AST to generate CTF IR objects.");
switch (node->type) {
case NODE_ROOT:
{
struct ctf_node *iter;
- int got_trace_decl = FALSE;
- int found_callsite = FALSE;
+ bool got_trace_decl = false;
/*
- * Find trace declaration's byte order first (for early
- * type aliases).
+ * The first thing we need is the native byte order of
+ * the trace block, because early class aliases can have
+ * a `byte_order` attribute set to `native`. If we don't
+ * have the native byte order yet, and we don't have any
+ * trace block yet, then fail with EINCOMPLETE.
*/
- bt_list_for_each_entry(iter, &node->u.root.trace, siblings) {
- if (got_trace_decl) {
- _PERROR("%s", "duplicate trace declaration");
- goto error;
- }
+ if (ctx->ctf_tc->default_byte_order == -1) {
+ bt_list_for_each_entry(iter, &node->u.root.trace, siblings) {
+ if (got_trace_decl) {
+ _BT_LOGE_NODE(node,
+ "Duplicate trace (`trace` block).");
+ ret = -1;
+ goto end;
+ }
- ret = set_trace_byte_order(ctx, iter);
- if (ret) {
- _PERROR("cannot set trace's byte order (%d)",
- ret);
- goto error;
+ ret = set_trace_byte_order(ctx, iter);
+ if (ret) {
+ _BT_LOGE_NODE(node,
+ "Cannot set trace's native byte order: "
+ "ret=%d", ret);
+ goto end;
+ }
+
+ got_trace_decl = true;
}
- got_trace_decl = TRUE;
+ if (!got_trace_decl) {
+ BT_LOGD_STR("Incomplete AST: need trace (`trace` block).");
+ ret = -EINCOMPLETE;
+ goto end;
+ }
}
- if (!got_trace_decl) {
- _PERROR("no trace declaration found (%d)", ret);
- ret = -EPERM;
- goto error;
+ BT_ASSERT(ctx->ctf_tc->default_byte_order == CTF_BYTE_ORDER_LITTLE ||
+ ctx->ctf_tc->default_byte_order == CTF_BYTE_ORDER_BIG);
+ BT_ASSERT(ctx->current_scope &&
+ ctx->current_scope->parent_scope == NULL);
+
+ /* Environment */
+ bt_list_for_each_entry(iter, &node->u.root.env, siblings) {
+ ret = visit_env(ctx, iter);
+ if (ret) {
+ _BT_LOGE_NODE(iter,
+ "Cannot visit trace's environment (`env` block) entry: "
+ "ret=%d", ret);
+ goto end;
+ }
}
+ BT_ASSERT(ctx->current_scope &&
+ ctx->current_scope->parent_scope == NULL);
+
/*
- * Visit clocks first since any early integer can be mapped
- * to one.
+ * Visit clock blocks.
*/
bt_list_for_each_entry(iter, &node->u.root.clock, siblings) {
ret = visit_clock_decl(ctx, iter);
if (ret) {
- _PERROR("error while visiting clock declaration (%d)",
+ _BT_LOGE_NODE(iter,
+ "Cannot visit clock class: ret=%d",
ret);
- goto error;
+ goto end;
}
}
+ BT_ASSERT(ctx->current_scope &&
+ ctx->current_scope->parent_scope == NULL);
+
/*
* Visit root declarations next, as they can be used by any
* following entity.
siblings) {
ret = visit_root_decl(ctx, iter);
if (ret) {
- _PERROR("error while visiting root declaration (%d)",
+ _BT_LOGE_NODE(iter,
+ "Cannot visit root entry: ret=%d",
ret);
- goto error;
+ goto end;
}
}
- /* Callsite are not supported */
- bt_list_for_each_entry(iter, &node->u.root.callsite, siblings) {
- found_callsite = TRUE;
- break;
- }
+ BT_ASSERT(ctx->current_scope &&
+ ctx->current_scope->parent_scope == NULL);
- if (found_callsite) {
- _PWARNING("%s", "\"callsite\" blocks are not supported as of this version");
+ /* Callsite blocks are not supported */
+ bt_list_for_each_entry(iter, &node->u.root.callsite, siblings) {
+ _BT_LOGW_NODE(iter,
+ "\"callsite\" blocks are not supported as of this version.");
}
- /* Environment */
- bt_list_for_each_entry(iter, &node->u.root.env, siblings) {
- ret = visit_env(ctx, iter);
- if (ret) {
- _PERROR("error while visiting environment block (%d)",
- ret);
- goto error;
- }
- }
+ BT_ASSERT(ctx->current_scope &&
+ ctx->current_scope->parent_scope == NULL);
/* Trace */
bt_list_for_each_entry(iter, &node->u.root.trace, siblings) {
ret = visit_trace_decl(ctx, iter);
if (ret) {
- _PERROR("%s", "error while visiting trace declaration");
- goto error;
+ _BT_LOGE_NODE(iter,
+ "Cannot visit trace (`trace` block): "
+ "ret=%d", ret);
+ goto end;
}
}
+ BT_ASSERT(ctx->current_scope &&
+ ctx->current_scope->parent_scope == NULL);
+
/* Streams */
bt_list_for_each_entry(iter, &node->u.root.stream, siblings) {
ret = visit_stream_decl(ctx, iter);
if (ret) {
- _PERROR("%s", "error while visiting stream declaration");
- goto error;
+ _BT_LOGE_NODE(iter,
+ "Cannot visit stream class: ret=%d",
+ ret);
+ goto end;
}
}
+ BT_ASSERT(ctx->current_scope &&
+ ctx->current_scope->parent_scope == NULL);
+
/* Events */
bt_list_for_each_entry(iter, &node->u.root.event, siblings) {
ret = visit_event_decl(ctx, iter);
if (ret) {
- _PERROR("%s", "error while visiting event declaration");
- goto error;
+ _BT_LOGE_NODE(iter,
+ "Cannot visit event class: ret=%d",
+ ret);
+ goto end;
}
}
+
+ BT_ASSERT(ctx->current_scope &&
+ ctx->current_scope->parent_scope == NULL);
break;
}
- case NODE_UNKNOWN:
default:
- _PERROR("unknown node type: %d", (int) node->type);
+ _BT_LOGE_NODE(node,
+ "Unexpected node type: node-type=%d",
+ node->type);
ret = -EINVAL;
- goto error;
+ goto end;
}
- /* Add stream classes to trace now */
- ret = add_stream_classes_to_trace(ctx);
+ /* Update default clock classes */
+ ret = ctf_trace_class_update_default_clock_classes(ctx->ctf_tc);
if (ret) {
- _PERROR("%s", "cannot add stream classes to trace");
+ ret = -EINVAL;
+ goto end;
}
- ctx_destroy(ctx);
- printf_verbose("done!\n");
+ /* Update trace class meanings */
+ ret = ctf_trace_class_update_meanings(ctx->ctf_tc);
+ if (ret) {
+ ret = -EINVAL;
+ goto end;
+ }
- return ret;
+ /* Update text arrays and sequences */
+ ret = ctf_trace_class_update_text_array_sequence(ctx->ctf_tc);
+ if (ret) {
+ ret = -EINVAL;
+ goto end;
+ }
-error:
- ctx_destroy(ctx);
- BT_PUT(*trace);
+ /* Resolve sequence lengths and variant tags */
+ ret = ctf_trace_class_resolve_field_classes(ctx->ctf_tc);
+ if (ret) {
+ ret = -EINVAL;
+ goto end;
+ }
+
+ if (ctx->trace_class) {
+ /*
+ * Update "in IR" for field classes.
+ *
+ * If we have no IR trace class, then we'll have no way
+ * to create IR fields anyway, so we leave all the
+ * `in_ir` members false.
+ */
+ ret = ctf_trace_class_update_in_ir(ctx->ctf_tc);
+ if (ret) {
+ ret = -EINVAL;
+ goto end;
+ }
+ }
+
+ /* Update saved value indexes */
+ ret = ctf_trace_class_update_value_storing_indexes(ctx->ctf_tc);
+ if (ret) {
+ ret = -EINVAL;
+ goto end;
+ }
+
+ /* Validate what we have so far */
+ ret = ctf_trace_class_validate(ctx->ctf_tc);
+ if (ret) {
+ ret = -EINVAL;
+ goto end;
+ }
+
+ if (ctx->trace_class) {
+ /* Copy new CTF metadata -> new IR metadata */
+ ret = ctf_trace_class_translate(ctx->trace_class, ctx->ctf_tc);
+ if (ret) {
+ ret = -EINVAL;
+ goto end;
+ }
+ }
+end:
return ret;
}