Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This is work in progress, needs BIG cleanup. It's here only for discussion
Rough overview of changes:
use
struct printf_state
to pass around % specifier info.Mostly it seems to work fine and reduces register pressure, but sometimes it's a bit cumbersome. I'll look into it further.
use
struct out_base
to handleout
callback.Personally I prefer this way of handling callbacks - parameters can be easily added,
out_base
can be included in any other object (for example serial driver struct) etc.In case of out function it is a bit overkill - it is undesirable to include
printf_state
inout_base
(a lot of compiler optimizations would be disabled) and it is possible to store both function pointer and argument in state.change
idx
to beuintptr_t
and allow starting from any value.idx
is incremented on each output, so it is desirable to have it in register. Withuintptr_t
it is possible to store output buffer pointer directly, saving some instruction, with almost zero penalty (for example it is impossible to write last byte of memory)test
idx < maxidx
before output function callbetter caching of values in register, simpler output functions
add FLAGS_ZERO
I hope it's consistent with rest of flags
unify _ntoa_long and _ntoa_long_long using macro (only parameter type differs)
Removes code duplication at cost of more complicated debugging
implement (almost?) correct rounding for
%f
fmsub
is relatively simple, some FPUs (Cortex-M4) support equivalent instructionfix
%g
trailing zeroesThe implementation isn't as elegant as I'd like, it may be conditional or maybe there is better way to rewrite it
I encountered interesting unspecified case:
(unsigned int)-INT_MIN
(and(unsigned int)(0 - value)
in current code) is causing integer overflow, which is unspecified behavior in C standard. gcc was able to use this to sign-extend long first, producing incorrect result forprintf("%d", INT_MIN);
move zero-termination from
_vsnprintf
tosnprintf
fixes
printf("%c", 0);
, is cleaner (only string needs termination), simplifies code a littleuintptr_t idx
removes need to special-casesprintf(NULL, ...)
case, just pass0
as limitadded new test cases from other sources (mainly libsanity), discovering some bugs (mostly opened as issues).
modified tests are just temporary hack to get testing quickly, I'll clean it up