printf replacement for embedded programming
printf-c.cc
is a C++ module that replaces certain C-language libc functions
with a tiny alternatives suitable for embedded programs.
The functions replaced areprintf
,vprintf
,sprintf
,vsprintf
,puts
,putchar
,fprintf
¹,vfprintf
¹,fiprintf
¹ ⁴,fputs
¹,fputc
¹,fflush
¹,fwrite
¹,snprintf
²,vsnprintf
²,asprintf
³, andvasprintf
³,
To use, compile printf-c.cc
using your C++ compiler, and link it into your project.
You will have to add the following linker flags:
-Wl,--wrap,printf -Wl,--wrap,fprintf -Wl,--wrap,sprintf -Wl,--wrap,asprintf
-Wl,--wrap,vprintf -Wl,--wrap,vfprintf -Wl,--wrap,vsprintf -Wl,--wrap,vasprintf
-Wl,--wrap,puts -Wl,--wrap,putchar -Wl,--wrap,snprintf -Wl,--wrap,fwrite
-Wl,--wrap,fputs -Wl,--wrap,fputc -Wl,--wrap,vsnprintf -Wl,--wrap,fflush
-Wl,--wrap,fiprintf
What -Wl,--wrap,somefunc
does it replaces all calls to somefunc
with calls to __wrap_somefunc
,
and all calls to __real_somefunc
with calls to the original somefunc
.
It is handy when you need to replace a library function that is not declared “weak”.
GNU build tools are probably required.
Compiling with -ffunction-sections -fdata-sections
and linking with -Wl,--gc-sections
is strongly recommended.
Compiling with -flto
is supported.
Compiling with -fbuiltin
is supported.
IMPORTANT: You will have to edit printf-c.cc file, locate wfunc
,
and replace that function with code that is suitable for your project.
The format string format is fully compliant with C99 and C++14,
with positional parameters supported optionally according to SUSv2:
"%%"
or"%" [position-specifier] [flag ...] [minimum-width-specifier] ["." precision-specifier] [length-modifier] [format-type]
Where
position-specifier
is decimal-digit [ decimal-digit ... ] "$"
minimum-width-specifier
and precision-specifier
are decimal-digit [ decimal-digit ... ]
or "*" [position-specifier]
"n"
format type"c"
format type.flag
is zero or more of these letters, in any order: "+" | "-" | "0" | "#" | " "
"+"
specifies that a plus sign should be printed in front of a non-negative number. Only affects decimal non-unsigned numeric formats." "
specifies that a space should be printed in front of a non-negative number. Only affects decimal non-unsigned numeric formats. Ignored if "+"
also given."-"
specifies that when padding to satisfy the minimum-width-specifier, the value should be left-aligned, not right-aligned."0"
specifies that when padding to satisfy the minimum-width-specifier, the value should be padded with zeroes, not spaces. Ignored if "-"
also given, or if a precision-specifier is used and STRICT_COMPLIANCE is set. Behavior is undefined if applied to non-numeric formats.#"
specifies that “0x” or “0X” should be printed in front of non-zero hexadecimal numbers, and that an octal number must always begin with zero, even if precision of 0 is explicitly specified. Ignored if STRICT_COMPLIANCE is unset."'"
flag, defined by SUSv2, is not supported"I"
flag, defined by glibc, is not supported"n"
format type.length-modifier
is "h" | "hh" | "l" | "ll" | "L" | "j" | "z" | "t"
"h"
and "hh"
are only supported if SUPPORT_H_LENGTHS is set"t"
is only supported if SUPPORT_T_LENGTH is set"j"
is only supported if SUPPORT_J_LENGTH is set"ll"
and "L"
affect float formats only if SUPPORT_LONG_DOUBLE is setwchar_t
strings or wint_t
chars are not supported.format-type
is "n" | "s" | "c" | "p" | "x" | "X" | "o" | "d" | "u" | "i" | "a" | "A" | "e" | "E" | "f" | "F" | "g" | "G" | "b"
"n"
is only supported if SUPPORT_N_FORMAT is set"b"
is only supported if SUPPORT_BINARY_FORMAT is set"e"
, "E"
, "f"
, "F"
, "g"
, and "G"
are only supported if SUPPORT_FLOAT_FORMATS is set"a"
and "A"
are only supported if SUPPORT_FLOAT_FORMATS and SUPPORT_A_FORMAT are both set"d"
and "i"
are equivalent and have the same meaning"p"
is treated similarly as %#x
, except that if STRICT_COMPLIANCE is set, "+"
and " "
flags will also be processed (this is what glibc does)"p"
format is printed as “(nil)
” (note that contrary to glibc, this string may be cut by precision-specifier)"s"
format is printed as “(null)
” (note that contrary to glibc, this string may be cut by precision-specifier)"S"
and "C"
, defined by SUSv2, are not supported"m"
, defined by glibc, is not supportedsprintf
within your stream I/O function invoked by printf
)printf
calls are not locked, so prints from different threads can interleave.printf("abc\n")
is automatically converted into puts("abc")
printf("%2$s %1$0*3$ld", 5L, "test", 4);
works and prints “test 0005”), disabled by defaultFILE*
pointer parameters are completely ignoreddprintf
, vdprintf
are not supported (POSIX.1-2008)wprintf
, fwprintf
, swprintf
, vwprintf
, vfwprintf
, and vswprintf
are not supported (C99, C++98)printf_s
, fprintf_s
, sprintf_s
, snprintf_s
, vprintf_s
, vfprintf_s
, vsprintf_s
, vsnprintf_s
, wprintf_s
, fwprintf_s
, swprintf_s
, snwprintf_s
, vwprintf_s
, vfwprintf_s
, vswprintf_s
, and vsnwprintf_s
are not supported (C11).p
or s
formats and max-width specifier is usedvsnprintf
and snprintf
are thread-safe only if your compiler honors the thread_local
attribute.⁵) If you really need more than this, edit MAX_EXPLICIT_PARAMS and MAX_AUTO_PARAMS in printf-c.cc. Their product should be less 2³²/MAX_ROUNDS.
e
, E
, f
, F
, g
, G
, a
, and A
) is all sorts of broken and disabled by defaultCopyright © Joel Yliluoma 2017. (http://iki.fi/bisqwit/)
Distribution terms: MIT