aboutsummaryrefslogtreecommitdiff
path: root/doc/api.rst
diff options
context:
space:
mode:
Diffstat (limited to 'doc/api.rst')
-rw-r--r--doc/api.rst1702
1 files changed, 1702 insertions, 0 deletions
diff --git a/doc/api.rst b/doc/api.rst
new file mode 100644
index 000000000000..8a9b7bb5cefe
--- /dev/null
+++ b/doc/api.rst
@@ -0,0 +1,1702 @@
+.. index:: API
+
+The libxo API
+=============
+
+This section gives details about the functions in libxo, how to call
+them, and the actions they perform.
+
+.. index:: Handles
+.. _handles:
+
+Handles
+-------
+
+libxo uses "handles" to control its rendering functionality. The
+handle contains state and buffered data, as well as callback functions
+to process data.
+
+Handles give an abstraction for libxo that encapsulates the state of a
+stream of output. Handles have the data type "`xo_handle_t`" and are
+opaque to the caller.
+
+The library has a default handle that is automatically initialized.
+By default, this handle will send text style output (`XO_STYLE_TEXT`) to
+standard output. The xo_set_style and xo_set_flags functions can be
+used to change this behavior.
+
+For the typical command that is generating output on standard output,
+there is no need to create an explicit handle, but they are available
+when needed, e.g., for daemons that generate multiple streams of
+output.
+
+Many libxo functions take a handle as their first parameter; most that
+do not use the default handle. Any function taking a handle can be
+passed NULL to access the default handle. For the convenience of
+callers, the libxo library includes handle-less functions that
+implicitly use the default handle.
+
+For example, the following are equivalent::
+
+ xo_emit("test");
+ xo_emit_h(NULL, "test");
+
+Handles are created using `xo_create` and destroy using
+`xo_destroy`.
+
+.. index:: xo_create
+
+xo_create
+~~~~~~~~~
+
+.. c:function:: xo_handle_t *xo_create (xo_style_t style, xo_xof_flags_t flags)
+
+ The `xo_create` function allocates a new handle which can be passed
+ to further libxo function calls. The `xo_handle_t` structure is
+ opaque.
+
+ :param xo_style_t style: Output style (XO_STYLE\_*)
+ :param xo_xof_flags_t flags: Flags for this handle (XOF\_*)
+ :return: New libxo handle
+ :rtype: xo_handle_t \*
+
+ ::
+
+ EXAMPLE:
+ xo_handle_t *xop = xo_create(XO_STYLE_JSON, XOF_WARN | XOF_PRETTY);
+ ....
+ xo_emit_h(xop, "testing\n");
+
+ See also :ref:`output-styles` and :ref:`flags`.
+
+.. index:: xo_create_to_file
+.. index:: XOF_CLOSE_FP
+
+xo_create_to_file
+~~~~~~~~~~~~~~~~~
+
+.. c:function::
+ xo_handle_t *xo_create_to_file (FILE *fp, unsigned style, unsigned flags)
+
+ The `xo_create_to_file` function is aconvenience function is
+ provided for situations when output should be written to a different
+ file, rather than the default of standard output.
+
+ The `XOF_CLOSE_FP` flag can be set on the returned handle to trigger a
+ call to fclose() for the FILE pointer when the handle is destroyed,
+ avoiding the need for the caller to perform this task.
+
+ :param fp: FILE to use as base for this handle
+ :type fp: FILE *
+ :param xo_style_t style: Output style (XO_STYLE\_*)
+ :param xo_xof_flags_t flags: Flags for this handle (XOF\_*)
+ :return: New libxo handle
+ :rtype: xo_handle_t \*
+
+.. index:: xo_set_writer
+.. index:: xo_write_func_t
+.. index:: xo_close_func_t
+.. index:: xo_flush_func_t
+
+xo_set_writer
+~~~~~~~~~~~~~
+
+.. c:function::
+ void xo_set_writer (xo_handle_t *xop, void *opaque, \
+ xo_write_func_t write_func, xo_close_func_t close_func, \
+ xo_flush_func_t flush_func)
+
+ The `xo_set_writer` function allows custom functions which can
+ tailor how libxo writes data. The `opaque` argument is recorded and
+ passed back to the functions, allowing the function to acquire
+ context information. The *write_func* function writes data to the
+ output stream. The *close_func* function can release this opaque
+ data and any other resources as needed. The *flush_func* function
+ is called to flush buffered data associated with the opaque object.
+
+ :param xop: Handle to modify (or NULL for default handle)
+ :type xop: xo_handle_t *
+ :param opaque: Pointer to opaque data passed to the given functions
+ :type opaque: void *
+ :param xo_write_func_t write_func: New write function
+ :param xo_close_func_t close_func: New close function
+ :param xo_flush_func_t flush_func: New flush function
+ :returns: void
+
+.. index:: xo_get_style
+
+xo_get_style
+~~~~~~~~~~~~
+
+.. c:function:: xo_style_t xo_get_style(xo_handle_t *xop)
+
+ Use the `xo_get_style` function to find the current output style for
+ a given handle. To use the default handle, pass a `NULL` handle.
+
+ :param xop: Handle to interrogate (or NULL for default handle)
+ :type xop: xo_handle_t *
+ :returns: Output style (XO_STYLE\_*)
+ :rtype: xo_style_t
+
+ ::
+
+ EXAMPLE::
+ style = xo_get_style(NULL);
+
+.. index:: XO_STYLE_TEXT
+.. index:: XO_STYLE_XML
+.. index:: XO_STYLE_JSON
+.. index:: XO_STYLE_HTML
+
+.. _output-styles:
+
+Output Styles (XO_STYLE\_\*)
+++++++++++++++++++++++++++++
+
+The libxo functions accept a set of output styles:
+
+ =============== =========================
+ Flag Description
+ =============== =========================
+ XO_STYLE_TEXT Traditional text output
+ XO_STYLE_XML XML encoded data
+ XO_STYLE_JSON JSON encoded data
+ XO_STYLE_HTML HTML encoded data
+ =============== =========================
+
+The "XML", "JSON", and "HTML" output styles all use the UTF-8
+character encoding. "TEXT" using locale-based encoding.
+
+.. index:: xo_set_style
+
+xo_set_style
+~~~~~~~~~~~~
+
+.. c:function:: void xo_set_style(xo_handle_t *xop, xo_style_t style)
+
+ The `xo_set_style` function is used to change the output style
+ setting for a handle. To use the default handle, pass a `NULL`
+ handle.
+
+ :param xop: Handle to modify
+ :type xop: xo_handle_t *
+ :param xo_style_t style: Output style (XO_STYLE\_*)
+ :returns: void
+
+ ::
+
+ EXAMPLE:
+ xo_set_style(NULL, XO_STYLE_XML);
+
+.. index:: xo_set_style_name
+
+xo_set_style_name
+~~~~~~~~~~~~~~~~~
+
+.. c:function:: int xo_set_style_name (xo_handle_t *xop, const char *style)
+
+ The `xo_set_style_name` function can be used to set the style based
+ on a name encoded as a string: The name can be any of the supported
+ styles: "text", "xml", "json", or "html".
+
+ :param xop: Handle for modify (or NULL for default handle)
+ :type xop: xo_handle_t \*
+ :param style: Text name of the style
+ :type style: const char \*
+ :returns: zero for success, non-zero for error
+ :rtype: int
+
+ ::
+
+ EXAMPLE:
+ xo_set_style_name(NULL, "html");
+
+.. index:: xo_set_flags
+
+xo_set_flags
+~~~~~~~~~~~~
+
+.. c:function:: void xo_set_flags(xo_handle_t *xop, xo_xof_flags_t flags)
+
+ :param xop: Handle for modify (or NULL for default handle)
+ :type xop: xo_handle_t \*
+ :param xo_xof_flags_t flags: Flags to add for the handle
+ :returns: void
+
+ Use the `xo_set_flags` function to turn on flags for a given libxo
+ handle. To use the default handle, pass a `NULL` handle.
+
+ ::
+
+ EXAMPLE:
+ xo_set_flags(NULL, XOF_PRETTY | XOF_WARN);
+
+.. index:: Flags; XOF_*
+.. index:: XOF_CLOSE_FP
+.. index:: XOF_COLOR
+.. index:: XOF_COLOR_ALLOWED
+.. index:: XOF_DTRT
+.. index:: XOF_INFO
+.. index:: XOF_KEYS
+.. index:: XOF_NO_ENV
+.. index:: XOF_NO_HUMANIZE
+.. index:: XOF_PRETTY
+.. index:: XOF_UNDERSCORES
+.. index:: XOF_UNITS
+.. index:: XOF_WARN
+.. index:: XOF_WARN_XML
+.. index:: XOF_XPATH
+.. index:: XOF_COLUMNS
+.. index:: XOF_FLUSH
+
+.. _flags:
+
+Flags (XOF\_\*)
++++++++++++++++
+
+The set of valid flags include:
+
+ =================== =========================================
+ Flag Description
+ =================== =========================================
+ XOF_CLOSE_FP Close file pointer on `xo_destroy`
+ XOF_COLOR Enable color and effects in output
+ XOF_COLOR_ALLOWED Allow color/effect for terminal output
+ XOF_DTRT Enable "do the right thing" mode
+ XOF_INFO Display info data attributes (HTML)
+ XOF_KEYS Emit the key attribute (XML)
+ XOF_NO_ENV Do not use the :ref:`libxo-options` env var
+ XOF_NO_HUMANIZE Display humanization (TEXT, HTML)
+ XOF_PRETTY Make "pretty printed" output
+ XOF_UNDERSCORES Replaces hyphens with underscores
+ XOF_UNITS Display units (XML, HMTL)
+ XOF_WARN Generate warnings for broken calls
+ XOF_WARN_XML Generate warnings in XML on stdout
+ XOF_XPATH Emit XPath expressions (HTML)
+ XOF_COLUMNS Force xo_emit to return columns used
+ XOF_FLUSH Flush output after each `xo_emit` call
+ =================== =========================================
+
+The `XOF_CLOSE_FP` flag will trigger the call of the *close_func*
+(provided via `xo_set_writer`) when the handle is destroyed.
+
+The `XOF_COLOR` flag enables color and effects in output regardless
+of output device, while the `XOF_COLOR_ALLOWED` flag allows color
+and effects only if the output device is a terminal.
+
+The `XOF_PRETTY` flag requests "pretty printing", which will trigger
+the addition of indentation and newlines to enhance the readability of
+XML, JSON, and HTML output. Text output is not affected.
+
+The `XOF_WARN` flag requests that warnings will trigger diagnostic
+output (on standard error) when the library notices errors during
+operations, or with arguments to functions. Without warnings enabled,
+such conditions are ignored.
+
+Warnings allow developers to debug their interaction with libxo.
+The function `xo_failure` can used as a breakpoint for a debugger,
+regardless of whether warnings are enabled.
+
+If the style is `XO_STYLE_HTML`, the following additional flags can be
+used:
+
+ =============== =========================================
+ Flag Description
+ =============== =========================================
+ XOF_XPATH Emit "data-xpath" attributes
+ XOF_INFO Emit additional info fields
+ =============== =========================================
+
+The `XOF_XPATH` flag enables the emission of XPath expressions detailing
+the hierarchy of XML elements used to encode the data field, if the
+XPATH style of output were requested.
+
+The `XOF_INFO` flag encodes additional informational fields for HTML
+output. See :ref:`field-information` for details.
+
+If the style is `XO_STYLE_XML`, the following additional flags can be
+used:
+
+ =============== =========================================
+ Flag Description
+ =============== =========================================
+ XOF_KEYS Flag "key" fields for XML
+ =============== =========================================
+
+The `XOF_KEYS` flag adds "key" attribute to the XML encoding for
+field definitions that use the "k" modifier. The key attribute has
+the value "key"::
+
+ xo_emit("{k:name}", item);
+
+ XML:
+ <name key="key">truck</name>
+
+.. index:: xo_clear_flags
+
+xo_clear_flags
+++++++++++++++
+
+.. c:function:: void xo_clear_flags (xo_handle_t *xop, xo_xof_flags_t flags)
+
+ :param xop: Handle for modify (or NULL for default handle)
+ :type xop: xo_handle_t \*
+ :param xo_xof_flags_t flags: Flags to clear for the handle
+ :returns: void
+
+ Use the `xo_clear_flags` function to turn off the given flags in a
+ specific handle. To use the default handle, pass a `NULL` handle.
+
+.. index:: xo_set_options
+
+xo_set_options
+++++++++++++++
+
+.. c:function:: int xo_set_options (xo_handle_t *xop, const char *input)
+
+ :param xop: Handle for modify (or NULL for default handle)
+ :type xop: xo_handle_t \*
+ :param input: string containing options to set
+ :type input: const char *
+ :returns: zero for success, non-zero for error
+ :rtype: int
+
+ The `xo_set_options` function accepts a comma-separated list of
+ output styles and modifier flags and enables them for a specific
+ handle. The options are identical to those listed in
+ :ref:`options`. To use the default handle, pass a `NULL` handle.
+
+.. index:: xo_destroy
+
+xo_destroy
+++++++++++
+
+.. c:function:: void xo_destroy(xo_handle_t *xop)
+
+ :param xop: Handle for modify (or NULL for default handle)
+ :type xop: xo_handle_t \*
+ :returns: void
+
+ The `xo_destroy` function releases a handle and any resources it is
+ using. Calling `xo_destroy` with a `NULL` handle will release any
+ resources associated with the default handle.
+
+.. index:: xo_emit
+
+Emitting Content (xo_emit)
+--------------------------
+
+The functions in this section are used to emit output. They use a
+`format` string containing field descriptors as specified in
+:ref:`format-strings`. The use of a handle is optional and `NULL` can
+be passed to access the internal "default" handle. See
+:ref:`handles`.
+
+The remaining arguments to `xo_emit` and `xo_emit_h` are a set of
+arguments corresponding to the fields in the format string. Care must
+be taken to ensure the argument types match the fields in the format
+string, since an inappropriate or missing argument can ruin your day.
+The `vap` argument to `xo_emit_hv` points to a variable argument list
+that can be used to retrieve arguments via `va_arg`.
+
+.. c:function:: xo_ssize_t xo_emit (const char *fmt, ...)
+
+ :param fmt: The format string, followed by zero or more arguments
+ :returns: If XOF_COLUMNS is set, the number of columns used; otherwise the number of bytes emitted
+ :rtype: xo_ssize_t
+
+.. c:function:: xo_ssize_t xo_emit_h (xo_handle_t *xop, const char *fmt, ...)
+
+ :param xop: Handle for modify (or NULL for default handle)
+ :type xop: xo_handle_t \*
+ :param fmt: The format string, followed by zero or more arguments
+ :returns: If XOF_COLUMNS is set, the number of columns used; otherwise the number of bytes emitted
+ :rtype: xo_ssize_t
+
+.. c:function:: xo_ssize_t xo_emit_hv (xo_handle_t *xop, const char *fmt, va_list vap)
+
+ :param xop: Handle for modify (or NULL for default handle)
+ :type xop: xo_handle_t \*
+ :param fmt: The format string
+ :param va_list vap: A set of variadic arguments
+ :returns: If XOF_COLUMNS is set, the number of columns used; otherwise the number of bytes emitted
+ :rtype: xo_ssize_t
+
+.. index:: xo_emit_field
+
+Single Field Emitting Functions (xo_emit_field)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The functions in this section emit formatted output similar to
+`xo_emit` but where `xo_emit` uses a single string argument containing
+the description for multiple fields, `xo_emit_field` emits a single
+field using multiple ar- guments to contain the field description.
+`xo_emit_field_h` adds an ex- plicit handle to use instead of the
+default handle, while `xo_emit_field_hv` accepts a va_list for
+additional flexibility.
+
+The arguments `rolmod`, `content`, `fmt`, and `efmt` are detailed in
+:ref:`field-formatting`. Using distinct arguments allows callers to
+pass the field description in pieces, rather than having to use
+something like `snprintf` to build the format string required by
+`xo_emit`. The arguments are each NUL-terminated strings. The `rolmod`
+argument contains the `role` and `modifier` portions of the field
+description, the `content` argument contains the `content` portion, and
+the `fmt` and `efmt` contain the `field-format` and `encoding-format` por-
+tions, respectively.
+
+As with `xo_emit`, the `fmt` and `efmt` values are both optional,
+since the `field-format` string defaults to "%s", and the
+`encoding-format`'s default value is derived from the `field-format`
+per :ref:`field-formatting`. However, care must be taken to avoid
+using a value directly as the format, since characters like '{', '%',
+and '}' will be interpreted as formatting directives, and may cause
+xo_emit_field to dereference arbitrary values off the stack, leading
+to bugs, core files, and gnashing of teeth.
+
+.. c:function:: xo_ssize_t xo_emit_field (const char *rolmod, const char *content, const char *fmt, const char *efmt, ...)
+
+ :param rolmod: A comma-separated list of field roles and field modifiers
+ :type rolmod: const char *
+ :param content: The "content" portion of the field description string
+ :type content: const char *
+ :param fmt: Contents format string
+ :type fmt: const char *
+ :param efmt: Encoding format string, followed by additional arguments
+ :type efmt: const char *
+ :returns: If XOF_COLUMNS is set, the number of columns used; otherwise the number of bytes emitted
+ :rtype: xo_ssize_t
+
+ ::
+
+ EXAMPLE::
+ xo_emit_field("T", title, NULL, NULL, NULL);
+ xo_emit_field("T", "Host name is ", NULL, NULL);
+ xo_emit_field("V", "host-name", NULL, NULL, host-name);
+ xo_emit_field(",leaf-list,quotes", "sku", "%s-%u", "%s-000-%u",
+ "gum", 1412);
+
+.. c:function:: xo_ssize_t xo_emit_field_h (xo_handle_t *xop, const char *rolmod, const char *contents, const char *fmt, const char *efmt, ...)
+
+ :param xop: Handle for modify (or NULL for default handle)
+ :type xop: xo_handle_t \*
+ :param rolmod: A comma-separated list of field roles and field modifiers
+ :type rolmod: const char *
+ :param contents: The "contents" portion of the field description string
+ :type contents: const char *
+ :param fmt: Content format string
+ :type fmt: const char *
+ :param efmt: Encoding format string, followed by additional arguments
+ :type efmt: const char *
+ :returns: If XOF_COLUMNS is set, the number of columns used; otherwise the number of bytes emitted
+ :rtype: xo_ssize_t
+
+.. c:function:: xo_ssize_t xo_emit_field_hv (xo_handle_t *xop, const char *rolmod, const char *contents, const char *fmt, const char *efmt, va_list vap)
+
+ :param xop: Handle for modify (or NULL for default handle)
+ :type xop: xo_handle_t \*
+ :param rolmod: A comma-separated list of field roles and field modifiers
+ :type rolmod: const char *
+ :param contents: The "contents" portion of the field description string
+ :type contents: const char *
+ :param fmt: Content format string
+ :type fmt: const char *
+ :param efmt: Encoding format string
+ :type efmt: const char *
+ :param va_list vap: A set of variadic arguments
+ :returns: If XOF_COLUMNS is set, the number of columns used; otherwise the number of bytes emitted
+ :rtype: xo_ssize_t
+
+.. index:: xo_attr
+.. _xo_attr:
+
+Attributes (xo_attr)
+~~~~~~~~~~~~~~~~~~~~
+
+The functions in this section emit an XML attribute with the given name
+and value. This only affects the XML output style.
+
+The `name` parameter give the name of the attribute to be encoded. The
+`fmt` parameter gives a printf-style format string used to format the
+value of the attribute using any remaining arguments, or the vap
+parameter passed to `xo_attr_hv`.
+
+All attributes recorded via `xo_attr` are placed on the next
+container, instance, leaf, or leaf list that is emitted.
+
+Since attributes are only emitted in XML, their use should be limited
+to meta-data and additional or redundant representations of data
+already emitted in other form.
+
+.. c:function:: xo_ssize_t xo_attr (const char *name, const char *fmt, ...)
+
+ :param name: Attribute name
+ :type name: const char *
+ :param fmt: Attribute value, as variadic arguments
+ :type fmt: const char *
+ :returns: -1 for error, or the number of bytes in the formatted attribute value
+ :rtype: xo_ssize_t
+
+ ::
+
+ EXAMPLE:
+ xo_attr("seconds", "%ld", (unsigned long) login_time);
+ struct tm *tmp = localtime(login_time);
+ strftime(buf, sizeof(buf), "%R", tmp);
+ xo_emit("Logged in at {:login-time}\n", buf);
+ XML:
+ <login-time seconds="1408336270">00:14</login-time>
+
+
+.. c:function:: xo_ssize_t xo_attr_h (xo_handle_t *xop, const char *name, const char *fmt, ...)
+
+ :param xop: Handle for modify (or NULL for default handle)
+ :type xop: xo_handle_t \*
+
+ The `xo_attr_h` function follows the conventions of `xo_attr` but
+ adds an explicit libxo handle.
+
+.. c:function:: xo_ssize_t xo_attr_hv (xo_handle_t *xop, const char *name, const char *fmt, va_list vap)
+
+ The `xo_attr_h` function follows the conventions of `xo_attr_h`
+ but replaced the variadic list with a variadic pointer.
+
+.. index:: xo_flush
+
+Flushing Output (xo_flush)
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. c:function:: xo_ssize_t xo_flush (void)
+
+ :returns: -1 for error, or the number of bytes generated
+ :rtype: xo_ssize_t
+
+ libxo buffers data, both for performance and consistency, but also
+ to allow for the proper function of various advanced features. At
+ various times, the caller may wish to flush any data buffered within
+ the library. The `xo_flush` call is used for this.
+
+ Calling `xo_flush` also triggers the flush function associated with
+ the handle. For the default handle, this is equivalent to
+ "fflush(stdio);".
+
+.. c:function:: xo_ssize_t xo_flush_h (xo_handle_t *xop)
+
+ :param xop: Handle for flush (or NULL for default handle)
+ :type xop: xo_handle_t \*
+ :returns: -1 for error, or the number of bytes generated
+ :rtype: xo_ssize_t
+
+ The `xo_flush_h` function follows the conventions of `xo_flush`,
+ but adds an explicit libxo handle.
+
+.. index:: xo_finish
+.. index:: xo_finish_atexit
+.. index:: atexit
+
+Finishing Output (xo_finish)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+When the program is ready to exit or close a handle, a call to
+`xo_finish` or `xo_finish_h` is required. This flushes any buffered
+data, closes open libxo constructs, and completes any pending
+operations.
+
+Calling this function is vital to the proper operation of libxo,
+especially for the non-TEXT output styles.
+
+.. c:function:: xo_ssize_t xo_finish (void)
+
+ :returns: -1 on error, or the number of bytes flushed
+ :rtype: xo_ssize_t
+
+.. c:function:: xo_ssize_t xo_finish_h (xo_handle_t *xop)
+
+ :param xop: Handle for finish (or NULL for default handle)
+ :type xop: xo_handle_t \*
+ :returns: -1 on error, or the number of bytes flushed
+ :rtype: xo_ssize_t
+
+.. c:function:: void xo_finish_atexit (void)
+
+ The `xo_finish_atexit` function is suitable for use with
+ :manpage:`atexit(3)` to ensure that `xo_finish` is called
+ on the default handle when the application exits.
+
+.. index:: UTF-8
+.. index:: xo_open_container
+.. index:: xo_close_container
+
+Emitting Hierarchy
+------------------
+
+libxo represents two types of hierarchy: containers and lists. A
+container appears once under a given parent where a list consists of
+instances that can appear multiple times. A container is used to hold
+related fields and to give the data organization and scope.
+
+.. index:: YANG
+
+.. admonition:: YANG Terminology
+
+ libxo uses terminology from YANG (:RFC:`7950`), the data modeling
+ language for NETCONF: container, list, leaf, and leaf-list.
+
+For XML and JSON, individual fields appear inside hierarchies which
+provide context and meaning to the fields. Unfortunately, these
+encoding have a basic disconnect between how lists is similar objects
+are represented.
+
+XML encodes lists as set of sequential elements::
+
+ <user>phil</user>
+ <user>pallavi</user>
+ <user>sjg</user>
+
+JSON encodes lists using a single name and square brackets::
+
+ "user": [ "phil", "pallavi", "sjg" ]
+
+This means libxo needs three distinct indications of hierarchy: one
+for containers of hierarchy appear only once for any specific parent,
+one for lists, and one for each item in a list.
+
+.. index:: Containers
+
+Containers
+~~~~~~~~~~
+
+A "*container*" is an element of a hierarchy that appears only once
+under any specific parent. The container has no value, but serves to
+contain and organize other nodes.
+
+To open a container, call xo_open_container() or
+xo_open_container_h(). The former uses the default handle and the
+latter accepts a specific handle. To close a level, use the
+xo_close_container() or xo_close_container_h() functions.
+
+Each open call must have a matching close call. If the XOF_WARN flag
+is set and the name given does not match the name of the currently open
+container, a warning will be generated.
+
+.. c:function:: xo_ssize_t xo_open_container (const char *name)
+
+ :param name: Name of the container
+ :type name: const char *
+ :returns: -1 on error, or the number of bytes generated
+ :rtype: xo_ssize_t
+
+ The `name` parameter gives the name of the container, encoded in
+ UTF-8. Since ASCII is a proper subset of UTF-8, traditional C
+ strings can be used directly.
+
+.. c:function:: xo_ssize_t xo_open_container_h (xo_handle_t *xop, const char *name)
+
+ :param xop: Handle to use (or NULL for default handle)
+ :type xop: xo_handle_t *
+
+ The `xo_open_container_h` function adds a `handle` parameter.
+
+.. c:function:: xo_ssize_t xo_close_container (const char *name)
+
+ :param name: Name of the container
+ :type name: const char *
+ :returns: -1 on error, or the number of bytes generated
+ :rtype: xo_ssize_t
+
+.. c:function:: xo_ssize_t xo_close_container_h (xo_handle_t *xop, const char *name)
+
+ :param xop: Handle to use (or NULL for default handle)
+ :type xop: xo_handle_t *
+
+ The `xo_close_container_h` function adds a `handle` parameter.
+
+Use the :index:`XOF_WARN` flag to generate a warning if the name given
+on the close does not match the current open container.
+
+For TEXT and HTML output, containers are not rendered into output
+text, though for HTML they are used to record an XPath value when the
+:index:`XOF_XPATH` flag is set.
+
+::
+
+ EXAMPLE:
+ xo_open_container("top");
+ xo_open_container("system");
+ xo_emit("{:host-name/%s%s%s}", hostname,
+ domainname ? "." : "", domainname ?: "");
+ xo_close_container("system");
+ xo_close_container("top");
+ TEXT:
+ my-host.example.org
+ XML:
+ <top>
+ <system>
+ <host-name>my-host.example.org</host-name>
+ </system>
+ </top>
+ JSON:
+ "top" : {
+ "system" : {
+ "host-name": "my-host.example.org"
+ }
+ }
+ HTML:
+ <div class="data"
+ data-tag="host-name">my-host.example.org</div>
+
+.. index:: xo_open_instance
+.. index:: xo_close_instance
+.. index:: xo_open_list
+.. index:: xo_close_list
+
+Lists and Instances
+~~~~~~~~~~~~~~~~~~~
+
+A "*list*" is set of one or more instances that appear under the same
+parent. The instances contain details about a specific object. One
+can think of instances as objects or records. A call is needed to
+open and close the list, while a distinct call is needed to open and
+close each instance of the list.
+
+The name given to all calls must be identical, and it is strongly
+suggested that the name be singular, not plural, as a matter of
+style and usage expectations::
+
+ EXAMPLE:
+ xo_open_list("item");
+
+ for (ip = list; ip->i_title; ip++) {
+ xo_open_instance("item");
+ xo_emit("{L:Item} '{:name/%s}':\n", ip->i_title);
+ xo_close_instance("item");
+ }
+
+ xo_close_list("item");
+
+Getting the list and instance calls correct is critical to the proper
+generation of XML and JSON data.
+
+Opening Lists
++++++++++++++
+
+.. c:function:: xo_ssize_t xo_open_list (const char *name)
+
+ :param name: Name of the list
+ :type name: const char *
+ :returns: -1 on error, or the number of bytes generated
+ :rtype: xo_ssize_t
+
+ The `xo_open_list` function open a list of instances.
+
+.. c:function:: xo_ssize_t xo_open_list_h (xo_handle_t *xop, const char *name)
+
+ :param xop: Handle to use (or NULL for default handle)
+ :type xop: xo_handle_t *
+
+Closing Lists
++++++++++++++
+
+.. c:function:: xo_ssize_t xo_close_list (const char *name)
+
+ :param name: Name of the list
+ :type name: const char *
+ :returns: -1 on error, or the number of bytes generated
+ :rtype: xo_ssize_t
+
+ The `xo_close_list` function closes a list of instances.
+
+.. c:function:: xo_ssize_t xo_close_list_h (xo_handle_t *xop, const char *name)
+
+ :param xop: Handle to use (or NULL for default handle)
+ :type xop: xo_handle_t *
+
+ The `xo_close_container_h` function adds a `handle` parameter.
+
+Opening Instances
++++++++++++++++++
+
+.. c:function:: xo_ssize_t xo_open_instance (const char *name)
+
+ :param name: Name of the instance (same as the list name)
+ :type name: const char *
+ :returns: -1 on error, or the number of bytes generated
+ :rtype: xo_ssize_t
+
+ The `xo_open_instance` function open a single instance.
+
+.. c:function:: xo_ssize_t xo_open_instance_h (xo_handle_t *xop, const char *name)
+
+ :param xop: Handle to use (or NULL for default handle)
+ :type xop: xo_handle_t *
+
+ The `xo_open_instance_h` function adds a `handle` parameter.
+
+Closing Instances
++++++++++++++++++
+
+.. c:function:: xo_ssize_t xo_close_instance (const char *name)
+
+ :param name: Name of the instance
+ :type name: const char *
+ :returns: -1 on error, or the number of bytes generated
+ :rtype: xo_ssize_t
+
+ The `xo_close_instance` function closes an open instance.
+
+.. c:function:: xo_ssize_t xo_close_instance_h (xo_handle_t *xop, const char *name)
+
+ :param xop: Handle to use (or NULL for default handle)
+ :type xop: xo_handle_t *
+
+ The `xo_close_instance_h` function adds a `handle` parameter.
+
+ ::
+
+ EXAMPLE:
+ xo_open_list("user");
+ for (i = 0; i < num_users; i++) {
+ xo_open_instance("user");
+ xo_emit("{k:name}:{:uid/%u}:{:gid/%u}:{:home}\n",
+ pw[i].pw_name, pw[i].pw_uid,
+ pw[i].pw_gid, pw[i].pw_dir);
+ xo_close_instance("user");
+ }
+ xo_close_list("user");
+ TEXT:
+ phil:1001:1001:/home/phil
+ pallavi:1002:1002:/home/pallavi
+ XML:
+ <user>
+ <name>phil</name>
+ <uid>1001</uid>
+ <gid>1001</gid>
+ <home>/home/phil</home>
+ </user>
+ <user>
+ <name>pallavi</name>
+ <uid>1002</uid>
+ <gid>1002</gid>
+ <home>/home/pallavi</home>
+ </user>
+ JSON:
+ user: [
+ {
+ "name": "phil",
+ "uid": 1001,
+ "gid": 1001,
+ "home": "/home/phil",
+ },
+ {
+ "name": "pallavi",
+ "uid": 1002,
+ "gid": 1002,
+ "home": "/home/pallavi",
+ }
+ ]
+
+Markers
+~~~~~~~
+
+Markers are used to protect and restore the state of open hierarchy
+constructs (containers, lists, or instances). While a marker is open,
+no other open constructs can be closed. When a marker is closed, all
+constructs open since the marker was opened will be closed.
+
+Markers use names which are not user-visible, allowing the caller to
+choose appropriate internal names.
+
+In this example, the code whiffles through a list of fish, calling a
+function to emit details about each fish. The marker "fish-guts" is
+used to ensure that any constructs opened by the function are closed
+properly::
+
+ EXAMPLE:
+ for (i = 0; fish[i]; i++) {
+ xo_open_instance("fish");
+ xo_open_marker("fish-guts");
+ dump_fish_details(i);
+ xo_close_marker("fish-guts");
+ }
+
+.. c:function:: xo_ssize_t xo_open_marker(const char *name)
+
+ :param name: Name of the instance
+ :type name: const char *
+ :returns: -1 on error, or the number of bytes generated
+ :rtype: xo_ssize_t
+
+ The `xo_open_marker` function records the current state of open tags
+ in order for `xo_close_marker` to close them at some later point.
+
+.. c:function:: xo_ssize_t xo_open_marker_h(const char *name)
+
+ :param xop: Handle to use (or NULL for default handle)
+ :type xop: xo_handle_t *
+
+ The `xo_open_marker_h` function adds a `handle` parameter.
+
+.. c:function:: xo_ssize_t xo_close_marker(const char *name)
+
+ :param name: Name of the instance
+ :type name: const char *
+ :returns: -1 on error, or the number of bytes generated
+ :rtype: xo_ssize_t
+
+ The `xo_close_marker` function closes any open containers, lists, or
+ instances as needed to return to the state recorded when
+ `xo_open_marker` was called with the matching name.
+
+.. c:function:: xo_ssize_t xo_close_marker(const char *name)
+
+ :param xop: Handle to use (or NULL for default handle)
+ :type xop: xo_handle_t *
+
+ The `xo_close_marker_h` function adds a `handle` parameter.
+
+DTRT Mode
+~~~~~~~~~
+
+Some users may find tracking the names of open containers, lists, and
+instances inconvenient. libxo offers a "Do The Right Thing" mode, where
+libxo will track the names of open containers, lists, and instances so
+the close function can be called without a name. To enable DTRT mode,
+turn on the XOF_DTRT flag prior to making any other libxo output::
+
+ xo_set_flags(NULL, XOF_DTRT);
+
+.. index:: XOF_DTRT
+
+Each open and close function has a version with the suffix "_d", which
+will close the open container, list, or instance::
+
+ xo_open_container_d("top");
+ ...
+ xo_close_container_d();
+
+This also works for lists and instances::
+
+ xo_open_list_d("item");
+ for (...) {
+ xo_open_instance_d("item");
+ xo_emit(...);
+ xo_close_instance_d();
+ }
+ xo_close_list_d();
+
+.. index:: XOF_WARN
+
+Note that the XOF_WARN flag will also cause libxo to track open
+containers, lists, and instances. A warning is generated when the
+name given to the close function and the name recorded do not match.
+
+Support Functions
+-----------------
+
+.. index:: xo_parse_args
+.. _xo_parse_args:
+
+Parsing Command-line Arguments (xo_parse_args)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. c:function:: int xo_parse_args (int argc, char **argv)
+
+ :param int argc: Number of arguments
+ :param argv: Array of argument strings
+ :return: -1 on error, or the number of remaining arguments
+ :rtype: int
+
+ The `xo_parse_args` function is used to process a program's
+ arguments. libxo-specific options are processed and removed from
+ the argument list so the calling application does not need to
+ process them. If successful, a new value for argc is returned. On
+ failure, a message is emitted and -1 is returned::
+
+ argc = xo_parse_args(argc, argv);
+ if (argc < 0)
+ exit(EXIT_FAILURE);
+
+ Following the call to xo_parse_args, the application can process the
+ remaining arguments in a normal manner. See :ref:`options` for a
+ description of valid arguments.
+
+.. index:: xo_set_program
+
+xo_set_program
+~~~~~~~~~~~~~~
+
+.. c:function:: void xo_set_program (const char *name)
+
+ :param name: Name to use as the program name
+ :type name: const char *
+ :returns: void
+
+ The `xo_set_program` function sets the name of the program as
+ reported by functions like `xo_failure`, `xo_warn`, `xo_err`, etc.
+ The program name is initialized by `xo_parse_args`, but subsequent
+ calls to `xo_set_program` can override this value::
+
+ EXAMPLE:
+ xo_set_program(argv[0]);
+
+ Note that the value is not copied, so the memory passed to
+ `xo_set_program` (and `xo_parse_args`) must be maintained by the
+ caller.
+
+.. index:: xo_set_version
+
+xo_set_version
+~~~~~~~~~~~~~~
+
+.. c:function:: void xo_set_version (const char *version)
+
+ :param name: Value to use as the version string
+ :type name: const char *
+ :returns: void
+
+ The `xo_set_version` function records a version number to be emitted
+ as part of the data for encoding styles (XML and JSON). This
+ version number is suitable for tracking changes in the content,
+ allowing a user of the data to discern which version of the data
+ model is in use.
+
+.. c:function:: void xo_set_version_h (xo_handle_t *xop, const char *version)
+
+ :param xop: Handle to use (or NULL for default handle)
+ :type xop: xo_handle_t *
+
+ The `xo_set_version` function adds a `handle` parameter.
+
+.. index:: --libxo
+.. index:: XOF_INFO
+.. index:: xo_info_t
+
+.. _field-information:
+
+Field Information (xo_info_t)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+HTML data can include additional information in attributes that
+begin with "data-". To enable this, three things must occur:
+
+First the application must build an array of xo_info_t structures,
+one per tag. The array must be sorted by name, since libxo uses a
+binary search to find the entry that matches names from format
+instructions.
+
+Second, the application must inform libxo about this information using
+the `xo_set_info` call::
+
+ typedef struct xo_info_s {
+ const char *xi_name; /* Name of the element */
+ const char *xi_type; /* Type of field */
+ const char *xi_help; /* Description of field */
+ } xo_info_t;
+
+ void xo_set_info (xo_handle_t *xop, xo_info_t *infop, int count);
+
+Like other libxo calls, passing `NULL` for the handle tells libxo to
+use the default handle.
+
+If the count is -1, libxo will count the elements of infop, but there
+must be an empty element at the end. More typically, the number is
+known to the application::
+
+ xo_info_t info[] = {
+ { "in-stock", "number", "Number of items in stock" },
+ { "name", "string", "Name of the item" },
+ { "on-order", "number", "Number of items on order" },
+ { "sku", "string", "Stock Keeping Unit" },
+ { "sold", "number", "Number of items sold" },
+ };
+ int info_count = (sizeof(info) / sizeof(info[0]));
+ ...
+ xo_set_info(NULL, info, info_count);
+
+Third, the emission of info must be triggered with the `XOF_INFO` flag
+using either the `xo_set_flags` function or the "`--libxo=info`"
+command line argument.
+
+The type and help values, if present, are emitted as the "data-type"
+and "data-help" attributes::
+
+ <div class="data" data-tag="sku" data-type="string"
+ data-help="Stock Keeping Unit">GRO-000-533</div>
+
+.. c:function:: void xo_set_info (xo_handle_t *xop, xo_info_t *infop, int count)
+
+ :param xop: Handle to use (or NULL for default handle)
+ :type xop: xo_handle_t *
+ :param infop: Array of information structures
+ :type infop: xo_info_t *
+ :returns: void
+
+.. index:: xo_set_allocator
+.. index:: xo_realloc_func_t
+.. index:: xo_free_func_t
+
+Memory Allocation
+~~~~~~~~~~~~~~~~~
+
+The `xo_set_allocator` function allows libxo to be used in
+environments where the standard :manpage:`realloc(3)` and
+:manpage:`free(3)` functions are not appropriate.
+
+.. c:function:: void xo_set_allocator (xo_realloc_func_t realloc_func, xo_free_func_t free_func)
+
+ :param xo_realloc_func_t realloc_func: Allocation function
+ :param xo_free_func_t free_func: Free function
+
+ *realloc_func* should expect the same arguments as
+ :manpage:`realloc(3)` and return a pointer to memory following the
+ same convention. *free_func* will receive the same argument as
+ :manpage:`free(3)` and should release it, as appropriate for the
+ environment.
+
+By default, the standard :manpage:`realloc(3)` and :manpage:`free(3)`
+functions are used.
+
+.. index:: --libxo
+
+.. _libxo-options:
+
+LIBXO_OPTIONS
+~~~~~~~~~~~~~
+
+The environment variable "LIBXO_OPTIONS" can be set to a subset of
+libxo options, including:
+
+- color
+- flush
+- flush-line
+- no-color
+- no-humanize
+- no-locale
+- no-retain
+- pretty
+- retain
+- underscores
+- warn
+
+For example, warnings can be enabled by::
+
+ % env LIBXO_OPTIONS=warn my-app
+
+Since environment variables are inherited, child processes will have
+the same options, which may be undesirable, making the use of the
+"`--libxo`" command-line option preferable in most situations.
+
+.. index:: xo_warn
+.. index:: xo_err
+.. index:: xo_errx
+.. index:: xo_message
+
+Errors, Warnings, and Messages
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Many programs make use of the standard library functions
+:manpage:`err(3)` and :manpage:`warn(3)` to generate errors and
+warnings for the user. libxo wants to pass that information via the
+current output style, and provides compatible functions to allow
+this::
+
+ void xo_warn (const char *fmt, ...);
+ void xo_warnx (const char *fmt, ...);
+ void xo_warn_c (int code, const char *fmt, ...);
+ void xo_warn_hc (xo_handle_t *xop, int code,
+ const char *fmt, ...);
+ void xo_err (int eval, const char *fmt, ...);
+ void xo_errc (int eval, int code, const char *fmt, ...);
+ void xo_errx (int eval, const char *fmt, ...);
+
+::
+
+ void xo_message (const char *fmt, ...);
+ void xo_message_c (int code, const char *fmt, ...);
+ void xo_message_hc (xo_handle_t *xop, int code,
+ const char *fmt, ...);
+ void xo_message_hcv (xo_handle_t *xop, int code,
+ const char *fmt, va_list vap);
+
+These functions display the program name, a colon, a formatted message
+based on the arguments, and then optionally a colon and an error
+message associated with either *errno* or the *code* parameter::
+
+ EXAMPLE:
+ if (open(filename, O_RDONLY) < 0)
+ xo_err(1, "cannot open file '%s'", filename);
+
+.. index:: xo_error
+.. index:: xo_error_h
+.. index:: xo_error_hv
+.. index:: xo_errorn
+.. index:: xo_errorn_h
+.. index:: xo_errorn_hv
+
+xo_error
+~~~~~~~~
+
+.. c:function:: void xo_error (const char *fmt, ...)
+
+ :param fmt: Format string
+ :type fmt: const char *
+ :returns: void
+
+.. c:function:: void xo_error_h (xo_handle_t *xop, const char *fmt, ...)
+
+ :param xop: libxo handle pointer
+ :type xop: xo_handle_t *
+ :param fmt: Format string
+ :type fmt: const char *
+ :returns: void
+
+.. c:function:: void xo_error_hv (xo_handle_t *xop, const char *fmt, va_list vap)
+
+ :param xop: libxo handle pointer
+ :type xop: xo_handle_t *
+ :param fmt: Format string
+ :type fmt: const char *
+ :param vap: variadic arguments
+ :type xop: va_list
+ :returns: void
+
+.. c:function:: void xo_errorn (const char *fmt, ...)
+
+ :param fmt: Format string
+ :type fmt: const char *
+ :returns: void
+
+.. c:function:: void xo_errorn_h (xo_handle_t *xop, const char *fmt, ...)
+
+ :param xop: libxo handle pointer
+ :type xop: xo_handle_t *
+ :param fmt: Format string
+ :type fmt: const char *
+ :returns: void
+
+.. c:function:: void xo_errorn_hv (xo_handle_t *xop, int need_newline, const char *fmt, va_list vap)
+
+ :param xop: libxo handle pointer
+ :type xop: xo_handle_t *
+ :param need_newline: boolean indicating need for trailing newline
+ :type need_newline: int
+ :param fmt: Format string
+ :type fmt: const char *
+ :param vap: variadic arguments
+ :type xop: va_list
+ :returns: void
+
+ The `xo_error` function can be used for generic errors that should
+ be reported over the handle, rather than to stderr. The `xo_error`
+ function behaves like `xo_err` for TEXT and HTML output styles, but
+ puts the error into XML or JSON elements::
+
+ EXAMPLE::
+ xo_error("Does not %s", "compute");
+ XML::
+ <error><message>Does not compute</message></error>
+ JSON::
+ "error": { "message": "Does not compute" }
+
+ The `xo_error_h` and `xo_error_hv` add a handle object and a
+ variadic-ized parameter to the signature, respectively.
+
+ The `xo_errorn` function supplies a newline at the end the error
+ message if the format string does not include one. The
+ `xo_errorn_h` and `xo_errorn_hv` functions add a handle object and
+ a variadic-ized parameter to the signature, respectively. The
+ `xo_errorn_hv` function also adds a boolean to indicate the need for
+ a trailing newline.
+
+.. index:: xo_no_setlocale
+.. index:: Locale
+
+xo_no_setlocale
+~~~~~~~~~~~~~~~
+
+.. c:function:: void xo_no_setlocale (void)
+
+ libxo automatically initializes the locale based on setting of the
+ environment variables LC_CTYPE, LANG, and LC_ALL. The first of this
+ list of variables is used and if none of the variables, the locale
+ defaults to "UTF-8". The caller may wish to avoid this behavior,
+ and can do so by calling the `xo_no_setlocale` function.
+
+Emitting syslog Messages
+------------------------
+
+syslog is the system logging facility used throughout the unix world.
+Messages are sent from commands, applications, and daemons to a
+hierarchy of servers, where they are filtered, saved, and forwarded
+based on configuration behaviors.
+
+syslog is an older protocol, originally documented only in source
+code. By the time :RFC:`3164` published, variation and mutation left the
+leading "<pri>" string as only common content. :RFC:`5424` defines a new
+version (version 1) of syslog and introduces structured data into the
+messages. Structured data is a set of name/value pairs transmitted
+distinctly alongside the traditional text message, allowing filtering
+on precise values instead of regular expressions.
+
+These name/value pairs are scoped by a two-part identifier; an
+enterprise identifier names the party responsible for the message
+catalog and a name identifying that message. `Enterprise IDs`_ are
+defined by IANA, the Internet Assigned Numbers Authority.
+
+.. _Enterprise IDs:
+ https://www.iana.org/assignments/enterprise-numbers/enterprise-numbers
+
+Use the `xo_set_syslog_enterprise_id` function to set the Enterprise
+ID, as needed.
+
+The message name should follow the conventions in
+:ref:`good-field-names`\ , as should the fields within the message::
+
+ /* Both of these calls are optional */
+ xo_set_syslog_enterprise_id(32473);
+ xo_open_log("my-program", 0, LOG_DAEMON);
+
+ /* Generate a syslog message */
+ xo_syslog(LOG_ERR, "upload-failed",
+ "error <%d> uploading file '{:filename}' "
+ "as '{:target/%s:%s}'",
+ code, filename, protocol, remote);
+
+ xo_syslog(LOG_INFO, "poofd-invalid-state",
+ "state {:current/%u} is invalid {:connection/%u}",
+ state, conn);
+
+The developer should be aware that the message name may be used in the
+future to allow access to further information, including
+documentation. Care should be taken to choose quality, descriptive
+names.
+
+.. _syslog-details:
+
+Priority, Facility, and Flags
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The `xo_syslog`, `xo_vsyslog`, and `xo_open_log` functions
+accept a set of flags which provide the priority of the message, the
+source facility, and some additional features. These values are OR'd
+together to create a single integer argument::
+
+ xo_syslog(LOG_ERR | LOG_AUTH, "login-failed",
+ "Login failed; user '{:user}' from host '{:address}'",
+ user, addr);
+
+These values are defined in <syslog.h>.
+
+The priority value indicates the importance and potential impact of
+each message:
+
+ ============= =======================================================
+ Priority Description
+ ============= =======================================================
+ LOG_EMERG A panic condition, normally broadcast to all users
+ LOG_ALERT A condition that should be corrected immediately
+ LOG_CRIT Critical conditions
+ LOG_ERR Generic errors
+ LOG_WARNING Warning messages
+ LOG_NOTICE Non-error conditions that might need special handling
+ LOG_INFO Informational messages
+ LOG_DEBUG Developer-oriented messages
+ ============= =======================================================
+
+The facility value indicates the source of message, in fairly generic
+terms:
+
+ =============== =======================================================
+ Facility Description
+ =============== =======================================================
+ LOG_AUTH The authorization system (e.g. :manpage:`login(1)`)
+ LOG_AUTHPRIV As LOG_AUTH, but logged to a privileged file
+ LOG_CRON The cron daemon: :manpage:`cron(8)`
+ LOG_DAEMON System daemons, not otherwise explicitly listed
+ LOG_FTP The file transfer protocol daemons
+ LOG_KERN Messages generated by the kernel
+ LOG_LPR The line printer spooling system
+ LOG_MAIL The mail system
+ LOG_NEWS The network news system
+ LOG_SECURITY Security subsystems, such as :manpage:`ipfw(4)`
+ LOG_SYSLOG Messages generated internally by :manpage:`syslogd(8)`
+ LOG_USER Messages generated by user processes (default)
+ LOG_UUCP The uucp system
+ LOG_LOCAL0..7 Reserved for local use
+ =============== =======================================================
+
+In addition to the values listed above, xo_open_log accepts a set of
+addition flags requesting specific logging behaviors:
+
+ ============ ====================================================
+ Flag Description
+ ============ ====================================================
+ LOG_CONS If syslogd fails, attempt to write to /dev/console
+ LOG_NDELAY Open the connection to :manpage:`syslogd(8)` immediately
+ LOG_PERROR Write the message also to standard error output
+ LOG_PID Log the process id with each message
+ ============ ====================================================
+
+.. index:: xo_syslog
+
+xo_syslog
+~~~~~~~~~
+
+.. c:function:: void xo_syslog (int pri, const char *name, const char *fmt, ...)
+
+ :param int pri: syslog priority
+ :param name: Name of the syslog event
+ :type name: const char *
+ :param fmt: Format string, followed by arguments
+ :type fmt: const char *
+ :returns: void
+
+ Use the `xo_syslog` function to generate syslog messages by calling
+ it with a log priority and facility, a message name, a format
+ string, and a set of arguments. The priority/facility argument are
+ discussed above, as is the message name.
+
+ The format string follows the same conventions as `xo_emit`'s format
+ string, with each field being rendered as an SD-PARAM pair::
+
+ xo_syslog(LOG_ERR, "poofd-missing-file",
+ "'{:filename}' not found: {:error/%m}", filename);
+
+ ... [poofd-missing-file@32473 filename="/etc/poofd.conf"
+ error="Permission denied"] '/etc/poofd.conf' not
+ found: Permission denied
+
+Support functions
+~~~~~~~~~~~~~~~~~
+
+.. index:: xo_vsyslog
+
+xo_vsyslog
+++++++++++
+
+.. c:function:: void xo_vsyslog (int pri, const char *name, const char *fmt, va_list vap)
+
+ :param int pri: syslog priority
+ :param name: Name of the syslog event
+ :type name: const char *
+ :param fmt: Format string
+ :type fmt: const char *
+ :param va_list vap: Variadic argument list
+ :returns: void
+
+ xo_vsyslog is identical in function to xo_syslog, but takes the set of
+ arguments using a va_list::
+
+ EXAMPLE:
+ void
+ my_log (const char *name, const char *fmt, ...)
+ {
+ va_list vap;
+ va_start(vap, fmt);
+ xo_vsyslog(LOG_ERR, name, fmt, vap);
+ va_end(vap);
+ }
+
+.. index:: xo_open_log
+
+xo_open_log
++++++++++++
+
+.. c:function:: void xo_open_log (const char *ident, int logopt, int facility)
+
+ :param indent:
+ :type indent: const char *
+ :param int logopt: Bit field containing logging options
+ :param int facility:
+ :returns: void
+
+ xo_open_log functions similar to :manpage:`openlog(3)`, allowing
+ customization of the program name, the log facility number, and the
+ additional option flags described in :ref:`syslog-details`.
+
+.. index:: xo_close_log
+
+xo_close_log
+++++++++++++
+
+.. c:function:: void xo_close_log (void)
+
+ The `xo_close_log` function is similar to :manpage:`closelog(3)`,
+ closing the log file and releasing any associated resources.
+
+.. index:: xo_set_logmask
+
+xo_set_logmask
+++++++++++++++
+
+.. c:function:: int xo_set_logmask (int maskpri)
+
+ :param int maskpri: the log priority mask
+ :returns: The previous log priority mask
+
+ The `xo_set_logmask` function is similar to :manpage:`setlogmask(3)`,
+ restricting the set of generated log event to those whose associated
+ bit is set in maskpri. Use `LOG_MASK(pri)` to find the appropriate bit,
+ or `LOG_UPTO(toppri)` to create a mask for all priorities up to and
+ including toppri::
+
+ EXAMPLE:
+ setlogmask(LOG_UPTO(LOG_WARN));
+
+.. index:: xo_set_syslog_enterprise_id
+
+xo_set_syslog_enterprise_id
++++++++++++++++++++++++++++
+
+.. c:function:: void xo_set_syslog_enterprise_id (unsigned short eid)
+
+ Use the `xo_set_syslog_enterprise_id` to supply a platform- or
+ application-specific enterprise id. This value is used in any future
+ syslog messages.
+
+ Ideally, the operating system should supply a default value via the
+ "kern.syslog.enterprise_id" sysctl value. Lacking that, the
+ application should provide a suitable value.
+
+Enterprise IDs are administered by IANA, the Internet Assigned Number
+Authority. The complete list is EIDs on their web site::
+
+ https://www.iana.org/assignments/enterprise-numbers/enterprise-numbers
+
+New EIDs can be requested from IANA using the following page::
+
+ http://pen.iana.org/pen/PenApplication.page
+
+Each software development organization that defines a set of syslog
+messages should register their own EID and use that value in their
+software to ensure that messages can be uniquely identified by the
+combination of EID + message name.
+
+Creating Custom Encoders
+------------------------
+
+The number of encoding schemes in current use is staggering, with new
+and distinct schemes appearing daily. While libxo provide XML, JSON,
+HMTL, and text natively, there are requirements for other encodings.
+
+Rather than bake support for all possible encoders into libxo, the API
+allows them to be defined externally. libxo can then interfaces with
+these encoding modules using a simplistic API. libxo processes all
+functions calls, handles state transitions, performs all formatting,
+and then passes the results as operations to a customized encoding
+function, which implements specific encoding logic as required. This
+means your encoder doesn't need to detect errors with unbalanced
+open/close operations but can rely on libxo to pass correct data.
+
+By making a simple API, libxo internals are not exposed, insulating the
+encoder and the library from future or internal changes.
+
+The three elements of the API are:
+
+- loading
+- initialization
+- operations
+
+The following sections provide details about these topics.
+
+.. index:: CBOR
+
+libxo source contains an encoder for Concise Binary Object
+Representation, aka CBOR (:RFC:`7049`), which can be used as an
+example for the API for other encoders.
+
+Loading Encoders
+~~~~~~~~~~~~~~~~
+
+Encoders can be registered statically or discovered dynamically.
+Applications can choose to call the `xo_encoder_register` function
+to explicitly register encoders, but more typically they are built as
+shared libraries, placed in the libxo/extensions directory, and loaded
+based on name. libxo looks for a file with the name of the encoder
+and an extension of ".enc". This can be a file or a symlink to the
+shared library file that supports the encoder::
+
+ % ls -1 lib/libxo/extensions/*.enc
+ lib/libxo/extensions/cbor.enc
+ lib/libxo/extensions/test.enc
+
+Encoder Initialization
+~~~~~~~~~~~~~~~~~~~~~~
+
+Each encoder must export a symbol used to access the library, which
+must have the following signature::
+
+ int xo_encoder_library_init (XO_ENCODER_INIT_ARGS);
+
+`XO_ENCODER_INIT_ARGS` is a macro defined in "xo_encoder.h" that defines
+an argument called "arg", a pointer of the type
+`xo_encoder_init_args_t`. This structure contains two fields:
+
+- `xei_version` is the version number of the API as implemented
+ within libxo. This version is currently as 1 using
+ `XO_ENCODER_VERSION`. This number can be checked to ensure
+ compatibility. The working assumption is that all versions should
+ be backward compatible, but each side may need to accurately know
+ the version supported by the other side. `xo_encoder_library_init`
+ can optionally check this value, and must then set it to the version
+ number used by the encoder, allowing libxo to detect version
+ differences and react accordingly. For example, if version 2 adds
+ new operations, then libxo will know that an encoding library that
+ set `xei_version` to 1 cannot be expected to handle those new
+ operations.
+
+- xei_handler must be set to a pointer to a function of type
+ `xo_encoder_func_t`, as defined in "xo_encoder.h". This function
+ takes a set of parameters:
+ - xop is a pointer to the opaque `xo_handle_t` structure
+ - op is an integer representing the current operation
+ - name is a string whose meaning differs by operation
+ - value is a string whose meaning differs by operation
+ - private is an opaque structure provided by the encoder
+
+Additional arguments may be added in the future, so handler functions
+should use the `XO_ENCODER_HANDLER_ARGS` macro. An appropriate
+"extern" declaration is provided to help catch errors.
+
+Once the encoder initialization function has completed processing, it
+should return zero to indicate that no error has occurred. A non-zero
+return code will cause the handle initialization to fail.
+
+Operations
+~~~~~~~~~~
+
+The encoder API defines a set of operations representing the
+processing model of libxo. Content is formatted within libxo, and
+callbacks are made to the encoder's handler function when data is
+ready to be processed:
+
+ ======================= =======================================
+ Operation Meaning (Base function)
+ ======================= =======================================
+ XO_OP_CREATE Called when the handle is created
+ XO_OP_OPEN_CONTAINER Container opened (xo_open_container)
+ XO_OP_CLOSE_CONTAINER Container closed (xo_close_container)
+ XO_OP_OPEN_LIST List opened (xo_open_list)
+ XO_OP_CLOSE_LIST List closed (xo_close_list)
+ XO_OP_OPEN_LEAF_LIST Leaf list opened (xo_open_leaf_list)
+ XO_OP_CLOSE_LEAF_LIST Leaf list closed (xo_close_leaf_list)
+ XO_OP_OPEN_INSTANCE Instance opened (xo_open_instance)
+ XO_OP_CLOSE_INSTANCE Instance closed (xo_close_instance)
+ XO_OP_STRING Field with Quoted UTF-8 string
+ XO_OP_CONTENT Field with content
+ XO_OP_FINISH Finish any pending output
+ XO_OP_FLUSH Flush any buffered output
+ XO_OP_DESTROY Clean up resources
+ XO_OP_ATTRIBUTE An attribute name/value pair
+ XO_OP_VERSION A version string
+ ======================= =======================================
+
+For all the open and close operations, the name parameter holds the
+name of the construct. For string, content, and attribute operations,
+the name parameter is the name of the field and the value parameter is
+the value. "string" are differentiated from "content" to allow differing
+treatment of true, false, null, and numbers from real strings, though
+content values are formatted as strings before the handler is called.
+For version operations, the value parameter contains the version.
+
+All strings are encoded in UTF-8.