The following patch (analogous to one I made to the PRINTF_MIN code which saved quite a bit of code space) has strangely contradictory code size effects.
If anyone else feels like tying it with a different compiler version (I'm using gcc-7 SVN trunk from a few days ago), I'd be interested in the results. ("size `find . -name vfprintf_std.o | sort`" is the heart of these tables.) Before After Delta filename 1030 1036 + 6 ./avr/lib/avr2/tiny-stack/vfprintf_std.o 1030 1052 +22 ./avr/lib/avr2/vfprintf_std.o 916 932 +16 ./avr/lib/avr25/tiny-stack/vfprintf_std.o 916 948 +32 ./avr/lib/avr25/vfprintf_std.o 1064 1080 +16 ./avr/lib/avr3/vfprintf_std.o 1064 1080 +16 ./avr/lib/avr31/vfprintf_std.o 950 978 +28 ./avr/lib/avr35/vfprintf_std.o 916 948 +32 ./avr/lib/avr4/vfprintf_std.o 946 974 +28 ./avr/lib/avr5/vfprintf_std.o 1028 974 -54 ./avr/lib/avr51/vfprintf_std.o 1026 974 -54 ./avr/lib/avr6/vfprintf_std.o 946 962 +16 ./avr/lib/avrxmega2/vfprintf_std.o 1016 962 -54 ./avr/lib/avrxmega4/vfprintf_std.o 1016 962 -54 ./avr/lib/avrxmega5/vfprintf_std.o 1016 962 -54 ./avr/lib/avrxmega6/vfprintf_std.o 1016 962 -54 ./avr/lib/avrxmega7/vfprintf_std.o What I'm doing is merging the signed decimal printing code with the rest, so the "(flags & FL_LONG) ? va_arg(ap,long) : va_arg(ap,int)" code and the call to __ultoa_invert() is shared. That requires a flag bit for "signed" which is hard to find; they're nearly all in use. Already, the FL_SPACE and FL_PLUS flags do double duty; if FL_ALT is set (which never happens with decimal), then they're used for the FL_ALTHEX and FL_ALTUPP flags. (I can't use the FL_NEGATIVE flag because that's the same bit as FL_LONG, and so not available until after the va_arg() call.) So I use the FL_ALT flag again, but directly test if base == 10. If so, it's a "signed" flag. There's a little bit more flag manipulation, but I had hoped the net effect would be beneficial. Unfortunately, it's confusing. diff --git a/avr-libc/libc/stdio/vfprintf.c b/avr-libc/libc/stdio/vfprintf.c index 0d8c892a..0e1df5ba 100644 --- a/avr-libc/libc/stdio/vfprintf.c +++ b/avr-libc/libc/stdio/vfprintf.c @@ -615,19 +615,14 @@ int vfprintf (FILE * stream, const char *fmt, va_list ap) } } - if (c == 'd' || c == 'i') { - long x = (flags & FL_LONG) ? va_arg(ap,long) : va_arg(ap,int); - flags &= ~(FL_NEGATIVE | FL_ALT); - if (x < 0) { - x = -x; - flags |= FL_NEGATIVE; - } - c = __ultoa_invert (x, (char *)buf, 10) - (char *)buf; - - } else { + { int base; - if (c == 'u') { + if (c == 'd' || c == 'i') { + flags |= FL_ALT; + base = 10; + goto ultoa; + } else if (c == 'u') { flags &= ~FL_ALT; base = 10; goto ultoa; @@ -638,7 +633,7 @@ int vfprintf (FILE * stream, const char *fmt, va_list ap) switch (c) { case 'o': base = 8; - goto ultoa; + break; case 'p': flags |= FL_ALT; /* FALLTHROUGH */ @@ -646,22 +641,28 @@ int vfprintf (FILE * stream, const char *fmt, va_list ap) if (flags & FL_ALT) flags |= FL_ALTHEX; base = 16; - goto ultoa; + break; case 'X': if (flags & FL_ALT) flags |= (FL_ALTHEX | FL_ALTUPP); base = 16 | XTOA_UPPER; - ultoa: - c = __ultoa_invert ((flags & FL_LONG) - ? va_arg(ap, unsigned long) - : va_arg(ap, unsigned int), - (char *)buf, base) - (char *)buf; - flags &= ~FL_NEGATIVE; break; - default: goto ret; } + ultoa: + { + long x = (flags & FL_LONG) ? va_arg(ap,long) : va_arg(ap,int); + flags &= ~FL_LONG; + if (flags & FL_ALT && base == 10) { + flags &= ~FL_ALT; + if (x < 0) { + x = -x; + flags |= FL_NEGATIVE; + } + } + c = __ultoa_invert (x, (char *)buf, base) - (char *)buf; + } } { _______________________________________________ AVR-libc-dev mailing list AVR-libc-dev@nongnu.org https://lists.nongnu.org/mailman/listinfo/avr-libc-dev