Hello, On Thu, Apr 24, 2008 at 05:22:28PM +0200, Freddy Spierenburg wrote: > The attached patch does add this support.
Unfortunately the yesterday patch featured a grave bug. I
overlooked the _ulong variable. Hence my patch could not handle
the MSB part of the long long, pretty pointless.
In solving this bug I could take two directions. Make _ulong a
long long or invent an extra _ulonglong. For performance reason I
chose the last route. I think those few extra conditional jumps
are worth not having to do 64-bit arithmetic on all integers,
please correct me if I'm wrong. Or perhaps you all think I'm
braindead anyway, trying to do 64-bit arithmetic on a simple
16-bit CPU. :)
Next I stumbled upon a gcc problem. I got the error below, while
compiling vuprintf.c:
stdlib/vuprintf.c: In function `vuprintf':
stdlib/vuprintf.c:605: internal error: Segmentation fault
A little bit of investigation showed me the line below was
causing the trouble:
notlastdigit=(_ulonglong>=base);
For some strange reason gcc has trouble comparing the long long
variable _ulonglong to the base. Unfortunately I do not have the
guts (yet) to dive into the gcc source. Does anybody have an idea
what is going on?
I changed the line into the line below and that works without
trouble:
notlastdigit=((_ulonglong>>32)>0)||((unsigned long)_ulonglong>=base);
But the elegant department is probably raising an eyebrow or two.
Anyway, please find attached a patch that this time correctly
adds the long long support to the printf() family. Any comments
are appreciated.
--
$ cat ~/.signature
Freddy Spierenburg <[email protected]> http://freddy.snarl.nl/
GnuPG: 0x7941D1E1=C948 5851 26D2 FA5C 39F1 E588 6F17 FD5D 7941 D1E1
$ # Please read http://www.ietf.org/rfc/rfc2015.txt before complain!
diff -Naur msp430-libc-20071026-orig/mspgcc-libc/src/stdlib/vuprintf.c msp430-libc-20071026/mspgcc-libc/src/stdlib/vuprintf.c
--- msp430-libc-20071026-orig/mspgcc-libc/src/stdlib/vuprintf.c 2007-10-26 22:33:50.000000000 +0000
+++ msp430-libc-20071026/mspgcc-libc/src/stdlib/vuprintf.c 2008-04-25 13:49:37.000000000 +0000
@@ -155,7 +155,7 @@
#define LADJUST 0x10 /* left adjustment */
#define ZEROPAD 0x20 /* zero (as opposed to blank) pad */
#define HEXPREFIX 0x40 /* add 0x or 0X prefix */
-
+#define LONGLONGINT 0x80 /* long long integer */
int vuprintf(int (*func)(int), const char *fmt0, va_list ap)
{
@@ -169,6 +169,7 @@
signed char prec; /* precision from format (%.3d), or -1 */
char sign; /* sign prefix (' ', '+', '-', or \0) */
unsigned long _ulong=0; /* integer arguments %[diouxX] */
+ unsigned long long _ulonglong=0; /* integer arguments %[diouxX] */
#define OCT 8
#define DEC 10
#define HEX 16
@@ -216,7 +217,10 @@
{
if (flags&LONGINT)
{
- _ulong=va_arg(ap, unsigned long);
+ if (flags&LONGLONGINT)
+ _ulonglong=va_arg(ap, unsigned long long);
+ else
+ _ulong=va_arg(ap, unsigned long);
}
else
{
@@ -312,7 +316,10 @@
}
else if (ch=='l')
{
- flags |= LONGINT;
+ if (flags & LONGINT)
+ flags |= LONGLONGINT;
+ else
+ flags |= LONGINT;
goto rflag;
}
else if (ch=='c')
@@ -327,7 +334,10 @@
flags |= LONGINT;
if (flags&LONGINT)
{
- _ulong=va_arg(ap, long);
+ if (flags&LONGLONGINT)
+ _ulonglong=va_arg(ap, long long);
+ else
+ _ulong=va_arg(ap, long);
}
else
{
@@ -336,10 +346,21 @@
_ulong = flags&SHORTINT ? (long)(short)_d : (long)_d;
}
- if ((long)_ulong < 0)
+ if (flags&LONGLONGINT)
+ {
+ if ((long long)_ulonglong < 0)
+ {
+ _ulonglong = -_ulonglong;
+ sign = '-';
+ }
+ }
+ else
{
- _ulong = -_ulong;
- sign = '-';
+ if ((long)_ulong < 0)
+ {
+ _ulong = -_ulong;
+ sign = '-';
+ }
}
base = DEC;
goto number;
@@ -412,7 +433,7 @@
{
base = HEX;
/* leading 0x/X only if non-zero */
- if (flags & ALT && _ulong != 0)
+ if (flags & ALT && ((_ulong != 0) || (_ulonglong != 0)))
flags |= HEXPREFIX;
/* unsigned conversions */
@@ -433,13 +454,27 @@
* -- ANSI X3J11
*/
cp = buf + BUF;
- if (_ulong != 0 || prec != 0)
+ if (((_ulong != 0) || (_ulonglong != 0)) || prec != 0)
{
register unsigned char _d, notlastdigit;
do
{
- notlastdigit=(_ulong>=base);
- _d = _ulong % base;
+ if (flags & LONGLONGINT)
+ {
+ /* This commented code line below causes an internal gcc
+ * error: Segmentation fault. The rather awkward line
+ * below is a temporarily work-around to this problem. */
+ /* notlastdigit=(_ulonglong>=base); */
+ notlastdigit=((_ulonglong>>32)>0)||((unsigned long)_ulonglong>=base);
+ _d = _ulonglong % base;
+ _ulonglong /= base;
+ }
+ else
+ {
+ notlastdigit=(_ulong>=base);
+ _d = _ulong % base;
+ _ulong /= base;
+ }
if (_d<10)
{
@@ -451,7 +486,6 @@
if (ch=='X') _d&=~0x20;
}
*--cp=_d;
- _ulong /= base;
}
while (notlastdigit);
signature.asc
Description: Digital signature
