/* * crprintf - printf with inline color tags and variables, powered by a register-based VM * * Copyright (c) 2026 theMackabu (me@themackabu.dev) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * usage: * crprintf("error: something went wrong\n"); * crprintf("info: hello %s\n", name); * crprintf("<#ff8800>orange text\n"); * crprintf(" %s %s\n", cmd->name, cmd->desc); * * supported tags: * * ... etc * ... *
    (underline) * etc - combine styles with underscores * etc - combine styles with + * <#RRGGBB> or <#RGB> for arbitrary 24-bit foreground colors * ... - right-pad contents to N visible columns *
    - emit a newline, - emit N newlines * ... - left-pad (right-align) contents to N visible columns * - emit N spaces * - emit N spaces (alias for space) * or - define a named style variable * {let name=style1+style2+...} or {let name=style1, name2=style2...} - alternative syntax * quoted values: {let label='hello'} or - quotes are stripped from value * <$name> to apply a variable as a style, {name} to emit its value as literal text * {~name} for lowercase, {^name} for uppercase * {~'string'} for lowercase literal, {^'string'} for uppercase literal * or to reset (pops one level) * to reset all styles (clears entire stack) * << and >> to emit literal < and > * %% to emit a literal % */ #ifndef CRPRINTF_H #define CRPRINTF_H #include #include #include typedef struct crprintf_state crprintf_state; typedef struct crprintf_compiled crprintf_compiled; void crprintf_set_color(bool enable); bool crprintf_get_color(void); void crprintf_set_debug(bool enable); bool crprintf_get_debug(void); void crprintf_set_debug_hex(bool enable); bool crprintf_get_debug_hex(void); crprintf_compiled *crprintf_compile(const char *fmt); int crprintf_exec(struct crprintf_compiled *prog, FILE *stream, ...); int crsprintf_inner(struct crprintf_compiled *prog, char *buf, size_t size, ...); void crprintf_var(const char *name, const char *value); void crprintf_hexdump(struct crprintf_compiled *prog, FILE *out); void crprintf_disasm(struct crprintf_compiled *prog, FILE *out); crprintf_state *crprintf_state_new(void); void crprintf_state_free(crprintf_state *state); crprintf_state *crprintf_state_clone(const crprintf_state *state); bool crprintf_state_eq(const crprintf_state *a, const crprintf_state *b); int crsprintf_stateful(char *buf, size_t size, crprintf_state *state, const char *fmt, ...); int crfprintf_stateful(FILE *stream, crprintf_state *state, const char *fmt, ...); crprintf_compiled *crprintf_recompile(crprintf_compiled *prev, const char *fmt); int crsprintf_compiled(char *buf, size_t size, crprintf_state *state, crprintf_compiled *prog, ...); void crprintf_compiled_free(crprintf_compiled *prog); #define _CRPRINTF_INIT(prog, fmt) \ if (!prog) { \ prog = crprintf_compile(fmt); \ if (crprintf_get_debug()) crprintf_disasm(prog, stderr); \ if (crprintf_get_debug_hex()) crprintf_hexdump(prog, stderr); \ } #define crprintf(fmt, ...) ({ \ static crprintf_compiled *_cp_prog_ = NULL; \ _CRPRINTF_INIT(_cp_prog_, fmt); \ crprintf_exec(_cp_prog_, stdout, ##__VA_ARGS__); \ }) #define crfprintf(stream, fmt, ...) ({ \ static crprintf_compiled *_cp_prog_ = NULL; \ _CRPRINTF_INIT(_cp_prog_, fmt); \ crprintf_exec(_cp_prog_, stream, ##__VA_ARGS__); \ }) #define crsprintf(buf, size, fmt, ...) ({ \ static crprintf_compiled *_cp_prog_ = NULL; \ _CRPRINTF_INIT(_cp_prog_, fmt); \ crsprintf_inner(_cp_prog_, buf, size, ##__VA_ARGS__); \ }) #endif