diff --git a/Makefile b/Makefile index 1ac111c..00bc875 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,6 @@ CFLAGS = --std=c99 -O2 -pedantic -Wall -Wextra -Wshadow +CFLAGS += -Wstrict-prototypes -Wmissing-prototypes -Wundef +CFLAGS += -Wpointer-arith -Wcast-align -Wcast-qual -Wredundant-decls %_check: %.out %.gold cmp $^ diff --git a/README.md b/README.md index 942872c..1f63328 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Motivation I was recently working on an embedded project with a STM32 MCU. The chip had 32kB of flash memory - that's heaps for a microcontroller! -How surprised I was when the linker suddelnly failed saying that +How surprised I was when the linker suddenly failed saying that the program is too big and won't fit! How come?! It's just some USB, I2C, GPIO, a few timers ... and snprintf() @@ -88,12 +88,13 @@ All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * Neither the name of the auhor nor the names of its contributors + * Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. diff --git a/mini-printf.c b/mini-printf.c index 53cfe99..7ee9bc1 100644 --- a/mini-printf.c +++ b/mini-printf.c @@ -53,11 +53,11 @@ mini_strlen(const char *s) static unsigned int mini_itoa(int value, unsigned int radix, unsigned int uppercase, unsigned int unsig, - char *buffer, unsigned int zero_pad) + char *buffer, unsigned int zero_pad, unsigned int width) { - char *pbuffer = buffer; - int negative = 0; - unsigned int i, len; + char *pbuffer = buffer; + int negative = 0; + unsigned int i, len; /* No support for unusual radixes. */ if (radix > 16) @@ -81,6 +81,9 @@ mini_itoa(int value, unsigned int radix, unsigned int uppercase, unsigned int un if (negative) *(pbuffer++) = '-'; + for (i = (pbuffer - buffer); i < width; i++) + *(pbuffer++) = ' '; + *(pbuffer) = '\0'; /* ... now we reverse it (could do it recursively but will @@ -137,18 +140,30 @@ mini_vsnprintf(char *buffer, unsigned int buffer_len, const char *fmt, va_list v b.pbuffer = buffer; b.buffer_len = buffer_len; + if (buffer_len > 0) *buffer = 0; + while ((ch=*(fmt++))) { if ((unsigned int)((b.pbuffer - b.buffer) + 1) >= b.buffer_len) break; if (ch!='%') _putc(ch, &b); else { - char zero_pad = 0; + unsigned int zero_pad = 0; char *ptr; unsigned int len; + unsigned int width = 0; - ch=*(fmt++); + ch=*(fmt++); // step over the % + /* Format width */ + if (ch>'0' && ch<='9') { + width = ch-'0'; + while (ch=*(fmt++), ch>='0' && ch<='9') { + width = width*10 + ch - '0'; + } + if (ch == '\0') + goto end; + } /* Zero padding requested */ if (ch=='0') { ch=*(fmt++); @@ -165,13 +180,15 @@ mini_vsnprintf(char *buffer, unsigned int buffer_len, const char *fmt, va_list v case 'u': case 'd': - len = mini_itoa(va_arg(va, unsigned int), 10, 0, (ch=='u'), bf, zero_pad); + if (width > sizeof bf) width = sizeof bf; /* prevent buffer overflow */ + len = mini_itoa(va_arg(va, unsigned int), 10, 0, (ch=='u'), bf, zero_pad, width); _puts(bf, len, &b); break; case 'x': case 'X': - len = mini_itoa(va_arg(va, unsigned int), 16, (ch=='X'), 1, bf, zero_pad); + if (width > sizeof bf) width = sizeof bf; /* prevent buffer overflow */ + len = mini_itoa(va_arg(va, unsigned int), 16, (ch=='X'), 1, bf, zero_pad, width); _puts(bf, len, &b); break; @@ -181,7 +198,11 @@ mini_vsnprintf(char *buffer, unsigned int buffer_len, const char *fmt, va_list v case 's' : ptr = va_arg(va, char*); - _puts(ptr, mini_strlen(ptr), &b); + { + unsigned l = mini_strlen(ptr); + for (unsigned ix=l; ix +#ifndef _LIBC_REVERT #include "mini-printf.h" +#define snprintf mini_snprintf +#endif int main(void) { char buff[30]; - mini_snprintf(buff, sizeof buff, "testing %d %d %07d", 1, 2, 3); + snprintf(buff, sizeof buff, "testing %d %d %07d", 1, 2, 3); puts(buff); - mini_snprintf(buff, sizeof buff, "faster %s %ccheaper%c", "and", 34, 34); + snprintf(buff, sizeof buff, "faster %s %ccheaper%c", "and", 34, 34); puts(buff); - mini_snprintf(buff, sizeof buff, "%x %% %X", 0xdeadf00d, 0xdeadf00d); + snprintf(buff, sizeof buff, "%x %% %X", 0xdeadf00d, 0xdeadf00d); puts(buff); - mini_snprintf(buff, sizeof buff, "%09d%09d%09d%09d%09d", 1, 2, 3, 4, 5); + snprintf(buff, sizeof buff, "%09d%09d%09d%09d%09d", 1, 2, 3, 4, 5); puts(buff); - mini_snprintf(buff, sizeof buff, "%d %u %d %u", 50, 50, -50, -50); + snprintf(buff, sizeof buff, "%d %u %d %u", 50, 50, -50, -50); + puts(buff); + snprintf(buff, sizeof buff, "%0"); + puts(buff); + snprintf(buff, sizeof buff, "a%0"); + puts(buff); + snprintf(buff, sizeof buff, "%"); + puts(buff); + snprintf(buff, sizeof buff, "b%"); + puts(buff); + snprintf(buff, 0, "%s", "hello"); + puts(buff); + snprintf(buff, sizeof buff, ""); + puts(buff); + snprintf(buff, sizeof buff, "(%6d) (%12d)", 78, 78); + puts(buff); + snprintf(buff, sizeof buff, "(%s) (%12s) (%s)", "a", "b", "xcccccccccccccccx"); + puts(buff); + snprintf(buff, sizeof buff, "(%s)", "xcccccccccccccccx"); puts(buff); return 0; } diff --git a/test1.gold b/test1.gold index 3a0c347..4d8dafb 100644 --- a/test1.gold +++ b/test1.gold @@ -3,3 +3,12 @@ faster and "cheaper" deadf00d % DEADF00D 00000000100000000200000000300 50 50 -50 4294967246 + +a + +b +b + +( 78) ( 78) +(a) ( b) (xcccccccc +(xcccccccccccccccx)