Usermode/libc - Fixed %x/%X being signed in printf
[tpg/acess2.git] / Usermode / Libraries / libc.so_src / printf.c
index 869ba22..1b61cba 100644 (file)
@@ -1,4 +1,4 @@
-/*
+#include <string.h>/*
  * Acess2 C Library
  * - By John Hodge (thePowersGang)
  *
@@ -200,7 +200,7 @@ EXPORT int _vcprintf_int(printf_putch_t putch_cb, void *putch_h, const char *for
                                _addchar('0');
                                _addchar(c);
                        }
-                       arg = bLongLong ? va_arg(args, int64_t) : va_arg(args, int32_t);
+                       arg = bLongLong ? va_arg(args, uint64_t) : va_arg(args, uint32_t);
                        pos += _printf_itoa(putch_cb, putch_h, arg, 16, c=='X',
                                FALSE, '\0', precision, minSize,cNumPad,bJustifyLeft);
                        break;
@@ -240,6 +240,13 @@ EXPORT int _vcprintf_int(printf_putch_t putch_cb, void *putch_h, const char *for
                        pos += _printf_ftoa(putch_cb, putch_h, arg_f, 10, FPN_SCI,
                                precision, 0, bJustifyLeft, c == 'E');
                        break;
+               // Scientific Float
+               case 'g':
+               case 'G':
+                       arg_f = bLong ? va_arg(args, long double) : va_arg(args, double);
+                       pos += _printf_ftoa(putch_cb, putch_h, arg_f, 10, FPN_SHORTEST,
+                               precision, 0, bJustifyLeft, c == 'G');
+                       break;
                // Hexadecimal Scientific
                case 'a':
                case 'A':
@@ -417,7 +424,8 @@ size_t _printf_itoa(printf_putch_t putch_cb, void *putch_h, uint64_t num,
        tmpBuf[pos++] = map[ num % base ];              // Last digit of {number}
        
        // length of number, minus the sign character
-       PadLength -= pos - sign_is_neg - (SignChar != '\0');
+       PadLength -= pos + (sign_is_neg || SignChar != '\0');
+       Precision -= pos + (sign_is_neg || SignChar != '\0');
        if( !bPadRight )
        {
                while(PadLength-- > 0)
@@ -465,13 +473,13 @@ int expand_double(double num, uint64_t *Significand, int16_t *Exponent, int *Sig
 //     printf("%llx %i %i %llx\n", *bit_rep, (int)*SignIsNeg, (int)*Exponent, *Significand);
 
        // Subnormals
-       if( *Exponent == -1023 && *Significand != 0 )
+       if( *Exponent == -0x3FF && *Significand != 0 )
                return 1;
        // Infinity
-       if( *Exponent == 0x800 && *Significand == 0)
+       if( *Exponent == 0x400 && *Significand == 0)
                return 2;
        // NaNs
-       if( *Exponent == 0x800 && *Significand != 0)
+       if( *Exponent == 0x400 && *Significand != 0)
                return 3;
 
        return 0;
@@ -573,12 +581,111 @@ size_t _printf_ftoa_hex(printf_putch_t putch_cb, void *putch_h, long double num,
        return ret;
 }
 
+#if 0
+size_t _printf_itoa_fixed(printf_putch_t putch_cb, void *putch_h, uint64_t num, size_t Base)
+{
+       uint64_t        den;
+       size_t  ret = 0;
+
+       den = 1ULL << (64-1);
+       
+       while( den )
+       {
+               putch_cb(putch_h, cDIGITS[num / den]);
+               ret ++;
+               num %= den;
+               den /= Base;
+       }
+
+       return ret;
+}
+
+size_t _printf_ftoa_dec(printf_putch_t putch_cb, void *putch_h, long double num, enum eFPN Notation, int Precision, int bForcePoint, int bForceSign, int bCapitals)
+{
+       size_t  ret = 0;
+        int    i;
+
+       #define _putch(_ch) do{\
+               putch_cb(putch_h, bCapitals ? toupper(_ch) : _ch), ret++;\
+       }while(0)
+       
+       uint64_t        significand;
+        int16_t        exponent;
+        int    signisneg;
+        int    rv = expand_double(num, &significand, &exponent, &signisneg);
+       switch(rv)
+       {
+       // 0: No errors, nothing special
+       case 0:
+               break;
+       // 1: Subnormals
+       case 1:
+               // TODO: Subnormal = 0?
+               break;
+       // 2: Infinity
+       case 2:
+               _putch('i');
+               _putch('n');
+               _putch('f');
+               return 3;
+       case 3:
+               _putch('N');
+               _putch('a');
+               _putch('N');
+               return 3;
+       }
+
+       uint64_t        whole, part;
+        int    pre_zeros, post_zeros;
+
+       #define XXX     0
+       if( Notation == FPN_SCI )
+       {
+       }
+       else if( exponent < 0 )
+       {
+               whole = 0;
+               part = XXX;
+               pre_zeros = 0;
+               post_zeros = XXX;
+       }
+       else if( exponent >= 64 )
+       {
+               part = 0;
+               whole = XXX;
+               pre_zeros = XXX;
+               post_zeros = 0;
+       }
+       else
+       {
+               // Split into fixed point
+               whole = (1 << exponent) | (significand >> (64-exponent));
+               part = significand << exponent;
+               pre_zeros = 0;
+               post_zeros = 0;
+       }
+
+       
+       // Whole portion
+       ret += _printf_itoa(putch_cb, putch_h, whole, 10, FALSE, FALSE, '\0', 0, 0, '\0', FALSE);
+       for(i = pre_zeros; i --; )      _putch('0');
+       // TODO: Conditional point
+       _putch('-');
+       for(i = post_zeros; i--; )      _putch('0');
+       ret += _printf_itoa_fixed(putch_cb, putch_h, part, 10);
+       
+       #undef _putch
+
+       return 0;
+}
+#endif
+
 size_t _printf_ftoa(printf_putch_t putch_cb, void *putch_h, long double num, size_t Base, enum eFPN Notation, int Precision, int bForcePoint, int bForceSign, int bCapitals)
 {
        uint64_t        significand;
        int16_t exponent;
         int    signisneg;
-        int    rv;
+        int    rv, i;
        size_t  ret = 0;
 
        #define _putch(_ch) do{\
@@ -631,12 +738,24 @@ size_t _printf_ftoa(printf_putch_t putch_cb, void *putch_h, long double num, siz
        {
                //TODO:
                //int   first_set_sig = BSL(significand);
-       //      TODO: if( num > pos(Base, 2+Precision+2+log_base(exponent) )
-               Notation = FPN_SCI;
+               // bSign+log10(num)+1+precision vs. bSign+1+1+precision+1+1+log10(exponent)
+                int    log10_num = exponent * 301 / 1000;      // log_10(2) = 0.30102999566...
+                int    log10_exp10 = 2;
+                int    sci_len = (signisneg || bForceSign) + 2 + (Precision-1) + 2 + log10_exp10;
+                int    std_whole_len = (log10_num > 0 ? log10_num : 1);
+                int    std_len = (signisneg || bForceSign) + std_whole_len + 1 + (Precision-std_whole_len);
+               if( sci_len > std_len ) {
+                       Precision -= std_whole_len;
+                       Notation = FPN_STD;
+               }
+               else {
+                       Precision -= 1;
+                       Notation = FPN_SCI;
+               }
        }
 
        double precision_max = 1;
-       while(Precision--)
+       for(i = Precision; i--; )
                precision_max /= Base;
 
        // Determine scientific's exponent and starting denominator
@@ -666,9 +785,9 @@ size_t _printf_ftoa(printf_putch_t putch_cb, void *putch_h, long double num, siz
                }
                den = 1;
        }
-       else
+       else if( num != 0.0 )
        {
-               while( den < num )
+               while( den <= num )
                        den *= Base;
                den /= Base;
        }
@@ -680,6 +799,8 @@ size_t _printf_ftoa(printf_putch_t putch_cb, void *putch_h, long double num, siz
                _putch('+');
        else {
        }
+       
+       num += precision_max/10 * 4.999;
 
         int    value;
        // Whole section
@@ -691,10 +812,10 @@ size_t _printf_ftoa(printf_putch_t putch_cb, void *putch_h, long double num, siz
        } while( den >= 1 );
 
        // Decimal point (if needed/forced)     
-       if( den >= precision_max || bForcePoint )
+       if( Precision > 0 || bForcePoint )
                _putch('.');
        // Decimal section
-       while( den >= precision_max )
+       for(i = Precision; i--; )
        {
                num = _longdiv(num, den, &value);
                _putch(cDIGITS[value]);
@@ -707,7 +828,7 @@ size_t _printf_ftoa(printf_putch_t putch_cb, void *putch_h, long double num, siz
                        _putch('p');
                else
                        _putch('e');
-               ret += _printf_itoa(putch_cb, putch_h, sci_exponent, Base, FALSE, TRUE, '+', 0, 0, '\0', FALSE);
+               ret += _printf_itoa(putch_cb, putch_h, sci_exponent, Base, FALSE, TRUE, '+', 3, 0, '\0', FALSE);
        }       
 
        #undef _putch

UCC git Repository :: git.ucc.asn.au