Fixing the missing initialization of the field 'initialized' in the global context...
[barectf.git] / README.md
index 28fedf4bf7705c5572a73017f934de56273bcfb4..fba513331091b5cef74ffc9488a9a30193152d6e 100644 (file)
--- a/README.md
+++ b/README.md
-barectf
-=======
+# barectf
 
 **barectf** is a command-line utility which generates pure C99
-code that is able to write native
-[CTF](http://git.efficios.com/?p=ctf.git;a=blob_plain;f=common-trace-format-specification.txt;hb=master)
-(the Common Trace Format) out of a pre-written CTF metadata file.
+code that is able to write native [Common Trace Format](http://diamon.org/ctf)
+(CTF) binary streams.
 
 You will find barectf interesting if:
 
-  1. You need to trace a program.
-  2. You need tracing to be as fast as possible, but also very flexible:
+  1. You need to trace an application.
+  2. You need tracing to be efficient, yet flexible:
      record integers of custom sizes, custom floating point numbers,
-     enumerations mapped to a specific integer type, structure fields,
-     NULL-terminated strings, static and dynamic arrays, etc.
+     enumerations supported by a specific integer type, and
+     null-terminated UTF-8/ASCII strings (C strings).
   3. You need to be able to convert the recorded binary events to
      human-readable text, as well as analyze them with Python scripts
      ([Babeltrace](http://www.efficios.com/babeltrace) does all that,
      given a CTF input).
   4. You _cannot_ use [LTTng](http://lttng.org/), an efficient tracing
      framework for the Linux kernel and Linux/BSD user applications, which
-     outputs CTF.
+     also outputs CTF.
 
 The target audience of barectf is developers who need to trace bare metal
 systems (without an operating system). The code produced by barectf
-is pure C99 and is lightweight enough to fit on a tiny microcontroller.
-Each event described in the CTF metadata input becomes one C function with
-one parameter mapped to one event field. CTF data is recorded in a buffer of
-any size provided by the user. This buffer corresponds to one CTF packet.
-The generated tracing functions report when the buffer is full. The user
-is entirely responsible for the buffering scheme: leave the buffer in memory,
-save it to some permanent storage, swap it with another empty buffer and
-concatenate recorded packets, etc.
+is pure C99 and can be lightweight enough to fit on a tiny microcontroller.
 
-barectf is written in Python 3 and currently uses
-[pytsdl](https://github.com/eepp/pytsdl) to parse the CTF metadata file
-provided by the user.
+**Key features**:
 
+  * Single input: easy-to-write [YAML](https://en.wikipedia.org/wiki/YAML)
+    configuration file (documentation below)
+  * 1-to-1 mapping from tracing function parameters to event fields
+  * Custom and bundled _platforms_ hiding the details of opening/closing
+    packets and writing them to a back-end (continuous tracing), getting
+    the clock values, etc.:
+    * _linux-fs_: basic Linux application tracing writing stream files to
+      the file system for demonstration purposes
+    * _parallella_: Adapteva Epiphany/[Parallella](http://parallella.org/)
+      with host-side consumer
+  * CTF metadata generated by the command-line tool (automatic trace UUID,
+    stream IDs, and event IDs)
+  * All basic CTF types are supported: integers, floating point numbers,
+    enumerations, and null-terminated strings (C strings)
+  * Binary streams produced by the generated C code and metadata file
+    produced by barectf are CTF 1.8-compliant
+  * Human-readable error reporting
 
-installing
-----------
+**Current limitations**:
 
-Make sure you have `pip` for Python 3. On the latest Ubuntu releases,
-it is called `pip3`:
+As of this version:
+
+  * All the generated tracing C functions, for a given barectf
+    stream-specific context, need to be called from the same thread, and cannot
+    be called from an interrupt handler, unless a user-provided
+    synchronization mechanism is used.
+  * CTF compound types (array, sequence, structure, variant) are not supported
+    yet, except at some very specific locations in the metadata.
+
+barectf is written in Python 3.
+
+
+## Installing
+
+Make sure you have Python 3 and `pip` for Python 3 installed, then
+install barectf.
+
+Note that you may pass the `--user` argument to
+`pip install` to install the tool in your home directory (instead of
+installing globally).
+
+**Latest Ubuntu**:
 
     sudo apt-get install python3-pip
+    sudo pip3 install barectf
 
-On Ubuntu 12.04, you need to install `setuptools` first, then use
-`easy_install3` to install `pip3`:
+**Ubuntu 12.04 and lower**:
 
     sudo apt-get install python3-setuptools
     sudo easy_install3 pip
+    sudo pip3 install barectf
 
-Install barectf:
+**Debian**:
 
+    sudo apt-get install python3-pip
     sudo pip3 install barectf
 
+**Fedora 20 and up**:
+
+    sudo yum install python3-pip
+    sudo pip3 install barectf
 
-using
------
+**Arch Linux**:
 
-Using barectf involves:
+    sudo install python-pip
+    sudo pip install barectf
 
-  1. Writing the CTF metadata file describing the various headers,
-     contexts and event fields.
-  2. Running the `barectf` command to generate C99 files out of
-     the CTF metadata file.
-  3. Using the generated C code in your specific application.
+**OS X**
 
-The following subsections explain the three steps above.
+With [Homebrew](http://brew.sh/):
 
+    brew install python3
+    pip3 install barectf
 
-### writing the CTF metadata
 
-The **Common Trace Format** is a specialized file format for recording
-trace data. CTF is designed to be very fast to write and very flexible.
-All headers, contexts and event fields written in binary files are
-described using a custom C-like, declarative language, TSDL (Trace
-Stream Description Language). The file containing this description is
-called the **CTF metadata**. The latter may be automatically generated
-by a tracer, like it is the case of LTTng, or written by hand. This
-metadata file is then used by CTF trace readers to know the layout of
-CTF binary files containing actual event contexts and fields.
+## What is CTF?
 
-The CTF metadata file contains several blocks describing various CTF
-binary layouts. A CTF trace file is a concatenation of several CTF
-packets. Here's the anatomy of a CTF packet:
+See the [CTF in a nutshell](http://diamon.org/ctf/#ctf-in-a-nutshell)
+section of CTF's website to understand the basics of this
+trace format.
 
-![CTF packet anatomy](doc/ctf-packet.png)
+The most important thing to understand about CTF, for barectf use
+cases, is the layout of a binary stream packet:
 
-A CTF packet belongs to a specific CTF stream. While the packet header
-is the same for all streams of a given CTF trace, everything else is
-specified per stream. Following this packet header is a packet context,
-and then actual recorded events. Each event starts with a mandatory
-header (same event header for all events of a given stream). The event
-header is followed by an optional event context with a layout shared
-by all events of a given stream. Then follows another optional event
-context, although this one has a layout specific to the event type.
-Finally, event fields are written.
+  * Packet header (defined at the trace level)
+  * Packet context (defined at the stream level)
+  * Sequence of events (defined at the stream level):
+    * Event header (defined at the stream level)
+    * Stream event context (defined at the stream level)
+    * Event context (defined at the event level)
+    * Event payload (defined at the event level)
 
-barectf asks you to write the CTF metadata by hand. Although its official
-[specification](http://git.efficios.com/?p=ctf.git;a=blob_plain;f=common-trace-format-specification.txt;hb=master)
-is thorough, you will almost always start from this template:
+The following diagram, stolen without remorse from CTF's website, shows
+said packet layout:
 
-```
-/* CTF 1.8 */
-
-// a few useful standard integer aliases
-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;
-
-// IEEE 754 standard-precision floating point alias
-typealias floating_point {
-    exp_dig = 8;
-    mant_dig = 24;
-    align = 32;
-} := float;
-
-// IEEE 754 double-precision floating point alias
-typealias floating_point {
-    exp_dig = 11;
-    mant_dig = 53;
-    align = 64;
-} := double;
-
-// trace block
-trace {
-    // CTF version 1.8; leave this as is
-    major = 1;
-    minor = 8;
-
-    /* Native byte order (`le` or `be`). This is used by barectf to generate
-     * the appropriate code when writing data to the packet.
-     */
-    byte_order = le;
-
-    /* Packet header. All packets (buffers) will have the same header.
-     *
-     * Special fields recognized by barectf (must appear in this order):
-     *
-     *   magic:     will be set to CTF's magic number (must be the first field)
-     *              (32-bit unsigned integer)
-     *   stream_id: will be set to the ID of the stream associated with
-     *              this packet (unsigned integer of your choice) (mandatory)
-     */
-    packet.header := struct {
-        uint32_t magic;
-        uint32_t stream_id;
-    };
-};
-
-// environment variables; you may add custom entries
-env {
-    domain = "bare";
-    tracer_name = "barectf";
-    tracer_major = 0;
-    tracer_minor = 1;
-    tracer_patchlevel = 0;
-};
-
-// clock descriptor
-clock {
-    // clock name
-    name = my_clock;
-
-    // clock frequency (Hz)
-    freq = 1000000000;
-
-    // optional clock value offset (offfset from Epoch is: offset * (1 / freq))
-    offset = 0;
-};
-
-// alias for integer used to hold clock cycles
-typealias integer {
-    size = 32;
-
-    // map to the appropriate clock using its name
-    map = clock.my_clock.value;
-} := my_clock_int_t;
-
-/* A stream. You may have as many streams as you want. Events are unique
- * within their own stream. The main advantage of having multiple streams
- * is having different event headers, stream event contexts and stream
- * packet contexts for each one.
- */
-stream {
-    /* Mandatory stream ID (must fit the integer type of
-     * `trace.packet.header.stream_id`.
-     */
-    id = 0;
-
-    /* Mandatory packet context. This structure follows the packet header
-     * (see `trace.packet.header`) immediately in CTF binary streams.
-     *
-     * Special fields recognized by barectf:
-     *
-     *   timestamp_begin: will be set to the current clock value when opening
-     *                    the packet (same integer type as the clock's value)
-     *   timestamp_end:   will be set to the current clock value when closing
-     *                    the packet (same integer type as the clock's value)
-     *   content_size:    will be set to the content size, in bits, of this
-     *                    stream (unsigned 32-bit or 64-bit integer) (mandatory)
-     *   packet_size:     will be set to the packet size, in bits, of this
-     *                    stream (unsigned 32-bit or 64-bit integer) (mandatory)
-     *   cpu_id:          if present, the barectf_open_packet() function of this
-     *                    stream will accept an additional parameter to specify the
-     *                    ID of the CPU associated with this stream (a given
-     *                    stream should only be written to by a specific CPU)
-     *                    (unsigned integer of your choice)
-     *
-     * `timestamp_end` must be present if `timestamp_begin` exists.
-     */
-    packet.context := struct {
-        my_clock_int_t timestamp_begin;
-        my_clock_int_t timestamp_end;
-        uint64_t content_size;
-        uint64_t packet_size;
-        uint32_t cpu_id;
-    };
+![](http://diamon.org/ctf/img/ctf-stream-packet.png)
 
-    /* Mandatory event header. All events recorded in this stream will start
-     * with this structure.
-     *
-     * Special fields recognized by barectf:
-     *
-     *   id:        will be filled by the event ID corresponding to a tracing
-     *              function (unsigned integer of your choice)
-     *   timestamp: will be filled by the current clock's value (same integer
-     *              type as the clock's value)
-     */
-    event.header := struct {
-        uint32_t id;
-        my_clock_int_t timestamp;
-    };
+Any of those six dynamic scopes, if defined at all, has an associated
+CTF type. barectf requires them to be structure types.
 
-    /* Optional stream event context (you may remove the whole block or leave
-     * the structure empty if you don't want any). This structure follows the
-     * event header (see `stream.event.header`) immediately in CTF binary streams.
-     */
-    event.context := struct {
-        int32_t _some_stream_event_context_field;
-    };
-};
-
-/* An event. Events have an ID, a name, an optional context and fields. An
- * event is associated to a specific stream using its stream ID.
- */
-event {
-    /* Mandatory event name. This is used by barectf to generate the suffix
-     * of this event's corresponding tracing function, so make sure it follows
-     * the C identifier syntax even though it's a quoted string here.
-     */
-    name = "my_event";
-
-    /* Mandatory event ID (must fit the integer type of
-     * in `stream.event.header.id` of the associated stream).
-     */
-    id = 0;
-
-    // ID of the stream in which this event will be recorded
-    stream_id = 0;
-
-    /* Optional event context (you may remove the whole block or leave the
-     * structure empty if you don't want one). This structure follows the
-     * stream event context (if it exists) immediately in CTF binary streams.
-     */
-    context := struct {
-        int32_t _some_event_context_field;
-    };
 
-    /* Mandatory event fields (although the structure may be left empty if this
-     * event has no fields). This structure follows the event context (if it
-     * exists) immediately in CTF binary streams.
-     */
-    fields := struct {
-        uint32_t _a;
-        uint32_t _b;
-        uint16_t _c;
-        string _d;
-    };
-};
-```
+## Using
 
-The top `/* CTF 1.8 */` is actually needed right there, and as is, since it
-acts as a CTF metadata magic number for CTF readers.
+Using barectf involves the following steps:
 
-Only one stream and one event (belonging to this single stream) are described
-in this template, but you may add as many as you need.
+  1. Writing the YAML configuration file defining the various header,
+     context, and event field types.
+  2. Running the `barectf` command-line tool with this configuration file
+     to generate the CTF metadata and C files.
+  3. Using the generated C code (tracing functions), along with the C code
+     provided by the appropriate barectf platform, in the source code of
+     your own application.
+  4. Running your application, along with anything the barectf platform
+     you chose requires, to generate the binary streams of a CTF trace.
 
-The following subsections describe the features of CTF metadata supported
-by barectf.
+Your application, when running, will generate CTF packets. Depending
+on the chosen barectf platform, those packets will be consumed and
+sequentially written at some place for later viewing/analysis.
 
+Here's a diagram summarizing the steps described above:
 
-#### types
+![](http://0x3b.org/ss/cardiectasis400.png)
 
-The supported structure field types are:
+The following subsections explain the four steps above.
 
-  * **integers** of any size (64-bit and less), any alignment (power of two)
-  * **floating point numbers** of any total size (64-bit and less), any
-    alignment (power of two)
-  * NULL-terminated **strings** of bytes
-  * **enumerations** associated with a specific integer type
-  * **static** and **dynamic arrays** of any type
-  * **structures** containing only integers, floating point numbers,
-    enumerations and _static_ arrays
+Also, have a look at the [`doc/examples`](doc/examples) directory, which
+contains complete examples.
 
-CTF also supports _variants_ (dynamic selection between different types),
-but barectf **does not**. Any detected variant will throw an error when
-running `barectf`.
 
+### Writing the YAML configuration file
 
-##### integers
+The barectf [YAML](https://en.wikipedia.org/wiki/YAML) configuration file
+is the only input the `barectf` command-line tool needs in order to generate
+the corresponding CTF metadata and C files.
 
-CTF integers are defined like this:
+To start with a concrete configuration, here's some minimal configuration:
 
-```
-integer {
-    // mandatory size in bits (64-bit and less)
-    size = 16;
-
-    /* Optional alignment in bits (power of two). Default is 8 when the
-     * size is a multiple of 8, and 1 otherwise.
-     */
-    align = 16;
-
-    // optional signedness (`true` or `false`); default is unsigned
-    signed = true;
-
-    /* Optional byte order (`le`, `be`, `native` or `network`). `native`
-     * will use the byte order specified by the `trace.byte_order`.
-     * Default is `native`.
-     */
-    byte_order = le;
-
-    /* Optional display base, used to display the integer value when
-     * reading the trace. Valid values are 2 (or `binary`, `bin` and `b`),
-     * 8 (or `o`, `oct` or `octal`), 10 (or `u`, `i`, `d`, `dec` or
-     * `decimal`), and 16 (or `x`, `X`, `p`, `hex` or `hexadecimal`).
-     * Default is 10.
-     */
-    base = hex;
-
-    /* Encoding (if this integer represents a character). Valid values
-     * are `none`, `UTF8` and `ASCII`. Default is `none`.
-     */
-    encoding = UTF8;
-}
+```yaml
+version: '2.0'
+metadata:
+  type-aliases:
+    uint16:
+      class: int
+      size: 16
+  trace:
+    byte-order: le
+  streams:
+    my_stream:
+      packet-context-type:
+        class: struct
+        fields:
+          packet_size: uint16
+          content_size: uint16
+      events:
+        my_event:
+          payload-type:
+            class: struct
+            fields:
+              my_field:
+                class: int
+                size: 8
 ```
 
-The size (the only mandatory property) does _not_ have to be a power of two:
+The `version` property must be set to the `2.0` _string_ (hence the single
+quotes). As features are added to barectf and to its configuration file schema,
+this version will be bumped accordingly.
 
+The `metadata` property is where the properties and layout of the
+eventual CTF trace are defined. The accepted properties of each object
+are documented later in this document. For the moment, note simply
+that the native byte order of the trace is set to `le` (little-endian),
+and that there's one defined stream named `my_stream`, having one
+defined event named `my_event`, having a structure as its payload
+type, with a single 8-bit unsigned integer type field named `my_field`. Also,
+the stream packet context type is a structure defining the mandatory
+`packet_size` and `content_size` special fields as 16-bit unsigned integer
+types.
+
+Running `barectf` with the configuration above (as a file named `config.yaml`):
+
+    barectf config.yaml
+
+will produce a C file (`barectf.c`), and its header file (`barectf.h`),
+the latter declaring the following function:
+
+```c
+void barectf_my_stream_trace_my_event(
+    struct barectf_my_stream_ctx *ctx, uint8_t ep_my_field);
 ```
-integer {size = 23;}
+
+`ctx` is the barectf context for the stream named `my_stream` (usually
+initialized and provided by the barectf platform), and `ep_my_field` is the
+value of the `my_event` event payload's `my_field` field.
+
+The following subsections define all the objects of the YAML configuration
+file.
+
+
+#### Configuration object
+
+The top-level object of the YAML configuration file.
+
+**Properties**:
+
+| Property | Type | Description | Required? | Default value |
+|---|---|---|---|---|
+| `version` | String | Must be set to `'2.0'` | Required | N/A |
+| `prefix` | String | Prefix to be used for function names, file names, etc. | Optional | `barectf_` |
+| `metadata` | [Metadata object](#metadata-object) | Trace metadata | Required | N/A |
+
+The `prefix` property must be set to a valid C identifier. It can be
+overridden by the `barectf` command-line tool's `--prefix` option.
+
+**Example**:
+
+```yaml
+version: '2.0'
+prefix: axx_
+metadata:
+  type-aliases:
+    uint16:
+      class: int
+      size: 16
+  trace:
+    byte-order: le
+  streams:
+    my_stream:
+      packet-context-type:
+        class: struct
+        fields:
+          packet_size: uint16
+          content_size: uint16
+      events:
+        my_event:
+          payload-type:
+            class: struct
+            fields:
+              a:
+                class: int
+                size: 8
 ```
 
-is perfectly valid.
 
-A CTF integer field will make barectf produce a corresponding C integer
-function parameter with an appropriate size. For example, the 23-bit integer
-above would produce an `uint32_t` parameter (of which only the first 23
-least significant bits will be written to the trace), while the first
-16-bit one will produce an `int16_t` parameter.
+#### Metadata object
+
+A metadata object defines the desired layout of the CTF trace to be
+produced by the generated C code. It is used by barectf to generate C code,
+as well as a corresponding CTF metadata file.
+
+**Properties**:
+
+| Property | Type | Description | Required? | Default value |
+|---|---|---|---|---|
+| `type-aliases` | Associative array of strings (alias names) to [type objects](#type-objects) or strings (previous alias names) | Type aliases to be used in trace, stream, and event objects | Optional | `{}` |
+| `log-levels` | Associative array of strings (log level names) to log level constant integers | Log levels to be used in event objects | Optional | `{}` |
+| `clocks` | Associative array of strings (clock names) to [clock objects](#clock-object) | Trace clocks | Optional | `{}` |
+| `env` | Associative array of strings (names) to strings or integers (values) | Trace environment variables | Optional | `{}` |
+| `trace` | [Trace object](#trace-object) | Metadata common to the whole trace | Required | N/A |
+| `streams` | Associative array of strings (stream names) to [stream objects](#stream-object) | Trace streams | Required | N/A |
+
+Each clock name of the `clocks` property must be a valid C identifier.
+
+The `streams` property must contain at least one entry. Each stream name must be
+a valid C identifier.
+
+Each environment variable name in the `env` property must be a valid
+C identifier. Those variables will be appended to some environment
+variables set by barectf itself.
+
+The order of the `type-aliases` entries is important: a type alias may only
+inherit from another type alias if the latter is defined before.
+
+**Example**:
+
+```yaml
+type-aliases:
+  uint8:
+    class: integer
+    size: 8
+  uint16:
+    class: integer
+    size: 16
+  uint32:
+    class: integer
+    size: 32
+  uint64:
+    class: integer
+    size: 64
+  clock-int:
+    inherit: uint64
+    property-mappings:
+      - type: clock
+        name: my_clock
+        property: value
+  byte: uint8
+  uuid:
+    class: array
+    length: 16
+    element-type: byte
+log-levels:
+  emerg: 0
+  alert: 1
+  critical: 2
+  error: 3
+  warning: 4
+  notice: 5
+  info: 6
+clocks:
+  my_clock:
+    freq: 1000000000
+    offset:
+      seconds: 1434072888
+    return-ctype: uint64_t
+env:
+  my_system_version: '0.3.2-2015.03'
+  bID: 15
+trace:
+  byte-order: le
+  uuid: auto
+  packet-header-type:
+    class: struct
+    min-align: 8
+    fields:
+      magic: uint32
+      uuid: uuid
+      stream_id: uint8
+streams:
+  my_stream:
+    packet-context-type:
+      class: struct
+      fields:
+        timestamp_begin: clock-int
+        timestamp_end: clock-int
+        packet_size: uint32
+        something: float
+        content_size: uint32
+        events_discarded: uint32
+    event-header-type:
+      class: struct
+      fields:
+        timestamp: clock-int
+        id: uint16
+    events:
+      simple_uint32:
+        log-level: error
+        payload-type:
+          class: struct
+          fields:
+            value: uint32
+      simple_int16:
+        payload-type:
+          class: struct
+          fields:
+            value:
+              inherit: uint16
+              signed: true
+```
 
-The `integer` block also accepts a `map` property which is only used
-when defining the integer used to carry the value of a specified
-clock. You may always follow the example above.
 
+#### Clock object
 
-##### floating point numbers
+A CTF clock.
 
-CTF floating point numbers are defined like this:
+**Properties**:
 
-```
-floating_point {
-    // exponent size in bits
-    exp_dig = 8;
-
-    // mantissa size in bits
-    mant_dig = 24;
-
-    /* Optional alignment (power of two). Default is 8 when the total
-     * size (exponent + mantissa) is a multiple of 8, and 1 otherwise.
-     */
-    align = 32;
-
-    /* Optional byte order (`le`, `be`, `native` or `network`). `native`
-     * will use the byte order specified by the `trace.byte_order`.
-     * Default is `native`.
-     */
-    byte_order = le;
-}
+| Property | Type | Description | Required? | Default value |
+|---|---|---|---|---|
+| `freq` | Integer (positive) | Frequency (Hz) | Optional | 1000000000 |
+| `description` | String | Description | Optional | No description |
+| `uuid` | String (UUID canonical format) | UUID (unique identifier of this clock) | Optional | No UUID |
+| `error-cycles` | Integer (zero or positive) | Error (uncertainty) of clock in clock cycles | Optional | 0 |
+| `offset` | [Clock offset object](#clock-offset-object) | Offset | Optional | Default clock offset object |
+| `absolute` | Boolean | Absolute clock | Optional | `false` |
+| `return-ctype` | String | Return C type of the associated clock callback | Optional | `uint32_t` |
+
+The `return-ctype` property must be set to a valid C integer type
+(or valid type definition). This is not currently validated by barectf
+itself, but the C compiler will fail to compile the generated C code
+if the clock's return type is not a valid C integer type.
+
+**Example**:
+
+```yaml
+freq: 2450000000
+description: CCLK/A2 (System clock, A2 clock domain)
+uuid: 184883f6-6b6e-4bfd-bcf7-1e45c055c56a
+error-cycles: 23
+offset:
+  seconds: 1434072888
+  cycles: 2003912
+absolute: false
+return-ctype: unsigned long long
 ```
 
-If a CTF floating point number is defined with an 8-bit exponent, a 24-bit
-mantissa and a 32-bit alignment, its barectf C function parameter type will
-be `float`. It will be `double` for an 11-bit exponent, 53-bit mantissa
-and 64-bit aligned CTF floating point number. Any other configuration
-will produce a `uint64_t` function parameter (you will need to cast your
-custom floating point number to this when calling the tracing function).
 
+##### Clock offset object
 
-##### strings
+An offset in seconds and clock cycles from the Unix epoch.
 
-CTF strings are pretty simple to define:
+**Properties**:
 
-```
-string
+| Property | Type | Description | Required? | Default value |
+|---|---|---|---|---|
+| `seconds` | Integer (zero or positive) | Seconds since the Unix epoch | Optional | 0 |
+| `cycles` | Integer (zero or positive) | Clock cycles since the Unix epoch plus the value of the `seconds` property | Optional | 0 |
+
+**Example**:
+
+```yaml
+seconds: 1435617321
+cycles: 194570
 ```
 
-They may also have an encoding property:
 
+#### Trace object
+
+Metadata common to the whole trace.
+
+**Properties**:
+
+| Property | Type | Description | Required? | Default value |
+|---|---|---|---|---|
+| `byte-order` | String | Native byte order (`le` for little-endian or `be` for big-endian) | Required | N/A |
+| `uuid` | String (UUID canonical format or `auto`) | UUID (unique identifier of this trace); automatically generated if value is `auto` | Optional | No UUID |
+| `packet-header-type` | [Type object](#type-objects) or string (alias name) | Type of packet header (must be a [structure type object](#structure-type-object)) | Optional | No packet header |
+
+Each field of the packet header structure type (`packet-header-type` property)
+corresponds to one parameter
+of the generated packet opening function (prefixed with `tph_`), except for the
+following special fields, which are automatically written if present:
+
+  * `magic` (32-bit unsigned [integer type object](#integer-type-object)):
+    packet magic number
+  * `uuid` ([array type object](#array-type-object) of 8-bit unsigned
+    [integer type objects](#integer-type-object), of length 16):
+    trace UUID (`uuid` property of trace object must be set)
+  * `stream_id` (unsigned [integer type object](#integer-type-object)):
+    stream ID
+
+As per CTF 1.8, the `stream_id` field is mandatory if there's more
+than one defined stream.
+
+**Example**:
+
+```yaml
+byte-order: le
+uuid: auto
+packet-header-type:
+  class: struct
+  fields:
+    magic: uint32
+    uuid:
+      class: array
+      length: 16
+      element-type: uint8
+    stream_id: uint16
 ```
-string {
-    // encoding: `none`, `UTF8` or `ASCII`; default is `none`
-    encoding = UTF8;
-}
+
+
+#### Stream object
+
+A CTF stream.
+
+**Properties**:
+
+| Property | Type | Description | Required? | Default value |
+|---|---|---|---|---|
+| `packet-context-type` | [Type object](#type-objects) or string (alias name) | Type of packet context (must be a [structure type object](#structure-type-object)) | Required | N/A |
+| `event-header-type` | [Type object]((#type-objects)) or string (alias name) | Type of event header (must be a [structure type object](#structure-type-object)) | Optional | No event header |
+| `event-context-type` | [Type object]((#type-objects)) or string (alias name) | Type of stream event context (must be a [structure type object](#structure-type-object)) | Optional | No stream event context |
+| `events` | Associative array of event names (string) to [event objects](#event-object) | Stream events | Required | N/A |
+
+Each field of the packet context structure type (`packet-context-type` property)
+corresponds to one parameter
+of the generated packet opening function (prefixed with `spc_`), except for the
+following special fields, which are automatically written if present:
+
+  * `timestamp_begin` and `timestamp_end` (unsigned
+    [integer type objects](#integer-type-object), with
+    a clock value property mapping): resp. open and close timestamps
+  * `packet_size` (unsigned [integer type object](#integer-type-object),
+    mandatory): packet size
+  * `content_size` (unsigned [integer type object](#integer-type-object),
+    mandatory): content size
+  * `events_discarded` (unsigned [integer type object](#integer-type-object)):
+    number of discarded events so far
+
+The `timestamp_end` field must exist if the `timestamp_begin` field exists,
+and vice versa.
+
+Each field of the event header structure type (`event-header-type` property)
+corresponds to one parameter of the generated tracing function
+(prefixed with `eh_`) (for a given event), except for the following special
+fields, which are automatically written if present:
+
+  * `id` (unsigned [integer type object](#integer-type-object)): event ID
+  * `timestamp` (unsigned [integer type object](#integer-type-object), with
+    a clock value property mapping): event timestamp
+
+The `id` field must exist if there's more than one defined event in the
+stream.
+
+Each field of the stream event context structure type (`event-context-type`
+property) corresponds to one parameter of the generated tracing function
+(prefixed with `seh_`) (for a given event).
+
+Each field name of the `packet-context-type`, `event-header-type`,
+and `event-context-type` properties must be a valid C identifier.
+
+The `events` property must contain at least one entry.
+
+**Example**:
+
+```yaml
+packet-context-type:
+  class: struct
+  fields:
+    timestamp_begin: clock-int
+    timestamp_end: clock-int
+    packet_size: uint32
+    content_size: uint32
+    events_discarded: uint16
+    my_custom_field: int12
+event-header-type:
+  class: struct
+  fields:
+    id: uint16
+    timestamp: clock-int
+event-context-type:
+  class: struct
+  fields:
+    obj_id: uint8
+events:
+  msg_in:
+    payload-type: msg-type
 ```
 
-CTF strings are always byte-aligned.
 
-A CTF string field will make barectf produce a corresponding C function
-parameter of type `const char*`. Bytes will be copied from this pointer
-until a byte of value 0 is found (which will also be written to the
-buffer to mark the end of the recorded string).
+#### Event object
 
+A CTF event.
 
-##### enumerations
+**Properties**:
 
-CTF enumerations associate labels to ranges of integer values. They
-are a great way to trace named states using an integer. Here's an
-example:
+| Property | Type | Description | Required? | Default value |
+|---|---|---|---|---|
+| `log-level` | String (predefined log level name) or integer (zero or positive) | Log level of this event | Optional | No log level |
+| `context-type` | [Type object](#type-objects) or string (alias name) | Type of event context (must be a [structure type object](#structure-type-object)) | Optional | No event context |
+| `payload-type` | [Type object](#type-objects) or string (alias name) | Type of event payload (must be a [structure type object](#structure-type-object)) | Required | N/A |
 
-```
-enum : uint32_t {
-    ZERO,
-    ONE,
-    TWO,
-    TEN = 10,
-    ELEVEN,
-    "label with spaces",
-    RANGE = 23 ... 193
-}
+Available log level names, for a given event, are defined by the
+`log-levels` property of the [metadata object](#metadata-object)
+containing it.
+
+Each field of the event context structure type (`context-type` property)
+corresponds to one parameter
+of the generated tracing function (prefixed with `ec_`).
+
+Each field of the event payload structure type (`payload-type` property)
+corresponds to one parameter
+of the generated tracing function (prefixed with `ep_`). The event
+payload structure type must contain at least one field.
+
+Each field name of the `context-type` and `payload-type` properties must be a
+valid C identifier.
+
+**Example**:
+
+```yaml
+log-level: error
+context-type:
+  class: struct
+  fields:
+    msg_id: uint16
+payload-type:
+  class: struct
+  fields:
+    src:
+      type: string
+    dst:
+      type: string
+    payload_sz: uint32
 ```
 
-Unless the first entry specifies a value, CTF enumerations are
-always started at 0. They work pretty much like their C counterpart,
-although they support ranges and literal strings as labels.
 
-CTF enumerations are associated with a CTF integer type (`uint32_t`
-above). This identifier must be an existing integer type alias.
+#### Type objects
 
-A CTF enumeration field will make barectf produce a corresponding C
-integer function parameter compatible with the associated CTF integer type.
+Type objects represent CTF types.
 
+**Common properties**:
 
-##### static arrays
+| Property | Type | Description | Required? | Default value |
+|---|---|---|---|---|
+| `class` | String | Type class | Required if `inherit` property is absent | N/A |
+| `inherit` | String | Name of type alias from which to inherit properties | Required if `class` property is absent | N/A |
 
-Structure field names may be followed by a subscripted constant to
-define a static array of the field type:
+The accepted values for the `class` property are:
 
-```
-struct {
-    integer {size = 16;} _field[10];
-}
-```
+| `class` property value | CTF type |
+|---|---|
+| `int`<br>`integer` | Integer type |
+| `flt`<br>`float`<br>`floating-point` | Floating point number type |
+| `enum`<br>`enumeration` | Enumeration type |
+| `str`<br>`string` | String type |
+| `struct`<br>`structure` | Structure type |
+| `array` | Array/sequence types |
+| `var`<br>`variant` | Variant type |
 
-In the above structure, `_field` is a static array of ten 16-bit integers.
+The `inherit` property accepts the name of any previously defined
+type alias. Any propery in a type object that inherits from another
+type object overrides the parent properties as follows:
 
-A CTF static array field will make barectf produce a `const void*` C function
-parameter. Bytes will be copied from this pointer to match the total static
-array size. In the example above, the integer size is 16-bit, thus its
-default alignment is 8-bit, so 20 bytes would be copied.
+  * Booleans, numbers, and strings: value of parent property with
+    the same name is replaced
+  * Arrays: new elements are appended to parent array
+  * Associative arrays: properties sharing the name of parent
+    properties completely replace them; new properties are
+    added to the parent associative array
 
-The inner element of a CTF static array _must be at least byte-aligned_
-(8-bit), either by forcing its alignment, or by ensuring it manually
-when placing fields one after the other. This means the following static
-array is valid for barectf:
 
-```
-struct {
-  // ...
-    integer {size = 5;} _field[10];
-}
-```
+##### Integer type object
 
-as long as the very first 5-bit, 1-bit aligned integer element starts
-on an 8-bit boundary.
+A CTF integer type.
 
+**Properties**:
 
-##### dynamic arrays
+| Property | Type | Description | Required? | Default value |
+|---|---|---|---|---|
+| `size` | Integer (positive) | Size (bits) (1 to 64) | Required | N/A |
+| `align` | Integer (positive) | Alignment (bits) (power of two) | Optional | 8 if `size` property is a multiple of 8, else 1 |
+| `signed` | Boolean | Signedness | Optional | `false` (unsigned) |
+| `base` | Integer | Display radix (2, 8, 10, or 16) | Optional | 10 |
+| `byte-order` | String | Byte order (`le` for little-endian, `be` for big-endian, or `native` to use the byte order defined at the trace level) | Optional | `native` |
+| `property-mappings` | Array of [property mapping objects](#property-mapping-object) | Property mappings of this integer type | Optional | N/A |
 
-Just like static arrays, dynamic arrays are defined using a subscripted
-length, albeit in this case, this length refers to another field using
-the dot notation. Dynamic arrays are called _sequences_ in the CTF
-specification.
+The `property-mappings` array property currently accepts only one element.
 
-Here's an example:
+**Example**:
 
+```yaml
+class: int
+size: 12
+signed: false
+base: 8
+byte-order: le
+property-mappings:
+  - type: clock
+    name: my_clock
+    property: value
 ```
-struct {
-    uint32_t _length;
-    integer {size = 16;} _field[_length];
-}
-```
 
-In the above structure, `_field` is a dynamic array of `_length`
-16-bit integers.
+**Equivalent C type**:
+
+  * Unsigned: `uint8_t`, `uint16_t`, `uint32_t`, or `uint64_t`, depending on the
+    `size` property
+  * Signed: `int8_t`, `int16_t`, `int32_t`, or `int64_t`, depending on the
+    `size` property
+
+
+###### Property mapping object
+
+A property mapping object associates an integer type with a stateful
+object's property. When the integer type is decoded from a CTF binary
+stream, the associated object's property is updated.
+
+Currently, the only available stateful object's property is the
+current value of a given clock.
 
-There are various scopes to which a dynamic array may refer:
+**Properties**:
 
-  * no prefix: previous field in the same structure, or in parent
-    structures until found
-  * `event.fields.` prefix: field of the event fields
-  * `event.context.` prefix: field of the event context if it exists
-  * `stream.event.context.` prefix: field of the stream event context
-    if it exists
-  * `stream.event.header.` prefix: field of the event header
-  * `stream.packet.context.` prefix: field of the packet context
-  * `trace.packet.header.` prefix: field of the packet header
-  * `env.` prefix: static property of the environment block
+| Property | Type | Description | Required? | Default value |
+|---|---|---|---|---|
+| `type` | String | Object type (always `clock`) | Required | N/A |
+| `name` | String | Clock name | Required | N/A |
+| `property` | String | Clock property name (always `value`) | Required | N/A |
 
-Here's another, more complex example:
+**Example**:
 
+```yaml
+type: clock
+name: my_clock
+property: value
 ```
-struct {
-    uint32_t _length;
-    string _other_field[stream.event.context.length];
-    float _static_array_of_dynamic_arrays[10][_length];
-}
+
+
+##### Floating point number type object
+
+A CTF floating point number type.
+
+**Properties**:
+
+| Property | Type | Description | Required? | Default value |
+|---|---|---|---|---|
+| `size` | [Floating point number type size object](#floating-point-number-type-size-object) | Size parameters | Required | N/A |
+| `align` | Integer (positive) | Alignment (bits) (power of two) | Optional | 8 |
+| `byte-order` | String | Byte order (`le` for little-endian, `be` for big-endian, or `native` to use the byte order defined at the trace level) | Optional | `native` |
+
+**Example**:
+
+```yaml
+class: float
+size:
+  exp: 11
+  mant: 53
+align: 64
+byte-order: be
 ```
 
-The above examples also demonstrates that dynamic arrays and static
-arrays may contain eachother. `_other_field` is a dynamic array of
-`stream.event.context.length` strings. `_static_array_of_dynamic_arrays`
-is a static array of 10 dynamic arrays of `_length` floating point
-numbers. This syntax follows the C language.
+**Equivalent C type**:
 
-A CTF dynamic array field will make barectf produce a `const void*` C function
-parameter. Bytes will be copied from this pointer to match the
-total dynamic array size. The previously recorded length will be
-found automatically (always an offset from the beginning of the
-stream packet, or from the beginning of the current event).
+  * 8-bit exponent, 24-bit mantissa, 32-bit alignment: `float`
+  * 11-bit exponent, 53-bit mantissa, 64-bit alignment: `double`
+  * Every other combination: `uint64_t`
 
-barectf has a few limitations concerning dynamic arrays:
 
-  * The inner element of a CTF dynamic array _must be at least byte-aligned_
-    (8-bit), either by forcing its alignment, or by ensuring it manually
-    when placing fields one after the other.
-  * The length type must be a 32-bit, byte-aligned unsigned integer
-    with a native byte order.
+###### Floating point number type size object
 
+The CTF floating point number type is encoded, in a binary stream,
+following [IEEE 754-2008](https://en.wikipedia.org/wiki/IEEE_floating_point)'s
+interchange format. The required parameters are the exponent and
+significand sizes, in bits. In CTF, the _mantissa_ size includes the
+sign bit, whereas IEEE 754-2008's significand size does not include it.
 
-##### structures
+**Properties**:
 
-Structures contain fields associating a name to a type. The fields
-are recorded in the specified order within the CTF binary stream.
+| Property | Type | Description | Required? | Default value |
+|---|---|---|---|---|
+| `exp` | Integer (positive) | Exponent size (bits) | Required | N/A |
+| `mant` | Integer (positive) | Mantissa size (significand size + 1) (bits) | Required | N/A |
 
-Here's an example:
+As per IEEE 754-2008, the sum of the `exp` and `mant` properties must be a
+multiple of 32.
 
-```
-struct {
-    uint32_t _a;
-    int16_t _b;
-    string {encoding = ASCII;} _c;
-}
-```
+The sum of the `exp` and `mant` properties must be lesser than or equal to 64.
 
-The default alignment of a structure is the largest alignment amongst
-its fields. For example, the following structure has a 32-bit alignment:
+**Example**:
 
-```
-struct {
-    uint16_t _a;             // alignment: 16
-    struct {                 // alignment: 32
-        uint32_t _a;         // alignment: 32
-        string; _b;          // alignment: 8
-    } _b;
-    integer {size = 64;} _c; // alignment: 8
-}
+```yaml
+exp: 8
+mant: 24
 ```
 
-This default alignment may be overridden using a special `align()`
-option after the structure is closed:
 
-```
-struct {
-    uint16_t _a;             // alignment: 16
-    struct {                 // alignment: 32
-        uint32_t _a;         // alignment: 32
-        string; _b;          // alignment: 8
-    } _b;
-    integer {size = 64;} _c; // alignment: 8
-} align(16)
-```
+##### Enumeration type object
 
-You may use structures as field types, although they must have a
-_known size_ when running barectf. This means they cannot contain
-sequences or strings.
+A CTF enumeration type.
 
-A CTF structure field will make barectf produce a `const void*` C function
-parameter. The structure (of known size) will be copied as is to the
-current buffer, respecting its alignment.
+Each label of an enumeration type is mapped to a single value, or to a
+range of values.
 
-Note that barectf requires inner structures to be at least byte-aligned.
+**Properties**:
 
-Be careful when using CTF structures for recording binary structures
-declared in C. You need to make sure your C compiler aligns structure
-fields and adds padding exactly in the way you define your equivalent
-CTF structure. For example, using GCC on the x86 architecture, 3 bytes
-are added after field `a` in the following C structure since `b` is
-32-bit aligned:
+| Property | Type | Description | Required? | Default value |
+|---|---|---|---|---|
+| `value-type` | [Integer type object](#integer-type-object) or string (alias name) | Supporting integer type | Required | N/A |
+| `members` | Array of [enumeration type member objects](#enumeration-type-member-object) | Enumeration members | Required | N/A |
 
-```c
-struct my_struct {
-    char a;
-    unsigned int b;
-};
-```
+The `members` property must contain at least one element. If the member
+is a string, its associated value is computed as follows:
 
-It would be wrong to use the following CTF structure:
+  * If the member is the first one of the `members` array, its value
+    is 0.
+  * If the previous member is a string, its value is the previous
+    member's computed value + 1.
+  * If the previous member is a single value member, its value is
+    the previous member's value + 1.
+  * If the previous member is a range member, its value is the previous
+    member's upper bound + 1.
 
-```
-struct {
-    integer {size = 8; signed = true;} a;
-    integer {size = 32;} b;
-}
-```
+The member values must not overlap each other.
 
-since field `b` is byte-aligned by default. This one would work fine:
+**Example**:
 
-```
-struct {
-    integer {size = 8; signed = true;} a;
-    integer {size = 32; align = 32;} b;
-}
+```yaml
+class: enum
+value-type: uint8
+members:
+  - ZERO
+  - ONE
+  - TWO
+  - label: SIX
+    value: 6
+  - SE7EN
+  - label: TWENTY TO FOURTY
+    value: [10, 40]
+  - FORTY-ONE
 ```
 
-CTF structures can prove very useful for recording protocols with named
-fields when reading the trace. For example, here's the CTF structure
-describing the IPv4 header (excluding options):
+**Equivalent C type**: equivalent C type of supporting integer type
+(see [integer type object documentation](#integer-type-object) above).
 
-```
-struct ipv4_header {
-    integer {size = 4;} version;
-    integer {size = 4;} ihl;
-    integer {size = 6;} dscp;
-    integer {size = 2;} ecn;
-    integer {size = 16; byte_order = network;} total_length;
-    integer {size = 16; byte_order = network;} identification;
-    integer {size = 1;} flag_more_fragment;
-    integer {size = 1;} flag_dont_fragment;
-    integer {size = 1;} flag_reserved;
-    integer {size = 13; byte_order = network;} fragment_offset;
-    integer {size = 8;} ttl;
-    integer {size = 8;} protocol;
-    integer {size = 16; byte_order = network;} header_checksum;
-    integer {size = 8;} src_ip_addr[4];
-    integer {size = 8;} dst_ip_addr[4];
-}
-```
 
-Although this complex structure has more than ten independent fields,
-the generated C function would only call a 20-byte `memcpy()`, making
-it fast to record. Bits will be unpacked properly and values displayed
-in a human-readable form by the CTF reader thanks to the CTF metadata.
+###### Enumeration type member object
 
+The member of a CTF enumeration type.
 
-#### type aliases
+If it's a string, the string is the member's label, and the members's
+value depends on the last member's value (see explanation in
+[enumeration type object documentation](#enumeration-type-object) above).
 
-Type aliases associate a name with a type definition. Any type may have
-any name. They are similar to C `typedef`s.
+Otherwise, it's a complete member object, with the following properties:
 
-Examples:
+| Property | Type | Description | Required? | Default value |
+|---|---|---|---|---|
+| `label` | String | Member's label | Required | N/A |
+| `value` | Integer (single value) or array of two integers (range value) | Member's value | Required | N/A |
 
-```
-typealias integer {
-    size = 16;
-    align = 4;
-    signed = true;
-    byte_order = network;
-    base = hex;
-    encoding = UTF8;
-} := my_int;
-```
+If the `value` property is an array of two integers, the member's label is
+associated to this range, both lower and upper bounds included. The array's
+first element must be lesser than or equal to the second element.
 
-```
-typealias floating_point {
-    exp_dig = 8;
-    mant_dig = 8;
-    align = 16;
-    byte_order = be;
-} := my_float;
-```
+**Example**:
 
+```yaml
+label: my enum label
+value: [-25, 78]
 ```
-typealias string {
-    encoding = ASCII;
-} := my_string;
+
+
+##### String type object
+
+A CTF null-terminated string type.
+
+This object has no properties.
+
+**Example**:
+
+```yaml
+class: string
 ```
 
+**Equivalent C type**: `const char *`.
+
+
+##### Array type object
+
+A CTF array or sequence (variable-length array) type.
+
+**Properties**:
+
+| Property | Type | Description | Required? | Default value |
+|---|---|---|---|---|
+| `element-type` | [Type object](#type-objects) or string (alias name) | Type of array's elements | Required | N/A |
+| `length` | Positive integer (static array) or string (variable-length array) | Array type's length | Required | N/A |
+
+If the `length` property is a string, the array type has a
+variable length (CTF sequence). In this case, the property's value
+refers to a previous structure field. The `length` property's value
+may be prefixed with one of the following strings to indicate an
+absolute lookup within a previous (or current) dynamic scope:
+
+  * `trace.packet.header.`: trace packet header
+  * `stream.packet.context.`: stream packet context
+  * `stream.event.header.`: stream event header
+  * `stream.event.context.`: stream event context
+  * `event.context.`: event context
+  * `event.payload.`: event payload
+
+The pointed field must have an unsigned integer type.
+
+**Example** (16 bytes):
+
+```yaml
+class: array
+length: 16
+element-type:
+  class: int
+  size: 8
 ```
-typealias enum : uint32_t {
-    ZERO,
-    ONE,
-    TWO,
-    TEN = 10,
-    ELEVEN,
-    "label with spaces",
-    RANGE = 23 ... 193
-} := my_enum;
+
+**Example** (variable-length array of null-terminated strings):
+
+```yaml
+class: array
+length: previous_field
+element-type:
+  class: string
 ```
 
+
+##### Structure type object
+
+A CTF structure type, i.e. a list of fields, each field
+having a name and a CTF type.
+
+**Properties**:
+
+| Property | Type | Description | Required? | Default value |
+|---|---|---|---|---|
+| `min-align` | Integer (positive) | Minimum alignment (bits) (power of two) | Optional | 1 |
+| `fields` | Associative array of field names (string) to [type objects](#type-objects) or strings (alias names) | Structure type's fields | Optional | `{}` |
+
+The order of the entries in the `fields` property is important; it is in
+this order that the fields are serialized in binary streams.
+
+**Example**:
+
+```yaml
+class: struct
+min-align: 32
+fields:
+  msg_id: uint8
+  src:
+    class: string
+  dst:
+    class: string
 ```
-typealias struct {
-    uint32_t _length;
-    string _other_field;
-    float _hello[10][_length];
-} align(8) := my_struct;
+
+
+##### Variant type object
+
+A CTF variant type, i.e. a tagged union of CTF types.
+
+**Properties**:
+
+| Property | Type | Description | Required? | Default value |
+|---|---|---|---|---|
+| `tag` | String | Variant type's tag | Required | N/A |
+| `types` | Associative array of strings to [type objects](#type-objects) or strings (alias names) | Possible types | Required | N/A |
+
+The `tag` property's value refers to a previous structure field.
+The value may be prefixed with one of the following strings to indicate
+an absolute lookup within a previous (or current) dynamic scope:
+
+  * `trace.packet.header.`: trace packet header
+  * `stream.packet.context.`: stream packet context
+  * `stream.event.header.`: stream event header
+  * `stream.event.context.`: stream event context
+  * `event.context.`: event context
+  * `event.payload.`: event payload
+
+The pointed field must have an enumeration type. Each type name in the
+`types` property must have its equivalent member's label in this
+enumeration type. This is how a variant's type is selected using the
+value of its tag.
+
+**Example**:
+
+```yaml
+class: variant
+tag: my_choice
+types:
+  a:
+    class: string
+  b: int32
+  c:
+    class: float
+    size:
+      align: 32
+      exp: 8
+      mant: 24
 ```
 
 
-### running the `barectf` command
+### Running the `barectf` command
 
 Using the `barectf` command-line utility is easy. In its simplest form,
-it outputs a few C99 files out of a CTF metadata file:
+it outputs a CTF metadata file and a few C files out of a
+YAML configuration file:
 
-    barectf metadata
+    barectf config.yaml
 
-will output in the current working directory:
+will output, in the current working directory:
 
-  * `barectf_bitfield.h`: macros used by tracing functions to pack bits
+  * `metadata`: CTF metadata file
+  * `barectf-bitfield.h`: macros used by tracing functions to pack bits
   * `barectf.h`: other macros and prototypes of context/tracing functions
   * `barectf.c`: context/tracing functions
 
-You may also want to produce `static inline` functions if your target
-system has enough memory to hold the extra code:
-
-    barectf --static-inline metadata
+`barectf_` is the default name of the files and the default prefix of
+barectf C functions and structures. The prefix is read from the
+configuration file (see the
+[configuration object documentation](#configuration-object)), but
+you may override it on the command line:
 
-`barectf` is the default name of the files and the default prefix of
-barectf C functions and structures. You may use a custom prefix:
-
-    barectf --prefix trace metadata
+    barectf --prefix my_app_ config.yaml
 
 You may also output the files elsewhere:
 
-    barectf --output /custom/path metadata
+    barectf --code-dir src --headers-dir include --metadata-dir ctf config.yaml
+
 
-### using the generated C99 code
+### Using the generated C code
 
 This section assumes you ran `barectf` with no options:
 
-    barectf metadata
+    barectf config.yaml
 
-The command generates C99 structures and functions to initialize
-and finalize bare CTF contexts. It also generates as many tracing functions
-as there are events described in the CTF metadata file.
+The command generates C structures and functions to initialize
+barectf contexts, open packets, and close packets. It also generates as many
+tracing functions as there are events defined in the YAML configuration
+file.
 
-Before starting the record events, you must initialize a barectf
-context. This is done using `barectf_init()`.
+An application should never have to initialize barectf contexts,
+open packets, or close packets; this is the purpose of a specific barectf
+platform, which wraps those calls in its own initialization and
+finalization functions.
 
-The clock callback parameter (`clock_cb`) is used to get the clock whenever
-a tracing function is called. Each platform has its own way of obtaining
-the a clock value, so this is left to user implementation. The actual
-return type of the clock callback depends on the clock value CTF integer
-type defined in the CTF metadata.
+The barectf project provides a few platforms in the [`platforms`](platforms)
+directory. Each one contains a `README.md` file explaining how to use
+the platform. If you're planning to write your own platform,
+read the next subsection. Otherwise, skip it.
 
-The `barectf_init()` function name will contain the decimal stream
-ID if you have more than one stream. You must allocate the context
-structure yourself.
 
-Example:
+#### Writing a barectf platform
 
-```c
-struct barectf_ctx* barectf_ctx = platform_alloc(sizeof(*barectf_ctx));
+A **_barectf platform_** is responsible for:
 
-barectf_init(barectf_ctx, buf, 8192, platform_get_clock, NULL);
-```
+  1. Providing some initialization and finalization functions
+     for the tracing infrastructure of the target. The initialization
+     function is responsible for initializing a barectf context,
+     providing the platform callback functions, and for opening the very
+     first stream packet(s). The finalization function is responsible
+     for closing, usually when not empty, the very last stream
+     packet(s).
+  2. Implementing the platform callback functions to accomodate the target
+     system. The main purposes of those callback functions are:
+     * Getting the current value of clock(s).
+     * Doing something with a packet once it's full. This is how
+       a ring buffer of packets may be implemented. The platform
+       may also be naive and write the full packets to the file system
+       directly.
 
-This initializes a barectf context with a buffer of 8192 bytes.
+Thus, the traced application itself should never have to call
+the barectf initialization, packet opening, and packet closing
+funcions. The application only deals with initializing/finalizing
+the platform, and calling the tracing functions.
 
-After the barectf context is initialized, open a packet using
-`barectf_open_packet()`. If you have any non-special fields in
-your stream packet context, `barectf_open_packet()` accepts a
-parameter for each of them since the packet context is written
-at this moment:
+The following diagram shows how each part connects with
+each other:
 
-```
-barectf_open_packet(barectf_ctx);
-```
+![](http://0x3b.org/ss/placoderm625.png)
+
+The following subsections explain what should exist in each
+platform function.
 
-Once the packet is opened, you may call any of the tracing functions to record
-CTF events into the context's buffer.
 
-As an example, let's take the following CTF event definition:
+##### Platform initialization function
 
+A barectf platform initialization function is responsible for
+initializing barectf context(s) (calling `barectf_init()`,
+where `barectf_` is the configured prefix), and opening the very
+first packet (calling `barectf_stream_open_packet()` with
+target-specific parameters, for each stream, where `stream` is
+the stream name).
+
+barectf generates one context C structure for each defined stream.
+They all contain the same first member, a structure with common
+properties.
+
+barectf generates a single context initialization function:
+
+```c
+void barectf_init(
+    void *ctx,
+    uint8_t *buf,
+    uint32_t buf_size,
+    struct barectf_platform_callbacks cbs,
+    void *data
+);
 ```
-event {
-    name = "my_event";
-    id = 0;
-    stream_id = 0;
-    fields := struct {
-        integer {size = 32;} _a;
-        integer {size = 14; signed = true;} _b;
-        floating_point {exp_dig = 8; mant_dig = 24; align = 32;} _c;
-        struct {
-            uint32_t _a;
-            uint32_t _b;
-        } _d;
-        string _e;
+
+This function must be called with each stream-specific context
+structure to be used afterwards. The parameters are:
+
+  * `ctx`: stream-specific barectf context (allocated by caller)
+  * `buf`: buffer to use for this stream's packet (allocated by caller)
+  * `buf_size`: size of `buf` in bytes
+  * `cbs`: platform callback functions to be used with this
+    stream-specific context
+  * `data`: user data passed to platform callback functions (`cbs`)
+
+**Example**:
+
+```c
+#define BUF_SZ 4096
+
+void platform_init(/* ... */)
+{
+    struct barectf_my_stream_ctx *ctx;
+    uint8_t *buf;
+    struct my_data *my_data;
+    struct barectf_platform_callbacks cbs = {
+        /* ... */
     };
-};
+
+    ctx = platform_alloc(sizeof(*ctx));
+    buf = platform_alloc(BUF_SZ);
+    my_data = platform_alloc(sizeof(*my_data));
+    my_data->ctx = ctx;
+    barectf_init(ctx, buf, BUF_SZ, cbs, my_data);
+
+    /* ... */
+}
 ```
 
-In this example, we assume the stream event context and the event context
-are not defined for this event. `barectf` generates the following tracing
-function prototype:
+barectf generates one packet opening and one packet closing
+function per defined stream, since each stream may have custom
+parameters at the packet opening time, and custom offsets of
+fields to write at packet closing time.
+
+The platform initialization should open the very first packet
+of each stream to use because the tracing functions expect the
+current packet to be opened.
+
+Here's an example of a packet opening function prototype:
 
 ```c
-int barectf_trace_my_event(
-    struct barectf_ctx* ctx,
-    uint32_t param_ef__a,
-    int16_t param_ef__b,
-    float param_ef__c,
-    const void* param_ef__d,
-    const char* param_ef__e
+void barectf_my_stream_open_packet(
+    struct barectf_my_stream_ctx *ctx,
+    float spc_something
 );
 ```
 
-When called, this function first calls the clock callback to get a clock
-value as soon as possible. It then proceeds to record each field with
-proper alignment and updates the barectf context. On success, 0 is returned.
-Otherwise, one of the following negative errors is returned:
+The function needs the stream-specific barectf context, as well as any
+custom trace packet header or stream packet context field; in this
+last example, `something` is a floating point number stream packet context
+field.
+
+
+##### barectf packet information API
+
+There's a small API to query stuff about the current packet of a
+given barectf context:
+
+```c
+uint32_t barectf_packet_size(void *ctx);
+int barectf_packet_is_full(void *ctx);
+int barectf_packet_is_empty(void *ctx);
+uint32_t barectf_packet_events_discarded(void *ctx);
+uint8_t *barectf_packet_buf(void *ctx);
+void barectf_packet_set_buf(void *ctx, uint8_t *buf, uint32_t buf_size);
+uint32_t barectf_packet_buf_size(void *ctx);
+int barectf_packet_is_open(void *ctx);
+```
+
+`barectf_packet_is_full()` returns 1 if the context's current packet
+is full (no space left for any event), 0 otherwise.
+
+`barectf_packet_is_empty()` returns 1 if the context's current packet
+is empty (no recorded events), 0 otherwise.
+
+`barectf_packet_events_discarded()` returns the number of lost (discarded)
+events _so far_ for a given stream.
+
+The buffer size (`buf_size` parameter of `barectf_packet_set_buf()` and
+return value of `barectf_packet_buf_size()`) is always a number of bytes.
+
+`barectf_packet_is_open()` returns 1 if the context's current packet
+is open (the packet opening function was called with this context).
+
+
+##### Platform callback functions
+
+The callback functions to implement for a given platform are
+in the generated `barectf_platform_callbacks` C structure. This
+structure will contain:
+
+  * One callback function per defined clock, using the clock's
+    return C type. Those functions must return the current clock
+    values.
+  * `is_backend_full()`: is the back-end full? If a new packet
+    is opened now, does it have its reserved space in the back-end?
+    Return 0 if it does, 1 otherwise.
+  * `open_packet()`: this callback function **must** call the relevant
+    packet opening function.
+  * `close_packet()`: this callback function **must** call the
+    relevant packet closing function _and_ copy/move the current packet
+    to the back-end.
+
+What exactly is a _back-end_ is left to the platform implementor. It
+could be a ring buffer of packets, or it could be dumber: `close_packet()`
+always appends the current packet to some medium, and `is_backend_full()`
+always returns 0 (back-end is never full).
+
+Typically, if `is_backend_full()` returns 0, then the next
+call to `close_packet()` should be able to write the current packet.
+If `is_backend_full()` returns 1, there will be lost (discarded)
+events. If a stream packet context has an `events_discarded` field,
+it will be written to accordingly when a packet is closed.
+
+If a platform needs double buffering, `open_packet()` is the callback
+function where packet buffers would be swapped (before calling
+the barectf packet opening function).
+
+
+##### Platform finalization function
+
+The platform finalization function should be called by the application
+when tracing is no more required. It is responsible for closing the
+very last packet of each stream.
+
+Typically, assuming there's only one stream (named `my_stream` in this
+example), the finalization function will look like this:
+
+```c
+void platform_tracing_finalize(struct platform_data *platform_data)
+{
+    if (barectf_packet_is_open(platform_data->ctx) &&
+            !barectf_packet_is_empty(platform_data->ctx)) {
+        barectf_my_stream_close_packet(platform_data->ctx);
+
+        /*
+         * Do whatever is necessary here to write the packet
+         * to the platform's back-end.
+         */
+    }
+}
+```
+
+That is: if the packet is still open (thus not closed and written yet)
+_and_ it contains at least one event (not empty), close and write the last
+packet.
+
+Note, however, that you might be interested in closing an open empty
+packet, since its packet context could update the discarded events count
+(if there were lost events between the last packet closing time and
+now, which is quite possible if the back-end became full after closing
+and writing the previous packet).
+
+
+#### Calling the generated tracing functions
+
+Calling the generated tracing functions is what the traced application
+actually does.
+
+For a given prefix named `barectf`, a given stream named `stream`, and
+a given event named `event`, the generated tracing function name is
+`barectf_stream_trace_event()`.
+
+The first parameter of a tracing function is always the stream-specific
+barectf context. Then, in this order:
+
+  * One parameter for each custom event header field
+    (prefixed with `seh_`)
+  * One parameter for each custom stream event context field
+    (prefixed with `sec_`)
+  * One parameter for each custom event context field
+    (prefixed with `ec_`)
+  * One parameter for each custom event payload field
+    (prefixed with `ep_`)
+
+A tracing function returns nothing: it either succeeds (the event
+is serialized in the current packet) or fails when there's no
+space left (the context's discarded events count is incremented).
+
+**Example**:
+
+Given the following [event object](#event-object), named `my_event`,
+placed in a stream named `default` with no custom event header/stream event
+context fields:
+
+```yaml
+context-type:
+  class: struct
+  fields:
+    msg_id:
+      class: int
+      size: 16
+payload-type:
+  class: struct
+  fields:
+    src:
+      class: string
+    dst:
+      class: string
+    a_id:
+      class: int
+      size: 3
+    b_id:
+      class: int
+      size: 7
+      signed: true
+    c_id:
+      class: int
+      size: 15
+    amt:
+      class: float
+      align: 32
+      size:
+        exp: 8
+        mant: 24
+```
 
-  * `-EBARECTF_NOSPC`: no space left in the context's buffer; the event
-    was **not** recorded. You should call `barectf_close_packet()` to finalize the
-    CTF packet.
+barectf will generate the following tracing function prototype:
 
-`barectf_close_packet()` may be called at any time.
-When `barectf_close_packet()` returns, the packet is complete and ready
-to be read by a CTF reader. CTF packets may be concatenated in a single
-CTF stream file. You may reuse the same context and buffer to record another
-CTF packet, as long as you call `barectf_open_packet()` before calling any
-tracing function.
+```c
+/* trace (stream "default", event "my_event") */
+void barectf_default_trace_my_event(
+    struct barectf_default_ctx *ctx,
+    uint16_t ec_msg_id,
+    const char *ep_src,
+    const char *ep_dst,
+    uint8_t ep_a_id,
+    int8_t ep_b_id,
+    uint16_t ep_c_id,
+    float amt
+);
+```
 
 
-### reading CTF traces
+### Reading CTF traces
 
-To form a complete CTF trace, put your CTF metadata file (it should be
-named `metadata`) and your binary stream files (concatenations of CTF
-packets written by C code generated by barectf) in the same directory.
+To form a complete CTF trace, the `metadata` file generated by the
+`barectf` command-line tool and the binary stream files generated
+by the application (or by an external consumer, depending on the
+platform) should be placed in the same directory.
 
 To read a CTF trace, use [Babeltrace](http://www.efficios.com/babeltrace).
-Babeltrace is packaged by most major distributions (`babeltrace`).
-Babeltrace ships with a command-line utility that can convert a CTF trace
-to human-readable text output. Also, it includes a Python binding so
-that you may analyze a CTF trace using a custom script.
+Babeltrace is packaged by most major distributions as the `babeltrace`
+package. Babeltrace ships with a command-line utility that can convert a
+CTF trace to human-readable text output. Also, it includes Python bindings
+so that you may analyze a CTF trace using a custom script.
 
 In its simplest form, the `babeltrace` command-line converter is quite
 easy to use:
 
     babeltrace /path/to/directory/containing/ctf/files
 
-See `babeltrace --help` for more options.
-
-You may also use the Python 3 binding of Babeltrace to create custom
-analysis scripts.
+See `babeltrace --help` and `man babeltrace` for more options.
This page took 0.03972 seconds and 4 git commands to generate.