#include <inttypes.h>
#include <endian.h>
#include <errno.h>
-#include <babeltrace/babeltrace.h>
+#include <babeltrace/babeltrace-internal.h>
#include <babeltrace/list.h>
#include <babeltrace/types.h>
#include <babeltrace/ctf/metadata.h>
return 0;
}
+static
+int get_unary_signed(struct cds_list_head *head, int64_t *value)
+{
+ struct ctf_node *node;
+ int i = 0;
+
+ cds_list_for_each_entry(node, head, siblings) {
+ assert(node->type == NODE_UNARY_EXPRESSION);
+ assert(node->u.unary_expression.type == UNARY_UNSIGNED_CONSTANT);
+ assert(node->u.unary_expression.link == UNARY_LINK_UNKNOWN);
+ assert(i == 0);
+ *value = node->u.unary_expression.u.signed_constant;
+ i++;
+ }
+ return 0;
+}
+
static
int get_unary_uuid(struct cds_list_head *head, uuid_t *uuid)
{
struct ctf_trace *trace)
{
struct ctf_node *expression;
- uint64_t alignment = 1, size;
+ uint64_t alignment = 1, size = 0;
int byte_order = trace->byte_order;
int signedness = 0;
int has_alignment = 0, has_size = 0;
return NULL;
}
g_free(s_right);
+ } else if (!strcmp(left->u.unary_expression.u.string, "map")) {
+ char *s_right;
+
+ if (right->u.unary_expression.type != UNARY_STRING) {
+ fprintf(fd, "[error] %s: map: expecting identifier\n",
+ __func__);
+ return NULL;
+ }
+ s_right = concatenate_unary_strings(&expression->u.ctf_expression.right);
+ if (!s_right) {
+ fprintf(fd, "[error] %s: unexpected unary expression for integer map\n", __func__);
+ g_free(s_right);
+ return NULL;
+ }
+ /* TODO: lookup */
+
} else {
- fprintf(fd, "[error] %s: unknown attribute name %s\n",
+ fprintf(fd, "[warning] %s: unknown attribute name %s\n",
__func__, left->u.unary_expression.u.string);
- return NULL;
+ /* Fall-through after warning */
}
}
if (!has_size) {
}
has_alignment = 1;
} else {
- fprintf(fd, "[error] %s: unknown attribute name %s\n",
+ fprintf(fd, "[warning] %s: unknown attribute name %s\n",
__func__, left->u.unary_expression.u.string);
- return NULL;
+ /* Fall-through after warning */
}
}
if (!has_mant_dig) {
}
encoding_c = right->u.unary_expression.u.string;
} else {
- fprintf(fd, "[error] %s: unknown attribute name %s\n",
+ fprintf(fd, "[warning] %s: unknown attribute name %s\n",
__func__, left->u.unary_expression.u.string);
- return NULL;
+ /* Fall-through after warning */
}
}
if (encoding_c && !strcmp(encoding_c, "ASCII"))
goto error;
}
event->fields_decl = container_of(declaration, struct declaration_struct, p);
+ } else if (!strcmp(left, "loglevel.identifier")) {
+ char *right;
+
+ if (CTF_EVENT_FIELD_IS_SET(event, loglevel_identifier)) {
+ fprintf(fd, "[error] %s: identifier already declared in event declaration\n", __func__);
+ ret = -EPERM;
+ goto error;
+ }
+ right = concatenate_unary_strings(&node->u.ctf_expression.right);
+ if (!right) {
+ fprintf(fd, "[error] %s: unexpected unary expression for event identifier\n", __func__);
+ ret = -EINVAL;
+ goto error;
+ }
+ event->loglevel_identifier = g_quark_from_string(right);
+ g_free(right);
+ CTF_EVENT_SET_FIELD(event, loglevel_identifier);
+ } else if (!strcmp(left, "loglevel.value")) {
+ if (CTF_EVENT_FIELD_IS_SET(event, loglevel_value)) {
+ fprintf(fd, "[error] %s: loglevel value already declared in event declaration\n", __func__);
+ ret = -EPERM;
+ goto error;
+ }
+ ret = get_unary_signed(&node->u.ctf_expression.right, &event->loglevel_value);
+ if (ret) {
+ fprintf(fd, "[error] %s: unexpected unary expression for event loglevel value\n", __func__);
+ ret = -EINVAL;
+ goto error;
+ }
+ CTF_EVENT_SET_FIELD(event, loglevel_value);
} else {
- fprintf(fd, "[error] %s: attribute \"%s\" is unknown in event declaration.\n", __func__, left);
- ret = -EINVAL;
- goto error;
+ fprintf(fd, "[warning] %s: attribute \"%s\" is unknown in event declaration.\n", __func__, left);
+ /* Fall-through after warning */
}
error:
g_free(left);
}
stream->packet_context_decl = container_of(declaration, struct declaration_struct, p);
} else {
- fprintf(fd, "[error] %s: attribute \"%s\" is unknown in stream declaration.\n", __func__, left);
- ret = -EINVAL;
- goto error;
+ fprintf(fd, "[warning] %s: attribute \"%s\" is unknown in stream declaration.\n", __func__, left);
+ /* Fall-through after warning */
}
error:
if (trace->streams->len <= stream->stream_id)
g_ptr_array_set_size(trace->streams, stream->stream_id + 1);
g_ptr_array_index(trace->streams, stream->stream_id) = stream;
+ stream->trace = trace;
return 0;
}
trace->packet_header_decl = container_of(declaration, struct declaration_struct, p);
} else {
- fprintf(fd, "[error] %s: attribute \"%s\" is unknown in trace declaration.\n", __func__, left);
- ret = -EINVAL;
- goto error;
+ fprintf(fd, "[warning] %s: attribute \"%s\" is unknown in trace declaration.\n", __func__, left);
}
error:
int ret = 0;
struct ctf_node *iter;
-restart:
if (trace->declaration_scope)
return -EEXIST;
trace->declaration_scope = new_declaration_scope(trace->root_declaration_scope);
return 0;
error:
- if (trace->packet_header_decl)
+ if (trace->packet_header_decl) {
declaration_unref(&trace->packet_header_decl->p);
+ trace->packet_header_decl = NULL;
+ }
g_ptr_array_free(trace->streams, TRUE);
free_declaration_scope(trace->declaration_scope);
trace->declaration_scope = NULL;
- /* byte order changed while creating types, retry. */
- if (ret == -EINTR) {
- goto restart;
+ return ret;
+}
+
+static
+int ctf_clock_declaration_visit(FILE *fd, int depth, struct ctf_node *node,
+ struct ctf_clock *clock, struct ctf_trace *trace)
+{
+ int ret = 0;
+
+ switch (node->type) {
+ case NODE_CTF_EXPRESSION:
+ {
+ char *left;
+
+ left = concatenate_unary_strings(&node->u.ctf_expression.left);
+ if (!strcmp(left, "name")) {
+ char *right;
+
+ if (CTF_CLOCK_FIELD_IS_SET(clock, name)) {
+ fprintf(fd, "[error] %s: name already declared in clock declaration\n", __func__);
+ ret = -EPERM;
+ goto error;
+ }
+ right = concatenate_unary_strings(&node->u.ctf_expression.right);
+ if (!right) {
+ fprintf(fd, "[error] %s: unexpected unary expression for clock name\n", __func__);
+ ret = -EINVAL;
+ goto error;
+ }
+ clock->name = g_quark_from_string(right);
+ g_free(right);
+ CTF_EVENT_SET_FIELD(clock, name);
+ } else if (!strcmp(left, "uuid")) {
+ char *right;
+
+ if (clock->uuid) {
+ fprintf(fd, "[error] %s: uuid already declared in clock declaration\n", __func__);
+ ret = -EPERM;
+ goto error;
+ }
+ right = concatenate_unary_strings(&node->u.ctf_expression.right);
+ if (!right) {
+ fprintf(fd, "[error] %s: unexpected unary expression for clock uuid\n", __func__);
+ ret = -EINVAL;
+ goto error;
+ }
+ clock->uuid = g_quark_from_string(right);
+ g_free(right);
+ } else if (!strcmp(left, "description")) {
+ char *right;
+
+ if (clock->description) {
+ fprintf(fd, "[warning] %s: duplicated clock description\n", __func__);
+ goto error; /* ret is 0, so not an actual error, just warn. */
+ }
+ right = concatenate_unary_strings(&node->u.ctf_expression.right);
+ if (!right) {
+ fprintf(fd, "[warning] %s: unexpected unary expression for clock description\n", __func__);
+ goto error; /* ret is 0, so not an actual error, just warn. */
+ }
+ clock->description = right;
+ } else if (!strcmp(left, "freq")) {
+ if (clock->freq) {
+ fprintf(fd, "[error] %s: freq already declared in clock declaration\n", __func__);
+ ret = -EPERM;
+ goto error;
+ }
+ ret = get_unary_unsigned(&node->u.ctf_expression.right, &clock->freq);
+ if (ret) {
+ fprintf(fd, "[error] %s: unexpected unary expression for clock freq\n", __func__);
+ ret = -EINVAL;
+ goto error;
+ }
+ } else if (!strcmp(left, "precision")) {
+ if (clock->precision) {
+ fprintf(fd, "[error] %s: precision already declared in clock declaration\n", __func__);
+ ret = -EPERM;
+ goto error;
+ }
+ ret = get_unary_unsigned(&node->u.ctf_expression.right, &clock->precision);
+ if (ret) {
+ fprintf(fd, "[error] %s: unexpected unary expression for clock precision\n", __func__);
+ ret = -EINVAL;
+ goto error;
+ }
+ } else if (!strcmp(left, "offset_s")) {
+ if (clock->offset_s) {
+ fprintf(fd, "[error] %s: offset_s already declared in clock declaration\n", __func__);
+ ret = -EPERM;
+ goto error;
+ }
+ ret = get_unary_unsigned(&node->u.ctf_expression.right, &clock->offset_s);
+ if (ret) {
+ fprintf(fd, "[error] %s: unexpected unary expression for clock offset_s\n", __func__);
+ ret = -EINVAL;
+ goto error;
+ }
+ } else if (!strcmp(left, "offset")) {
+ if (clock->offset) {
+ fprintf(fd, "[error] %s: offset already declared in clock declaration\n", __func__);
+ ret = -EPERM;
+ goto error;
+ }
+ ret = get_unary_unsigned(&node->u.ctf_expression.right, &clock->offset);
+ if (ret) {
+ fprintf(fd, "[error] %s: unexpected unary expression for clock offset\n", __func__);
+ ret = -EINVAL;
+ goto error;
+ }
+ } else {
+ fprintf(fd, "[warning] %s: attribute \"%s\" is unknown in clock declaration.\n", __func__, left);
+ }
+
+error:
+ g_free(left);
+ break;
+ }
+ default:
+ return -EPERM;
+ /* TODO: declaration specifier should be added. */
+ }
+
+ return ret;
+}
+
+static
+int ctf_clock_visit(FILE *fd, int depth, struct ctf_node *node, struct ctf_trace *trace)
+{
+ int ret = 0;
+ struct ctf_node *iter;
+ struct ctf_clock *clock;
+
+ clock = g_new0(struct ctf_clock, 1);
+ cds_list_for_each_entry(iter, &node->u.clock.declaration_list, siblings) {
+ ret = ctf_clock_declaration_visit(fd, depth + 1, iter, clock, trace);
+ if (ret)
+ goto error;
+ }
+ if (!CTF_CLOCK_FIELD_IS_SET(clock, name)) {
+ ret = -EPERM;
+ fprintf(fd, "[error] %s: missing namefield in clock declaration\n", __func__);
+ goto error;
}
+ g_hash_table_insert(trace->clocks, (gpointer) (unsigned long) clock->name, clock);
+ return 0;
+
+error:
+ g_free(clock->description);
+ g_free(clock);
return ret;
}
+static
+void clock_free(gpointer data)
+{
+ struct ctf_clock *clock = data;
+
+ g_free(clock->description);
+ g_free(clock);
+}
+
static
int ctf_root_declaration_visit(FILE *fd, int depth, struct ctf_node *node, struct ctf_trace *trace)
{
return 0;
}
+/* TODO: missing metadata "destroy" (memory leak) */
int ctf_visitor_construct_metadata(FILE *fd, int depth, struct ctf_node *node,
struct ctf_trace *trace, int byte_order)
{
struct ctf_node *iter;
printf_verbose("CTF visitor: metadata construction... ");
- trace->root_declaration_scope = new_declaration_scope(NULL);
trace->byte_order = byte_order;
+ trace->clocks = g_hash_table_new_full(g_direct_hash, g_direct_equal,
+ NULL, clock_free);
+
+retry:
+ trace->root_declaration_scope = new_declaration_scope(NULL);
switch (node->type) {
case NODE_ROOT:
}
cds_list_for_each_entry(iter, &node->u.root.trace, siblings) {
ret = ctf_trace_visit(fd, depth + 1, iter, trace);
+ if (ret == -EINTR) {
+ free_declaration_scope(trace->root_declaration_scope);
+ /*
+ * Need to restart creation of type
+ * definitions, aliases and
+ * trace header declarations.
+ */
+ goto retry;
+ }
if (ret) {
fprintf(fd, "[error] %s: trace declaration error\n", __func__);
goto error;
}
}
+ cds_list_for_each_entry(iter, &node->u.root.clock, siblings) {
+ ret = ctf_clock_visit(fd, depth + 1, iter,
+ trace);
+ if (ret) {
+ fprintf(fd, "[error] %s: clock declaration error\n", __func__);
+ goto error;
+ }
+ }
+
if (!trace->streams) {
fprintf(fd, "[error] %s: missing trace declaration\n", __func__);
ret = -EINVAL;
error:
free_declaration_scope(trace->root_declaration_scope);
+ g_hash_table_destroy(trace->clocks);
return ret;
}