blob: 909c9d9420d221b54d49a89a2d31fa961c32f9af [file] [log] [blame]
.. _formatted_output:
Formatted Output
################
Applications as well as Zephyr itself requires infrastructure to format
values for user consumption. The standard C99 library ``*printf()``
functionality fulfills this need for streaming output devices or memory
buffers, but in an embedded system devices may not accept streamed data
and memory may not be available to store the formatted output.
Internal Zephyr API traditionally provided this both for
:c:func:`printk` and for Zephyr's internal minimal libc, but with
separate internal interfaces. Logging, tracing, shell, and other
applications made use of either these APIs or standard libc routines
based on build options.
The :c:func:`cbprintf` public APIs convert C99 format strings and
arguments, providing output produced one character at a time through a
callback mechanism, replacing the original internal functions and
providing support for almost all C99 format specifications. Existing
use of ``s*printf()`` C libraries in Zephyr can be converted to
:c:func:`snprintfcb()` to avoid pulling in libc implementations.
Several Kconfig options control the set of features that are enabled,
allowing some control over features and memory usage:
* :kconfig:option:`CONFIG_CBPRINTF_FULL_INTEGRAL`
or :kconfig:option:`CONFIG_CBPRINTF_REDUCED_INTEGRAL`
* :kconfig:option:`CONFIG_CBPRINTF_FP_SUPPORT`
* :kconfig:option:`CONFIG_CBPRINTF_FP_A_SUPPORT`
* :kconfig:option:`CONFIG_CBPRINTF_FP_ALWAYS_A`
* :kconfig:option:`CONFIG_CBPRINTF_N_SPECIFIER`
:kconfig:option:`CONFIG_CBPRINTF_LIBC_SUBSTS` can be used to provide functions
that behave like standard libc functions but use the selected cbprintf
formatter rather than pulling in another formatter from libc.
In addition :kconfig:option:`CONFIG_CBPRINTF_NANO` can be used to revert back to
the very space-optimized but limited formatter used for :c:func:`printk`
before this capability was added.
.. _cbprintf_packaging:
Cbprintf Packaging
******************
Typically, strings are formatted synchronously when a function from ``printf``
family is called. However, there are cases when it is beneficial that formatting
is deferred. In that case, a state (format string and arguments) must be captured.
Such state forms a self-contained package which contains format string and
arguments. Additionally, package may contain copies of strings which are
part of a format string (format string or any ``%s`` argument). Package primary
content resembles va_list stack frame thus standard formatting functions are
used to process a package. Since package contains data which is processed as
va_list frame, strict alignment must be maintained. Due to required padding,
size of the package depends on alignment. When package is copied, it should be
copied to a memory block with the same alignment as origin.
Package can have following variants:
* **Self-contained** - non read-only strings appended to the package. String can be
formatted from such package as long as there is access to read-only string
locations. Package may contain information where read-only strings are located
within the package. That information can be used to convert packet to fully
self-contained package.
* **Fully self-contained** - all strings are appended to the package. String can be
formatted from such package without any external data.
* **Transient**- only arguments are stored. Package contain information
where pointers to non read-only strings are located within the package. Optionally,
it may contain read-only string location information. String can be formatted
from such package as long as non read-only strings are still valid and read-only
strings are accessible. Alternatively, package can be converted to **self-contained**
package or **fully self-contained** if information about read-only string
locations is present in the package.
Package can be created using two methods:
* runtime - using :c:func:`cbprintf_package` or :c:func:`cbvprintf_package`. This
method scans format string and based on detected format specifiers builds the
package.
* static - types of arguments are detected at compile time by the preprocessor
and package is created as simple assignments to a provided memory. This method
is significantly faster than runtime (more than 15 times) but has following
limitations: requires ``_Generic`` keyword (C11 feature) to be supported by
the compiler and can only create a package that is known to have no string
arguments (``%s``). :c:macro:`CBPRINTF_MUST_RUNTIME_PACKAGE` can be used to
determine at compile time if static packaging can be applied. Macro determines
need for runtime packaging based on presence of char pointers in the argument
list so there are cases when it will be false positive, e.g. ``%p`` with char
pointer.
Several Kconfig options control behavior of the packaging:
* :kconfig:option:`CONFIG_CBPRINTF_PACKAGE_LONGDOUBLE`
* :kconfig:option:`CONFIG_CBPRINTF_STATIC_PACKAGE_CHECK_ALIGNMENT`
Cbprintf package conversion
===========================
It is possible to convert package to a variant which contains more information, e.g
**transient** package can be converted to **self-contained**. Conversion to
**fully self-contained** package is possible if :c:macro:`CBPRINTF_PACKAGE_ADD_RO_STR_POS`
flag was used when package was created.
:c:func:`cbprintf_package_copy` is used to calculate space needed for the new
package and to copy and convert a package.
Cbprintf package format
=======================
Format of the package contains paddings which are platform specific. Package consists
of header which contains size of package (excluding appended strings) and number of
appended strings. It is followed by the arguments which contains alignment paddings
and resembles *va_list* stack frame. Finally, package optionally contains appended
strings. Each string contains 1 byte header which contains index of the location
where address argument is stored. During packaging address is set to null and
before string formatting it is updated to point to the current string location
within the package. Updating address argument must happen just before string
formatting since address changes whenever package is copied.
+------------------+-------------------------------------------------------------------------+
| Header | 1 byte: Argument list size including header and *fmt* (in 32 bit words) |
| +-------------------------------------------------------------------------+
| sizeof(void \*) | 1 byte: Number of strings appended to the package |
| +-------------------------------------------------------------------------+
| | 1 byte: Number of read-only string argument locations |
| +-------------------------------------------------------------------------+
| | 1 byte: Number of transient string argument locations |
| +-------------------------------------------------------------------------+
| | platform specific padding to sizeof(void \*) |
+------------------+-------------------------------------------------------------------------+
| Arguments | Pointer to *fmt* (or null if *fmt* is appended to the package) |
| +-------------------------------------------------------------------------+
| | (optional padding for platform specific alignment) |
| +-------------------------------------------------------------------------+
| | argument 0 |
| +-------------------------------------------------------------------------+
| | (optional padding for platform specific alignment) |
| +-------------------------------------------------------------------------+
| | argument 1 |
| +-------------------------------------------------------------------------+
| | ... |
+------------------+-------------------------------------------------------------------------+
| String location | Indexes of words within the package where read-only strings are located |
| information +-------------------------------------------------------------------------+
| (optional) | Indexes of words within the package where transient strings are located |
+------------------+-------------------------------------------------------------------------+
| Appended | 1 byte: Index within the package to the location of associated argument |
| strings +-------------------------------------------------------------------------+
| (optional) | Null terminated string |
| +-------------------------------------------------------------------------+
| | ... |
+------------------+-------------------------------------------------------------------------+
.. warning::
If :kconfig:option:`CONFIG_MINIMAL_LIBC` is selected in combination with
:kconfig:option:`CONFIG_CBPRINTF_NANO` formatting with C standard library
functions like ``printf`` or ``snprintf`` is limited. Among other
things the ``%n`` specifier, most format flags, precision control, and
floating point are not supported.
API Reference
*************
.. doxygengroup:: cbprintf_apis