diff options
Diffstat (limited to 'libfmt')
-rw-r--r-- | libfmt/CMakeLists.txt | 15 | ||||
-rw-r--r-- | libfmt/include/libfmt/fmt.h | 23 | ||||
-rw-r--r-- | libfmt/libmisc.c | 73 | ||||
-rw-r--r-- | libfmt/quote.c | 159 |
4 files changed, 0 insertions, 270 deletions
diff --git a/libfmt/CMakeLists.txt b/libfmt/CMakeLists.txt deleted file mode 100644 index dc626f7..0000000 --- a/libfmt/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ -# libfmt/CMakeLists.txt - Support for pico-fmt -# -# Copyright (C) 2025 Luke T. Shumaker <lukeshu@lukeshu.com> -# SPDX-License-Identifier: AGPL-3.0-or-later - -add_library(libfmt INTERFACE) -target_include_directories(libfmt PUBLIC INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/include) -target_sources(libfmt INTERFACE - libmisc.c - quote.c -) -target_link_libraries(libfmt INTERFACE - pico_fmt - libmisc -) diff --git a/libfmt/include/libfmt/fmt.h b/libfmt/include/libfmt/fmt.h deleted file mode 100644 index 692abf2..0000000 --- a/libfmt/include/libfmt/fmt.h +++ /dev/null @@ -1,23 +0,0 @@ -/* libfmt/fmt.h - Support for pico-fmt - * - * Copyright (C) 2025 Luke T. Shumaker <lukeshu@lukeshu.com> - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -#ifndef _LIBFMT_FMT_H_ -#define _LIBFMT_FMT_H_ - -#include <pico/fmt_printf.h> -#include <pico/fmt_install.h> - -#include <libmisc/obj.h> - -/** - * An object that implements fmt_formatter can be printed using - * `printf("%v", boxed_obj)`. - */ -#define fmt_formatter_LO_IFACE \ - LO_FUNC(void, format, struct fmt_state *) -LO_INTERFACE(fmt_formatter); - -#endif /* _LIBFMT_FMT_H_ */ diff --git a/libfmt/libmisc.c b/libfmt/libmisc.c deleted file mode 100644 index 134b9f0..0000000 --- a/libfmt/libmisc.c +++ /dev/null @@ -1,73 +0,0 @@ -/* libfmt/libmisc.c - Integrate pico-fmt with libmisc - * - * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -#include <stdarg.h> /* for va_list, va_start(), va_end() */ -#include <stdio.h> /* for vprintf(), putchar(), fflush() */ -#if LIB_PICO_STDIO -#include <pico/stdio.h> /* for stdio_putchar_raw() */ -#endif - -#include <libmisc/macro.h> /* for LM_UNUSED() */ -#include <libmisc/_intercept.h> /* for __lm_printf() and __lm_light_printf() */ - -#include <libfmt/fmt.h> /* for fmt_vfctprintf() */ - -#if LIB_PICO_STDIO -static void libfmt_light_fct(char character, void *LM_UNUSED(arg)) { - if (character == '\n') - stdio_putchar_raw('\r'); - stdio_putchar_raw(character); -} -#else -static void libfmt_libc_fct(char character, void *LM_UNUSED(arg)) { - putchar(character); -} -#endif - -int __lm_printf(const char *format, ...) { - va_list va; - va_start(va, format); -#if LIB_PICO_STDIO - /* pico_stdio has already intercepted vprintf for us, and - * their stdio_buffered_printer() is better than our - * libfmt_libc_fct() because buffering. */ - int ret = vprintf(format, va); -#else - int ret = fmt_vfctprintf(libfmt_libc_fct, NULL, format, va); - fflush(stdout); -#endif - va_end(va); - return ret; -} - -int __lm_light_printf(const char *format, ...) { - va_list va; - va_start(va, format); -#if LIB_PICO_STDIO - /* libfmt_light_fct() and stdio_buffered_printer() both use 68 - * bytes of stack; but the buffer lives on the stack of - * stdio.c:__wrap_vprintf(); so that's where you'll see the - * numbers be different if you're analyzing it. (Also, being - * able to skip the stdio_stack_buffer_flush() call.) */ - int ret = fmt_vfctprintf(libfmt_light_fct, NULL, format, va); - stdio_flush(); -#else - int ret = fmt_vfctprintf(libfmt_libc_fct, NULL, format, va); - fflush(stdout); -#endif - va_end(va); - return ret; -} - -static void libfmt_conv_formatter(struct fmt_state *state) { - lo_interface fmt_formatter obj = va_arg(*state->args, lo_interface fmt_formatter); - LO_CALL(obj, format, state); -} - -[[gnu::constructor]] -static void libfmt_install_formatter(void) { - fmt_install('v', libfmt_conv_formatter); -} diff --git a/libfmt/quote.c b/libfmt/quote.c deleted file mode 100644 index c91e0b0..0000000 --- a/libfmt/quote.c +++ /dev/null @@ -1,159 +0,0 @@ -/* libfmt/quote.c - C-string quoting for pico-fmt - * - * Copyright (C) 2025 Luke T. Shumaker <lukeshu@lukeshu.com> - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -#include <string.h> /* for strnlen() */ -#include <stdint.h> /* for uint{n}_t() */ - -#include <libfmt/fmt.h> - -enum quote { - QUOTE_NONE, /* c */ - QUOTE_SIMPLE, /* \c */ - QUOTE_U4, /* \uABCD */ - QUOTE_U8, /* \UABCDABCD */ -}; - -static inline enum quote needs_quote(uint32_t ch) { - if (ch == '\a' || - ch == '\b' || - ch == '\f' || - ch == '\n' || - ch == '\r' || - ch == '\t' || - ch == '\v' || - ch == '\\' || - ch == '\'' || - ch == '"' || - ch == '?') - return QUOTE_SIMPLE; - else if (' ' <= ch && ch <= '~') - return QUOTE_NONE; - else if (ch < 0x10000) - return QUOTE_U4; - else - return QUOTE_U8; -} - -/** - * Quote a string to ASCII-only C syntax. Valid UTF-8 is quoted as - * short C-escape characters, \uABCD or \UABCDABCD; invalid UTF-8 is - * quoted as \xAB. - */ -static void libfmt_conv_quote(struct fmt_state *state) { - uint32_t ch; - uint8_t chlen; - - const char *in = va_arg(*state->args, char*); - size_t in_len = strnlen(in, (state->flags & FMT_FLAG_PRECISION) ? state->precision : (size_t)-1); - - size_t out_len = 2; - for (size_t pos = 0; pos < in_len;) { - if ((in[pos] & 0b10000000) == 0b00000000) { ch = in[pos] & 0b01111111; chlen = 1; } - else if ((in[pos] & 0b11100000) == 0b11000000) { ch = in[pos] & 0b00011111; chlen = 2; } - else if ((in[pos] & 0b11110000) == 0b11100000) { ch = in[pos] & 0b00001111; chlen = 3; } - else if ((in[pos] & 0b11111000) == 0b11110000) { ch = in[pos] & 0b00000111; chlen = 4; } - else goto measure_invalid_utf8; - if ((ch == 0 && chlen != 1) || pos + chlen > in_len) goto measure_invalid_utf8; - for (uint8_t i = 1; i < chlen; i++) { - if ((in[pos+i] & 0b11000000) != 0b10000000) goto measure_invalid_utf8; - ch = (ch << 6) | (in[pos+i] & 0b00111111); - } - if (ch > 0x10FFFF) goto measure_invalid_utf8; - pos += chlen; - - switch (needs_quote(ch)) { - case QUOTE_NONE : out_len += 1; break; - case QUOTE_SIMPLE : out_len += 2; break; - case QUOTE_U4 : out_len += 6; break; - case QUOTE_U8 : out_len += 10; break; - } - continue; - measure_invalid_utf8: - pos++; - out_len += 4; /* \xAB */ - } - - if (!(state->flags & FMT_FLAG_LEFT)) { - for (size_t i = 0; i + out_len < state->width; i++) { - fmt_state_putchar(state, ' '); - } - } - - fmt_state_putchar(state, '"'); - for (size_t pos = 0; pos < in_len;) { - if ((in[pos] & 0b10000000) == 0b00000000) { ch = in[pos] & 0b01111111; chlen = 1; } - else if ((in[pos] & 0b11100000) == 0b11000000) { ch = in[pos] & 0b00011111; chlen = 2; } - else if ((in[pos] & 0b11110000) == 0b11100000) { ch = in[pos] & 0b00001111; chlen = 3; } - else if ((in[pos] & 0b11111000) == 0b11110000) { ch = in[pos] & 0b00000111; chlen = 4; } - else goto output_invalid_utf8; - if ((ch == 0 && chlen != 1) || pos + chlen > in_len) goto output_invalid_utf8; - for (uint8_t i = 1; i < chlen; i++) { - if ((in[pos+i] & 0b11000000) != 0b10000000) goto output_invalid_utf8; - ch = (ch << 6) | (in[pos+i] & 0b00111111); - } - if (ch > 0x10FFFF) goto output_invalid_utf8; - pos += chlen; - - switch (needs_quote(ch)) { - case QUOTE_NONE: - fmt_state_putchar(state, ch); - break; - case QUOTE_SIMPLE: - fmt_state_putchar(state, '\\'); - switch (ch) { - case '\a': fmt_state_putchar(state, 'a'); break; - case '\b': fmt_state_putchar(state, 'b'); break; - case '\f': fmt_state_putchar(state, 'f'); break; - case '\n': fmt_state_putchar(state, 'n'); break; - case '\r': fmt_state_putchar(state, 'r'); break; - case '\t': fmt_state_putchar(state, 't'); break; - case '\v': fmt_state_putchar(state, 'v'); break; - case '\\': fmt_state_putchar(state, '\\'); break; - case '\'': fmt_state_putchar(state, '\''); break; - case '"': fmt_state_putchar(state, '"'); break; - case '?': fmt_state_putchar(state, '?'); break; - } - break; - case QUOTE_U4: - fmt_state_putchar(state, '\\'); - fmt_state_putchar(state, 'u'); - fmt_state_putchar(state, (ch >> 12) & 0xF); - fmt_state_putchar(state, (ch >> 8) & 0xF); - fmt_state_putchar(state, (ch >> 4) & 0xF); - fmt_state_putchar(state, (ch >> 0) & 0xF); - break; - case QUOTE_U8: - fmt_state_putchar(state, '\\'); - fmt_state_putchar(state, 'U'); - fmt_state_putchar(state, (ch >> 28) & 0xF); - fmt_state_putchar(state, (ch >> 24) & 0xF); - fmt_state_putchar(state, (ch >> 20) & 0xF); - fmt_state_putchar(state, (ch >> 16) & 0xF); - fmt_state_putchar(state, (ch >> 12) & 0xF); - fmt_state_putchar(state, (ch >> 8) & 0xF); - fmt_state_putchar(state, (ch >> 4) & 0xF); - fmt_state_putchar(state, (ch >> 0) & 0xF); - break; - } - continue; - output_invalid_utf8: - fmt_state_putchar(state, '\\'); - fmt_state_putchar(state, 'x'); - fmt_state_putchar(state, (in[pos] >> 4) & 0xF); - fmt_state_putchar(state, (in[pos] >> 0) & 0xF); - pos++; - } - fmt_state_putchar(state, '"'); - - for (size_t i = 0; i + out_len < state->width; i++) { - fmt_state_putchar(state, ' '); - } -} - -[[gnu::constructor]] -static void libfmt_install_quote(void) { - fmt_install('q', libfmt_conv_quote); -} |