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 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 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 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:

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 CONFIG_CBPRINTF_NANO can be used to revert back to the very space-optimized but limited formatter used for printk() before this capability was added.

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 contains copies of all strings which are part of a format string (format string or any %s argument) and are identifed as the one located in the read write memory. 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 be created using two methods:

  • runtime - using cbprintf_package() or 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). 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:

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

sizeof(void *)

1 byte: Argument list size including header and fmt (in 32 bit words)

1 byte: Number of appended strings

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

Appended

strings

1 byte: Index within the package to the location of associated argument

Null terminated string

Warning

If CONFIG_MINIMAL_LIBC is selected in combination with 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

group cbprintf_apis

Defines

CBPRINTF_PACKAGE_ALIGNMENT

Required alignment of the buffer used for packaging.

CBPRINTF_MUST_RUNTIME_PACKAGE(skip, flags, ...)

Determine if string must be packaged in run time.

Static packaging can be applied if size of the package can be determined at compile time. In general, package size can be determined at compile time if there are no string arguments which might be copied into package body if they are considered transient.

Note

By default any char pointers are considered to be pointing at transient strings. This can be narrowed down to non const pointers by using CBPRINTF_MUST_RUNTIME_PACKAGE_CONST_CHAR.

Parameters
  • skip – number of read only string arguments in the parameter list. It shall be non-zero if there are known read only string arguments present in the string (e.g. function name prefix in the log message).

  • ... – String with arguments.

  • flags – option flags. See Package flags..

Return values
  • 1 – if string must be packaged in run time.

  • 0 – string can be statically packaged.

CBPRINTF_STATIC_PACKAGE(packaged, inlen, outlen, align_offset, flags, ...)

Statically package string.

Build string package from formatted string. It assumes that formatted string is in the read only memory.

If _Generic is not supported then runtime packaging is performed.

Parameters
  • packaged – pointer to where the packaged data can be stored. Pass a null pointer to skip packaging but still calculate the total space required. The data stored here is relocatable, that is it can be moved to another contiguous block of memory. It must be aligned to the size of the longest argument. It is recommended to use CBPRINTF_PACKAGE_ALIGNMENT for alignment.

  • inlen – set to the number of bytes available at packaged. If packaged is NULL the value is ignored.

  • outlen – variable updated to the number of bytes required to completely store the packed information. If input buffer was too small it is set to -ENOSPC.

  • align_offset – input buffer alignment offset in bytes. Where offset 0 means that buffer is aligned to CBPRINTF_PACKAGE_ALIGNMENT. Xtensa requires that packaged is aligned to CBPRINTF_PACKAGE_ALIGNMENT so it must be multiply of CBPRINTF_PACKAGE_ALIGNMENT or 0.

  • flags – option flags. See Package flags..

  • ... – formatted string with arguments. Format string must be constant.

Typedefs

typedef int (*cbprintf_cb)()

Signature for a cbprintf callback function.

This function expects two parameters:

  • c a character to output. The output behavior should be as if this was cast to an unsigned char.

  • ctx a pointer to an object that provides context for the output operation.

The declaration does not specify the parameter types. This allows a function like fputc to be used without requiring all context pointers to be to a FILE object.

Return

the value of c cast to an unsigned char then back to int, or a negative error code that will be returned from cbprintf().

Functions

int cbprintf_package(void *packaged, size_t len, uint32_t flags, const char *format, ...)

Capture state required to output formatted data later.

Like cbprintf() but instead of processing the arguments and emitting the formatted results immediately all arguments are captured so this can be done in a different context, e.g. when the output function can block.

In addition to the values extracted from arguments this will ensure that copies are made of the necessary portions of any string parameters that are not confirmed to be stored in read-only memory (hence assumed to be safe to refer to directly later).

Parameters
  • packaged – pointer to where the packaged data can be stored. Pass a null pointer to store nothing but still calculate the total space required. The data stored here is relocatable, that is it can be moved to another contiguous block of memory. However, under condition that alignment is maintained. It must be aligned to at least the size of a pointer.

  • len – this must be set to the number of bytes available at packaged if it is not null. If packaged is null then it indicates hypothetical buffer alignment offset in bytes compared to CBPRINTF_PACKAGE_ALIGNMENT alignment. Buffer alignment offset impacts returned size of the package. Xtensa requires that buffer is always aligned to CBPRINTF_PACKAGE_ALIGNMENT so it must be multiply of CBPRINTF_PACKAGE_ALIGNMENT or 0 when packaged is null.

  • flags – option flags. See Package flags..

  • format – a standard ISO C format string with characters and conversion specifications.

  • ... – arguments corresponding to the conversion specifications found within format.

Return values
  • nonegative – the number of bytes successfully stored at packaged. This will not exceed len.

  • -EINVAL – if format is not acceptable

  • -EFAULT – if packaged alignment is not acceptable

  • -ENOSPC – if packaged was not null and the space required to store exceed len.

int cbvprintf_package(void *packaged, size_t len, uint32_t flags, const char *format, va_list ap)

Capture state required to output formatted data later.

Like cbprintf() but instead of processing the arguments and emitting the formatted results immediately all arguments are captured so this can be done in a different context, e.g. when the output function can block.

In addition to the values extracted from arguments this will ensure that copies are made of the necessary portions of any string parameters that are not confirmed to be stored in read-only memory (hence assumed to be safe to refer to directly later).

Parameters
  • packaged – pointer to where the packaged data can be stored. Pass a null pointer to store nothing but still calculate the total space required. The data stored here is relocatable, that is it can be moved to another contiguous block of memory. The pointer must be aligned to a multiple of the largest element in the argument list.

  • len – this must be set to the number of bytes available at packaged. Ignored if packaged is NULL.

  • flags – option flags. See Package flags..

  • format – a standard ISO C format string with characters and conversion specifications.

  • ap – captured stack arguments corresponding to the conversion specifications found within format.

Return values
  • nonegative – the number of bytes successfully stored at packaged. This will not exceed len.

  • -EINVAL – if format is not acceptable

  • -ENOSPC – if packaged was not null and the space required to store exceed len.

int cbprintf_fsc_package(void *in_packaged, size_t in_len, void *packaged, size_t len)

Convert package to fully self-contained (fsc) package.

By default, package does not contain read only strings. However, if needed it may be converted to a fully self-contained package which contains all strings. In order to allow such conversion, original package must be created with CBPRINTF_PACKAGE_ADD_STRING_IDXS flag. Such package will contain necessary data to find read only strings in the package and copy them into package body.

Parameters
  • in_packaged – pointer to original package created with CBPRINTF_PACKAGE_ADD_STRING_IDXS.

  • in_lenin_packaged length.

  • packaged – pointer to location where fully self-contained version of the input package will be written. Pass a null pointer to calculate space required.

  • len – must be set to the number of bytes available at packaged. Not used if packaged is null.

Return values
  • nonegative – the number of bytes successfully stored at packaged. This will not exceed len. If packaged is null, calculated length.

  • -ENOSPC – if packaged was not null and the space required to store exceed len.

  • -EINVAL – if in_packaged is null.

int cbpprintf(cbprintf_cb out, void *ctx, void *packaged)

Generate the output for a previously captured format operation.

Note

Memory indicated by packaged will be modified in a non-destructive way, meaning that it could still be reused with this function again.

Parameters
  • out – the function used to emit each generated character.

  • ctx – context provided when invoking out

  • packaged – the data required to generate the formatted output, as captured by cbprintf_package() or cbvprintf_package(). The alignment requirement on this data is the same as when it was initially created.

Returns

the number of characters printed, or a negative error value returned from invoking out.

int cbprintf(cbprintf_cb out, void *ctx, const char *format, ...)

*printf-like output through a callback.

This is essentially printf() except the output is generated character-by-character using the provided out function. This allows formatting text of unbounded length without incurring the cost of a temporary buffer.

All formatting specifiers of C99 are recognized, and most are supported if the functionality is enabled.

Note

The functionality of this function is significantly reduced when CONFIG_CBPRINTF_NANO is selected.

Parameters
  • out – the function used to emit each generated character.

  • ctx – context provided when invoking out

  • format – a standard ISO C format string with characters and conversion specifications.

  • ... – arguments corresponding to the conversion specifications found within format.

Returns

the number of characters printed, or a negative error value returned from invoking out.

int cbvprintf(cbprintf_cb out, void *ctx, const char *format, va_list ap)

varargs-aware *printf-like output through a callback.

This is essentially vsprintf() except the output is generated character-by-character using the provided out function. This allows formatting text of unbounded length without incurring the cost of a temporary buffer.

Note

This function is available only when CONFIG_CBPRINTF_LIBC_SUBSTS is selected.

Note

The functionality of this function is significantly reduced when CONFIG_CBPRINTF_NANO is selected.

Parameters
  • out – the function used to emit each generated character.

  • ctx – context provided when invoking out

  • format – a standard ISO C format string with characters and conversion specifications.

  • ap – a reference to the values to be converted.

Returns

the number of characters generated, or a negative error value returned from invoking out.

int fprintfcb(FILE *stream, const char *format, ...)

fprintf using Zephyrs cbprintf infrastructure.

return The number of characters printed.

Note

This function is available only when CONFIG_CBPRINTF_LIBC_SUBSTS is selected.

Note

The functionality of this function is significantly reduced when CONFIG_CBPRINTF_NANO is selected.

Parameters
  • stream – the stream to which the output should be written.

  • format – a standard ISO C format string with characters and conversion specifications.

  • ... – arguments corresponding to the conversion specifications found within format.

int vfprintfcb(FILE *stream, const char *format, va_list ap)

vfprintf using Zephyrs cbprintf infrastructure.

Note

This function is available only when CONFIG_CBPRINTF_LIBC_SUBSTS is selected.

Note

The functionality of this function is significantly reduced when CONFIG_CBPRINTF_NANO is selected.

Parameters
  • stream – the stream to which the output should be written.

  • format – a standard ISO C format string with characters and conversion specifications.

  • ap – a reference to the values to be converted.

Returns

The number of characters printed.

int printfcb(const char *format, ...)

printf using Zephyrs cbprintf infrastructure.

Note

This function is available only when CONFIG_CBPRINTF_LIBC_SUBSTS is selected.

Note

The functionality of this function is significantly reduced when CONFIG_CBPRINTF_NANO is selected.

Parameters
  • format – a standard ISO C format string with characters and conversion specifications.

  • ... – arguments corresponding to the conversion specifications found within format.

Returns

The number of characters printed.

int vprintfcb(const char *format, va_list ap)

vprintf using Zephyrs cbprintf infrastructure.

Note

This function is available only when CONFIG_CBPRINTF_LIBC_SUBSTS is selected.

Note

The functionality of this function is significantly reduced when CONFIG_CBPRINTF_NANO is selected.

Parameters
  • format – a standard ISO C format string with characters and conversion specifications.

  • ap – a reference to the values to be converted.

Returns

The number of characters printed.

int snprintfcb(char *str, size_t size, const char *format, ...)

snprintf using Zephyrs cbprintf infrastructure.

Note

This function is available only when CONFIG_CBPRINTF_LIBC_SUBSTS is selected.

Note

The functionality of this function is significantly reduced when CONFIG_CBPRINTF_NANO is selected.

Parameters
  • str – where the formatted content should be written

  • size – maximum number of chaacters for the formatted output, including the terminating null byte.

  • format – a standard ISO C format string with characters and conversion specifications.

  • ... – arguments corresponding to the conversion specifications found within format.

Returns

The number of characters that would have been written to str, excluding the terminating null byte. This is greater than the number actually written if size is too small.

int vsnprintfcb(char *str, size_t size, const char *format, va_list ap)

vsnprintf using Zephyrs cbprintf infrastructure.

Note

This function is available only when CONFIG_CBPRINTF_LIBC_SUBSTS is selected.

Note

The functionality of this function is significantly reduced when CONFIG_CBPRINTF_NANO is selected.

Parameters
  • str – where the formatted content should be written

  • size – maximum number of chaacters for the formatted output, including the terminating null byte.

  • format – a standard ISO C format string with characters and conversion specifications.

  • ap – a reference to the values to be converted.

Returns

The number of characters that would have been written to str, excluding the terminating null byte. This is greater than the number actually written if size is too small.