#include <inttypes.h>
#include <endian.h>
#include <errno.h>
+#include <babeltrace/babeltrace.h>
#include <babeltrace/list.h>
#include <babeltrace/types.h>
#include <babeltrace/ctf/metadata.h>
struct declaration_scope *declaration_scope,
struct ctf_trace *trace);
+static
+int ctf_stream_visit(FILE *fd, int depth, struct ctf_node *node,
+ struct declaration_scope *parent_declaration_scope, struct ctf_trace *trace);
+
/*
* String returned must be freed by the caller using g_free.
*/
}
static
-struct ctf_stream *trace_stream_lookup(struct ctf_trace *trace, uint64_t stream_id)
+struct ctf_stream_class *trace_stream_lookup(struct ctf_trace *trace, uint64_t stream_id)
{
if (trace->streams->len <= stream_id)
return NULL;
static
struct declaration *ctf_declaration_struct_visit(FILE *fd,
int depth, const char *name, struct cds_list_head *declaration_list,
- int has_body, struct declaration_scope *declaration_scope,
+ int has_body, struct cds_list_head *min_align,
+ struct declaration_scope *declaration_scope,
struct ctf_trace *trace)
{
struct declaration_struct *struct_declaration;
declaration_scope);
return &struct_declaration->p;
} else {
+ uint64_t min_align_value = 0;
+
/* For unnamed struct, create type */
/* For named struct (with body), create type and add to declaration scope */
if (name) {
return NULL;
}
}
- struct_declaration = struct_declaration_new(declaration_scope);
+ if (!cds_list_empty(min_align)) {
+ ret = get_unary_unsigned(min_align, &min_align_value);
+ if (ret) {
+ fprintf(fd, "[error] %s: unexpected unary expression for structure \"align\" attribute\n", __func__);
+ ret = -EINVAL;
+ goto error;
+ }
+ }
+ struct_declaration = struct_declaration_new(declaration_scope,
+ min_align_value);
cds_list_for_each_entry(iter, declaration_list, siblings) {
ret = ctf_struct_declaration_list_visit(fd, depth + 1, iter,
struct_declaration, trace);
int byte_order = trace->byte_order;
int signedness = 0;
int has_alignment = 0, has_size = 0;
+ int base = 10;
struct declaration_integer *integer_declaration;
cds_list_for_each_entry(expression, expressions, siblings) {
return NULL;
}
alignment = right->u.unary_expression.u.unsigned_constant;
+ /* Make sure alignment is a power of two */
+ if (alignment == 0 || (alignment & (alignment - 1)) != 0) {
+ fprintf(fd, "[error] %s: align: expecting power of two\n",
+ __func__);
+ return NULL;
+ }
has_alignment = 1;
+ } else if (!strcmp(left->u.unary_expression.u.string, "base")) {
+ switch (right->u.unary_expression.type) {
+ case UNARY_UNSIGNED_CONSTANT:
+ switch (right->u.unary_expression.u.unsigned_constant) {
+ case 2:
+ case 8:
+ case 10:
+ case 16:
+ base = right->u.unary_expression.u.unsigned_constant;
+ break;
+ default:
+ fprintf(fd, "[error] %s: base not supported (%" PRIu64 ")\n",
+ __func__, right->u.unary_expression.u.unsigned_constant);
+ return NULL;
+ }
+ break;
+ case UNARY_STRING:
+ {
+ char *s_right = concatenate_unary_strings(&expression->u.ctf_expression.right);
+ if (!s_right) {
+ fprintf(fd, "[error] %s: unexpected unary expression for integer base\n", __func__);
+ g_free(s_right);
+ return NULL;
+ }
+ if (!strcmp(s_right, "decimal") || !strcmp(s_right, "dec") || !strcmp(s_right, "d")
+ || !strcmp(s_right, "i") || !strcmp(s_right, "u")) {
+ base = 10;
+ } else if (!strcmp(s_right, "hexadecimal") || !strcmp(s_right, "hex")
+ || !strcmp(s_right, "x") || !strcmp(s_right, "X")
+ || !strcmp(s_right, "p")) {
+ base = 16;
+ } else if (!strcmp(s_right, "octal") || !strcmp(s_right, "oct")
+ || !strcmp(s_right, "o")) {
+ base = 8;
+ } else if (!strcmp(s_right, "binary") || !strcmp(s_right, "b")) {
+ base = 2;
+ } else {
+ fprintf(fd, "[error] %s: unexpected expression for integer base (%s)\n", __func__, s_right);
+ g_free(s_right);
+ return NULL;
+ }
+
+ g_free(s_right);
+ break;
+ }
+ default:
+ fprintf(fd, "[error] %s: base: expecting unsigned constant or unary string\n",
+ __func__);
+ return NULL;
+ }
} else {
fprintf(fd, "[error] %s: unknown attribute name %s\n",
__func__, left->u.unary_expression.u.string);
}
}
integer_declaration = integer_declaration_new(size,
- byte_order, signedness, alignment);
+ byte_order, signedness, alignment, base);
return &integer_declaration->p;
}
return NULL;
}
alignment = right->u.unary_expression.u.unsigned_constant;
+ /* Make sure alignment is a power of two */
+ if (alignment == 0 || (alignment & (alignment - 1)) != 0) {
+ fprintf(fd, "[error] %s: align: expecting power of two\n",
+ __func__);
+ return NULL;
+ }
has_alignment = 1;
} else {
fprintf(fd, "[error] %s: unknown attribute name %s\n",
node->u._struct.name,
&node->u._struct.declaration_list,
node->u._struct.has_body,
+ &node->u._struct.min_align,
declaration_scope,
trace);
case TYPESPEC_VARIANT:
fprintf(fd, "[error] %s: missing name field in event declaration\n", __func__);
goto error;
}
- /* Allow only one event without id per stream */
- if (!CTF_EVENT_FIELD_IS_SET(event, id)
- && event->stream->events_by_id->len != 0) {
- ret = -EPERM;
- fprintf(fd, "[error] %s: missing id field in event declaration\n", __func__);
- goto error;
- }
if (!CTF_EVENT_FIELD_IS_SET(event, stream_id)) {
/* Allow missing stream_id if there is only a single stream */
- if (trace->streams->len == 1) {
+ switch (trace->streams->len) {
+ case 0: /* Create stream if there was none. */
+ ret = ctf_stream_visit(fd, depth, NULL, trace->root_declaration_scope, trace);
+ if (ret)
+ goto error;
+ /* Fall-through */
+ case 1:
event->stream_id = 0;
event->stream = trace_stream_lookup(trace, event->stream_id);
- } else {
+ break;
+ default:
ret = -EPERM;
fprintf(fd, "[error] %s: missing stream_id field in event declaration\n", __func__);
goto error;
}
}
+ /* Allow only one event without id per stream */
+ if (!CTF_EVENT_FIELD_IS_SET(event, id)
+ && event->stream->events_by_id->len != 0) {
+ ret = -EPERM;
+ fprintf(fd, "[error] %s: missing id field in event declaration\n", __func__);
+ goto error;
+ }
if (event->stream->events_by_id->len <= event->id)
g_ptr_array_set_size(event->stream->events_by_id, event->id + 1);
g_ptr_array_index(event->stream->events_by_id, event->id) = event;
static
-int ctf_stream_declaration_visit(FILE *fd, int depth, struct ctf_node *node, struct ctf_stream *stream, struct ctf_trace *trace)
+int ctf_stream_declaration_visit(FILE *fd, int depth, struct ctf_node *node, struct ctf_stream_class *stream, struct ctf_trace *trace)
{
int ret = 0;
{
int ret = 0;
struct ctf_node *iter;
- struct ctf_stream *stream;
+ struct ctf_stream_class *stream;
struct definition_scope *parent_def_scope;
- stream = g_new0(struct ctf_stream, 1);
+ stream = g_new0(struct ctf_stream_class, 1);
stream->declaration_scope = new_declaration_scope(parent_declaration_scope);
stream->events_by_id = g_ptr_array_new();
stream->event_quark_to_id = g_hash_table_new(g_direct_hash, g_direct_equal);
stream->files = g_ptr_array_new();
- cds_list_for_each_entry(iter, &node->u.stream.declaration_list, siblings) {
- ret = ctf_stream_declaration_visit(fd, depth + 1, iter, stream, trace);
- if (ret)
- goto error;
+ if (node) {
+ cds_list_for_each_entry(iter, &node->u.stream.declaration_list, siblings) {
+ ret = ctf_stream_declaration_visit(fd, depth + 1, iter, stream, trace);
+ if (ret)
+ goto error;
+ }
}
if (CTF_STREAM_FIELD_IS_SET(stream, stream_id)) {
/* check that packet header has stream_id field. */
fprintf(fd, "[error] %s: missing stream_id field in packet header declaration, but stream_id attribute is declared for stream.\n", __func__);
goto error;
}
- }
-
- /* Allow only one id-less stream */
- if (!CTF_STREAM_FIELD_IS_SET(stream, stream_id)
- && trace->streams->len != 0) {
- ret = -EPERM;
- fprintf(fd, "[error] %s: missing id field in stream declaration\n", __func__);
- goto error;
+ } else {
+ /* Allow only one id-less stream */
+ if (trace->streams->len != 0) {
+ ret = -EPERM;
+ fprintf(fd, "[error] %s: missing id field in stream declaration\n", __func__);
+ goto error;
+ }
+ stream->stream_id = 0;
}
if (trace->streams->len <= stream->stream_id)
g_ptr_array_set_size(trace->streams, stream->stream_id + 1);
fprintf(fd, "[error] %s: missing uuid field in trace declaration\n", __func__);
goto error;
}
+ if (!CTF_TRACE_FIELD_IS_SET(trace, byte_order)) {
+ ret = -EPERM;
+ fprintf(fd, "[error] %s: missing byte_order field in trace declaration\n", __func__);
+ goto error;
+ }
parent_def_scope = NULL;
if (trace->packet_header_decl) {
int ret = 0;
struct ctf_node *iter;
- fprintf(fd, "CTF visitor: metadata construction... ");
+ printf_verbose("CTF visitor: metadata construction... ");
trace->root_declaration_scope = new_declaration_scope(NULL);
+ trace->streams = g_ptr_array_new();
trace->byte_order = byte_order;
switch (node->type) {
(int) node->type);
return -EINVAL;
}
- fprintf(fd, "done.\n");
+ printf_verbose("done.\n");
return ret;
}