The following subsections explain the three steps above.
+Also, have a look at the [`examples`](examples) directory which
+contains a few complete examples.
+
### writing the CTF metadata
--- /dev/null
+BARECTF ?= barectf
+RM = rm -rf
+
+CFLAGS = -O2 -Wall
+
+TARGET = simple
+OBJS = $(TARGET).o barectf.o
+
+.PHONY: all view clean
+
+all: $(TARGET)
+
+$(TARGET): $(OBJS)
+ $(CC) -o $@ $^
+
+barectf.h barectf.c: ctf/metadata
+ barectf $<
+
+barectf.o: barectf.c
+ $(CC) $(CFLAGS) -Wno-strict-aliasing -Wno-unused-variable -c $<
+
+$(TARGET).o: $(TARGET).c barectf.h
+ $(CC) $(CFLAGS) -c $<
+
+clean:
+ $(RM) $(TARGET) $(OBJS) ctf/stream*
+ $(RM) barectf.h barectf_bitfield.h barectf.c
--- /dev/null
+/* CTF 1.8 */
+
+typealias integer {size = 8; align = 8;} := uint8_t;
+typealias integer {size = 16; align = 16;} := uint16_t;
+typealias integer {size = 32; align = 32;} := uint32_t;
+typealias integer {size = 64; align = 64;} := uint64_t;
+typealias integer {size = 8; align = 8; signed = true;} := int8_t;
+typealias integer {size = 16; align = 16; signed = true;} := int16_t;
+typealias integer {size = 32; align = 32; signed = true;} := int32_t;
+typealias integer {size = 64; align = 64; signed = true;} := int64_t;
+
+typealias floating_point {
+ exp_dig = 8;
+ mant_dig = 24;
+ align = 32;
+} := float;
+
+typealias floating_point {
+ exp_dig = 11;
+ mant_dig = 53;
+ align = 64;
+} := double;
+
+trace {
+ major = 1;
+ minor = 8;
+ byte_order = le;
+
+ packet.header := struct {
+ uint32_t magic;
+ uint32_t stream_id;
+ };
+};
+
+env {
+ domain = "bare";
+ tracer_name = "barectf";
+ tracer_major = 0;
+ tracer_minor = 1;
+ tracer_patchlevel = 0;
+};
+
+clock {
+ name = my_clock;
+ freq = 1000000000;
+ offset = 0;
+};
+
+typealias integer {
+ size = 64;
+ map = clock.my_clock.value;
+} := my_clock_int_t;
+
+stream {
+ id = 0;
+
+ packet.context := struct {
+ my_clock_int_t timestamp_begin;
+ my_clock_int_t timestamp_end;
+ uint64_t packet_size;
+ uint64_t content_size;
+ };
+
+ event.header := struct {
+ uint32_t id;
+ my_clock_int_t timestamp;
+ };
+};
+
+/* an event with a simple 32-bit unsigned integer field */
+event {
+ name = "simple_uint32";
+ id = 0;
+ stream_id = 0;
+
+ fields := struct {
+ uint32_t _value;
+ };
+};
+
+/* an event with a simple 16-bit signed integer field */
+event {
+ name = "simple_int16";
+ id = 1;
+ stream_id = 0;
+
+ fields := struct {
+ int16_t _value;
+ };
+};
+
+/*
+ * An event with a simple IEEE 754 (see type alias above) single-precision
+ * floating point number.
+ */
+event {
+ name = "simple_float";
+ id = 2;
+ stream_id = 0;
+
+ fields := struct {
+ float _value;
+ };
+};
+
+/* an event with a simple NULL-terminated string field */
+event {
+ name = "simple_string";
+ id = 3;
+ stream_id = 0;
+
+ fields := struct {
+ string _value;
+ };
+};
+
+/* custom enumeration, of which the key is a 8-bit unsigned integer */
+typealias enum : uint8_t {
+ NEW, /* 0 */
+ TERMINATED, /* 1 */
+ READY, /* 2 */
+ RUNNING, /* 3 */
+ WAITING, /* 4 */
+} := state_t;
+
+/* an event with a simple enumeration (see type alias above) field */
+event {
+ name = "simple_enum";
+ id = 4;
+ stream_id = 0;
+
+ fields := struct {
+ state_t _state;
+ };
+};
+
+/* an event with a few fields */
+event {
+ name = "a_few_fields";
+ id = 5;
+ stream_id = 0;
+
+ fields := struct {
+ int32_t _int32;
+ uint16_t _uint16;
+ double _double;
+ string _string;
+ state_t _state;
+ };
+};
+
+/* an event with bit-packed integer fields */
+event {
+ name = "bit_packed_integers";
+ id = 6;
+ stream_id = 0;
+
+ fields := struct {
+ integer {size = 1;} _uint1;
+ integer {size = 1; signed = true;} _int1;
+ integer {size = 2;} _uint2;
+ integer {size = 3; signed = true;} _int3;
+ integer {size = 4;} _uint4;
+ integer {size = 5; signed = true;} _int5;
+ integer {size = 6;} _uint6;
+ integer {size = 7; signed = true;} _int7;
+ integer {size = 8; align = 1;} _uint8;
+ };
+};
--- /dev/null
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "barectf.h"
+
+static uint64_t get_clock(void* data)
+{
+ struct timespec ts;
+
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+
+ return ts.tv_sec * 1000000000UL + ts.tv_nsec;
+}
+
+enum state_t {
+ NEW,
+ TERMINATED,
+ READY,
+ RUNNING,
+ WAITING,
+};
+
+static void simple(uint8_t* buf, size_t sz)
+{
+ /* initialize barectf context */
+ struct barectf_ctx ctx;
+ struct barectf_ctx* pctx = &ctx;
+
+ barectf_init(pctx, buf, sz, get_clock, NULL);
+
+ /* open packet */
+ barectf_open_packet(pctx);
+
+ /* record events */
+ barectf_trace_simple_uint32(pctx, 20150101);
+ barectf_trace_simple_int16(pctx, -2999);
+ barectf_trace_simple_float(pctx, 23.57);
+ barectf_trace_simple_string(pctx, "Hello, World!");
+ barectf_trace_simple_enum(pctx, RUNNING);
+ barectf_trace_a_few_fields(pctx, -1, 301, -3.14159, "Hello again!", NEW);
+ barectf_trace_bit_packed_integers(pctx, 1, -1, 3, -2, 2, 7, 23, -55, 232);
+
+ /* close packet */
+ barectf_close_packet(pctx);
+}
+
+static void write_packet(const char* filename, const uint8_t* buf, size_t sz)
+{
+ FILE* fh = fopen(filename, "wb");
+
+ if (!fh) {
+ return;
+ }
+
+ fwrite(buf, 1, sz, fh);
+ fclose(fh);
+}
+
+int main(void)
+{
+ puts("simple barectf example!");
+
+ const size_t buf_sz = 8192;
+
+ uint8_t* buf = malloc(buf_sz);
+
+ if (!buf) {
+ return 1;
+ }
+
+ simple(buf, buf_sz);
+ write_packet("ctf/stream_0", buf, buf_sz);
+ free(buf);
+
+ return 0;
+}