|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
Bounded, heap-free printf-subset formatter for the esp-hosted port. More...
Go to the source code of this file.
Data Structures | |
| struct | ra8_esp_hosted_fmt_spec |
| One parsed conversion specification. More... | |
Typedefs | |
| typedef struct ra8_esp_hosted_fmt_spec | ra8_esp_hosted_fmt_spec_t |
Enumerations | |
| enum | ra8_esp_hosted_fmt_bound_t : uint16_t { k_ra8_esp_hosted_fmt_digits_max = 20U , k_ra8_esp_hosted_fmt_width_max = 64U , k_ra8_esp_hosted_fmt_spec_max = 12U } |
| Fixed bounds the formatter works within. More... | |
| enum | ra8_esp_hosted_fmt_len_t : uint8_t { k_ra8_esp_hosted_fmt_len_int = 0U , k_ra8_esp_hosted_fmt_len_long = 1U , k_ra8_esp_hosted_fmt_len_llong = 2U , k_ra8_esp_hosted_fmt_len_size = 3U } |
| Argument width selected by a conversion's length modifier. More... | |
Functions | |
| bool | priv_ra8_esp_hosted_fmt_parse (const char *after_percent, ra8_esp_hosted_fmt_spec_t *out) |
| Parse one conversion specification. | |
| uint8_t | priv_ra8_esp_hosted_fmt_utoa (char *buf, uint64_t value, uint8_t base, bool upper) |
| Render an unsigned value into a digit buffer, least digit last. | |
| uint32_t | priv_ra8_esp_hosted_fmt_vformat (char *out, uint32_t cap, const char *fmt, va_list ap) |
| Format into a bounded buffer from a variable-argument list. | |
Bounded, heap-free printf-subset formatter for the esp-hosted port.
The vendored esp-hosted core logs with printf-style calls (ESP_LOGI(TAG, "len u if d", len, if_type)), but this project's logger takes a plain message string and has no formatting at all. Some formatter therefore has to exist between them.
It is written here rather than delegated to vsnprintf because the C library's printf family is not admissible in this image: NASA Power of 10 Rule 3 forbids allocation after initialisation, this board has no heap at all (_sbrk is a strong symbol that reports a fatal error), and newlib's formatting paths are not contractually allocation-free. A bounded formatter that only ever writes into a caller-supplied buffer removes the question.
An unsupported conversion is copied through verbatim, so an unhandled specifier shows up in the log as itself rather than silently consuming an argument and desynchronising every later one.
Definition in file ra8_esp_hosted_fmt_internal.h.
| typedef struct ra8_esp_hosted_fmt_spec ra8_esp_hosted_fmt_spec_t |
| enum ra8_esp_hosted_fmt_bound_t : uint16_t |
Fixed bounds the formatter works within.
Every loop in the formatter is bounded by one of these, which is what keeps it inside NASA Power of 10 Rule 2 while parsing a format string it did not write. The digit bound covers the widest value the supported bases can produce; the width bound is what a field width is clamped to, so one conversion can never fill an arbitrary buffer.
Definition at line 72 of file ra8_esp_hosted_fmt_internal.h.
| enum ra8_esp_hosted_fmt_len_t : uint8_t |
Argument width selected by a conversion's length modifier.
Decides how much the formatter pulls off the variable-argument list. Getting this wrong does not merely mis-print one value, it misaligns every argument after it, so the modifier is parsed explicitly rather than assumed.
Definition at line 105 of file ra8_esp_hosted_fmt_internal.h.
|
nodiscard |
Parse one conversion specification.
Reads flags, then an optional decimal width, then an optional length modifier, then the conversion character, from the text immediately following a per-cent sign. Stops at the first character that cannot belong to a specification.
A width longer than the formatter's own line budget is clamped rather than honoured, so a hostile or mistyped format string cannot make a single conversion consume the whole buffer.
| [in] | after_percent | Text following the per-cent sign, NUL terminated. Must be non-null. |
| [out] | out | Parsed specification. Must be non-null. Fully written on success; on failure conv and consumed are zero. |
| true | out holds a specification and consumed is non-zero. |
| false | A pointer was null, the text ended mid-specification, or the conversion character is not one this formatter emits. |
Parse one conversion specification.
Definition at line 419 of file ra8_esp_hosted_fmt.c.
References ra8_esp_hosted_fmt_spec::consumed, ra8_esp_hosted_fmt_spec::conv, internal_is_supported(), internal_parse_flags(), internal_parse_len(), internal_parse_width(), ra8_esp_hosted_fmt_spec::len, and ra8_esp_hosted_fmt_spec::width.
Referenced by priv_ra8_esp_hosted_fmt_vformat().
|
nodiscard |
Render an unsigned value into a digit buffer, least digit last.
Writes the digits of value in base into buf, NUL terminated, and reports the digit count. Zero renders as a single 0 rather than an empty string. The buffer must be large enough for the widest result the base allows, which is 64 binary-ish digits plus a terminator; the caller sizes it from k_ra8_esp_hosted_fmt_digits_max.
| [out] | buf | Destination for the digits. Must be non-null and at least k_ra8_esp_hosted_fmt_digits_max + 1 bytes. |
| [in] | value | Value to render. |
| [in] | base | Radix; only 10 and 16 are produced by this formatter. |
| [in] | upper | Whether hexadecimal digits use upper case. |
| 0 | buf was null or base was outside 2..16. |
Render an unsigned value into a digit buffer, least digit last.
Definition at line 232 of file ra8_esp_hosted_fmt.c.
References k_ra8_esp_hosted_fmt_ch_nul, k_ra8_esp_hosted_fmt_digits_max, k_ra8_esp_hosted_fmt_radix_hex, k_ra8_esp_hosted_fmt_radix_min, s_ra8_esp_hosted_fmt_digits_lower, and s_ra8_esp_hosted_fmt_digits_upper.
Referenced by internal_emit_conv(), and ra8_esp_hosted_log_hexdump().
| uint32_t priv_ra8_esp_hosted_fmt_vformat | ( | char * | out, |
| uint32_t | cap, | ||
| const char * | fmt, | ||
| va_list | ap ) |
Format into a bounded buffer from a variable-argument list.
Walks fmt, copying ordinary characters and expanding the supported conversions listed in the file-level documentation. Writing stops when the buffer is one byte from full; the result is always NUL terminated when cap is non-zero, and the return value is the number of characters actually written, not the number that would have been written. Truncation is therefore visible to the caller without a second pass and without ever reporting a length past the end of the buffer.
| [out] | out | Destination buffer. Must be non-null when cap is non-zero. |
| [in] | cap | Capacity of out in bytes, including the terminator. |
| [in] | fmt | Format string. Must be non-null. |
| [in] | ap | Argument list positioned at the first conversion argument. The caller owns starting and ending it. |
| 0 | cap was zero, or a pointer was null, or fmt was empty. |
Format into a bounded buffer from a variable-argument list.
Definition at line 689 of file ra8_esp_hosted_fmt.c.
References ra8_esp_hosted_fmt_args::ap, ra8_esp_hosted_fmt_spec::consumed, internal_emit_conv(), internal_put(), k_ra8_esp_hosted_fmt_ch_nul, k_ra8_esp_hosted_fmt_ch_percent, ra8_esp_hosted_fmt_cursor::len, ra8_esp_hosted_fmt_cursor::out, and priv_ra8_esp_hosted_fmt_parse().
Referenced by priv_ra8_esp_hosted_log_vwrite().