Port: memstream compat for mingw
[babeltrace.git] / plugins / ctf / common / metadata / visitor-generate-ir.c
index badbf995bacaecbd99a97857a252372ca706cad3..6fefc24d9b29e8d2ad5c1fed4f38dd1c7a6e9e6f 100644 (file)
@@ -226,6 +226,9 @@ struct ctx {
        /* Offset (ns) to apply to clock classes on creation */
        uint64_t clock_class_offset_ns;
 
+       /* Eventual name suffix of the trace to set */
+       char *trace_name_suffix;
+
        /* Trace attributes */
        enum bt_ctf_byte_order trace_bo;
        uint64_t trace_major;
@@ -381,7 +384,7 @@ struct bt_ctf_field_type *ctx_decl_scope_lookup_prefix_alias(
 
        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);
@@ -497,7 +500,7 @@ int ctx_decl_scope_register_prefix_alias(struct ctx_decl_scope *scope,
        }
 
        g_hash_table_insert(scope->decl_map,
-               (gpointer) (unsigned long) qname, decl);
+               GUINT_TO_POINTER(qname), decl);
 
        /* Hash table's reference */
        bt_get(decl);
@@ -572,6 +575,45 @@ int ctx_decl_scope_register_variant(struct ctx_decl_scope *scope,
                name, decl);
 }
 
+/**
+ * Destroys a visitor context.
+ *
+ * @param ctx  Visitor context to destroy
+ */
+static
+void ctx_destroy(struct ctx *ctx)
+{
+       struct ctx_decl_scope *scope;
+       /*
+        * Destroy all scopes, from current one to the root scope.
+        */
+
+       if (!ctx) {
+               goto end;
+       }
+
+       scope = ctx->current_scope;
+
+       while (scope) {
+               struct ctx_decl_scope *parent_scope = scope->parent_scope;
+
+               ctx_decl_scope_destroy(scope);
+               scope = parent_scope;
+       }
+
+       bt_put(ctx->trace);
+
+       if (ctx->stream_classes) {
+               g_hash_table_destroy(ctx->stream_classes);
+       }
+
+       free(ctx->trace_name_suffix);
+       g_free(ctx);
+
+end:
+       return;
+}
+
 /**
  * Creates a new visitor context.
  *
@@ -581,7 +623,7 @@ int ctx_decl_scope_register_variant(struct ctx_decl_scope *scope,
  */
 static
 struct ctx *ctx_create(struct bt_ctf_trace *trace, FILE *efd,
-               uint64_t clock_class_offset_ns)
+               uint64_t clock_class_offset_ns, const char *trace_name_suffix)
 {
        struct ctx *ctx = NULL;
        struct ctx_decl_scope *scope = NULL;
@@ -603,53 +645,27 @@ struct ctx *ctx_create(struct bt_ctf_trace *trace, FILE *efd,
                goto error;
        }
 
+       if (trace_name_suffix) {
+               ctx->trace_name_suffix = strdup(trace_name_suffix);
+               if (!ctx->trace_name_suffix) {
+                       goto error;
+               }
+       }
+
        ctx->trace = trace;
        ctx->efd = efd;
        ctx->current_scope = scope;
+       scope = NULL;
        ctx->trace_bo = BT_CTF_BYTE_ORDER_NATIVE;
        ctx->clock_class_offset_ns = clock_class_offset_ns;
        return ctx;
 
 error:
-       g_free(ctx);
+       ctx_destroy(ctx);
        ctx_decl_scope_destroy(scope);
        return NULL;
 }
 
-/**
- * Destroys a visitor context.
- *
- * @param ctx  Visitor context to destroy
- */
-static
-void ctx_destroy(struct ctx *ctx)
-{
-       struct ctx_decl_scope *scope;
-       /*
-        * Destroy all scopes, from current one to the root scope.
-        */
-
-       if (!ctx) {
-               goto end;
-       }
-
-       scope = ctx->current_scope;
-
-       while (scope) {
-               struct ctx_decl_scope *parent_scope = scope->parent_scope;
-
-               ctx_decl_scope_destroy(scope);
-               scope = parent_scope;
-       }
-
-       bt_put(ctx->trace);
-       g_hash_table_destroy(ctx->stream_classes);
-       g_free(ctx);
-
-end:
-       return;
-}
-
 /**
  * Pushes a new declaration scope on top of a visitor context's
  * declaration scope stack.
@@ -855,6 +871,11 @@ int get_unary_unsigned(struct bt_list_head *head, uint64_t *value)
        int ret = 0;
        struct ctf_node *node;
 
+       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;
@@ -4619,6 +4640,62 @@ end:
        return ret;
 }
 
+static
+int set_trace_name(struct ctx *ctx)
+{
+       GString *name;
+       int ret = 0;
+       struct bt_value *value = NULL;
+
+       assert(bt_ctf_trace_get_stream_class_count(ctx->trace) == 0);
+       name = g_string_new(NULL);
+       if (!name) {
+               ret = -1;
+               goto end;
+       }
+
+       /*
+        * Check if we have a trace environment string value named `hostname`.
+        * If so, use it as the trace name's prefix.
+        */
+       value = bt_ctf_trace_get_environment_field_value_by_name(ctx->trace,
+               "hostname");
+       if (bt_value_is_string(value)) {
+               const char *hostname;
+
+               ret = bt_value_string_get(value, &hostname);
+               assert(ret == 0);
+               g_string_append(name, hostname);
+
+               if (ctx->trace_name_suffix) {
+                       g_string_append_c(name, G_DIR_SEPARATOR);
+               }
+       }
+
+       if (ctx->trace_name_suffix) {
+               g_string_append(name, ctx->trace_name_suffix);
+       }
+
+       ret = bt_ctf_trace_set_name(ctx->trace, name->str);
+       if (ret) {
+               goto error;
+       }
+
+       goto end;
+
+error:
+       ret = -1;
+
+end:
+       bt_put(value);
+
+       if (name) {
+               g_string_free(name, TRUE);
+       }
+
+       return ret;
+}
+
 static
 int move_ctx_stream_classes_to_trace(struct ctx *ctx)
 {
@@ -4626,6 +4703,20 @@ int move_ctx_stream_classes_to_trace(struct ctx *ctx)
        GHashTableIter iter;
        gpointer key, stream_class;
 
+       if (g_hash_table_size(ctx->stream_classes) > 0 &&
+                       bt_ctf_trace_get_stream_class_count(ctx->trace) == 0) {
+               /*
+                * We're about to add the first stream class to the
+                * trace. This will freeze the trace, and after this
+                * we cannot set the name anymore. At this point,
+                * set the trace name.
+                */
+               ret = set_trace_name(ctx);
+               if (ret) {
+                       goto end;
+               }
+       }
+
        g_hash_table_iter_init(&iter, ctx->stream_classes);
 
        while (g_hash_table_iter_next(&iter, &key, &stream_class)) {
@@ -4659,12 +4750,6 @@ struct ctf_visitor_generate_ir *ctf_visitor_generate_ir_create(FILE *efd,
                goto error;
        }
 
-       ret = bt_ctf_trace_set_name(trace, name);
-       if (ret) {
-               _FPERROR(efd, "cannot set trace's name to `%s`", name);
-               goto error;
-       }
-
        /* Set packet header to NULL to override the default one */
        ret = bt_ctf_trace_set_packet_header_type(trace, NULL);
        if (ret) {
@@ -4674,7 +4759,7 @@ struct ctf_visitor_generate_ir *ctf_visitor_generate_ir_create(FILE *efd,
        }
 
        /* Create visitor's context */
-       ctx = ctx_create(trace, efd, clock_class_offset_ns);
+       ctx = ctx_create(trace, efd, clock_class_offset_ns, name);
        if (!ctx) {
                _FPERROR(efd, "%s", "cannot create visitor context");
                goto error;
This page took 0.026077 seconds and 4 git commands to generate.