printf(3) now supports signed integers and ptrdiff_t.

This commit is contained in:
Jonas 'Sortie' Termansen 2011-12-05 13:13:07 +01:00
parent a9609502ed
commit 0bb91ee161
2 changed files with 199 additions and 60 deletions

View File

@ -83,5 +83,69 @@ extern "C" uint64_t __umoddi3(uint64_t a, uint64_t b)
return remainder; return remainder;
} }
extern "C" int64_t __divdi3(int64_t a, int64_t b)
{
if ( a >= 0 && b >= 0 )
{
uint64_t numer = a;
uint64_t denom = b;
uint64_t result = __udivdi3(numer, denom);
return +((int64_t) result);
}
else if ( a < 0 && b >= 0 )
{
uint64_t numer = -a;
uint64_t denom = b;
uint64_t result = __udivdi3(numer, denom);
return -((int64_t) result);
}
else if ( a >= 0 && b < 0 )
{
uint64_t numer = a;
uint64_t denom = -b;
uint64_t result = __udivdi3(numer, denom);
return -((int64_t) result);
}
else // if ( a < 0 && b < 0 )
{
uint64_t numer = -a;
uint64_t denom = -b;
uint64_t result = __udivdi3(numer, denom);
return +((int64_t) result);
}
}
extern "C" int64_t __moddi3(int64_t a, int64_t b)
{
if ( a >= 0 && b >= 0 )
{
uint64_t numer = a;
uint64_t denom = b;
uint64_t result = __umoddi3(numer, denom);
return +((int64_t) result);
}
else if ( a < 0 && b >= 0 )
{
uint64_t numer = -a;
uint64_t denom = b;
uint64_t result = __umoddi3(numer, denom);
return -((int64_t) result);
}
else if ( a >= 0 && b < 0 )
{
uint64_t numer = a;
uint64_t denom = -b;
uint64_t result = __umoddi3(numer, denom);
return +((int64_t) result);
}
else // if ( a < 0 && b < 0 )
{
uint64_t numer = -a;
uint64_t denom = -b;
uint64_t result = __umoddi3(numer, denom);
return -((int64_t) result);
}
}
#endif #endif

View File

@ -30,84 +30,132 @@ namespace Maxsi
{ {
namespace String namespace String
{ {
int ConvertUInt32(uint32_t Num, char* Dest) int ConvertInt32(int32_t num, char* dest)
{ {
uint32_t Copy = Num; int result = 0;
int Result = 0; int32_t copy = num;
while ( Copy > 9 ) { Copy /= 10; Result++; } if ( num < 0 )
int Offset = Result;
while ( Offset >= 0 )
{ {
Dest[Offset] = '0' + Num % 10; Num /= 10; Offset--; *dest++ = '-';
result++;
int offset = 0;
while ( copy < -9 ) { copy /= 10; offset++; }
result += offset;
while ( offset >= 0 )
{
dest[offset] = '0' - num % 10; num /= 10; offset--;
}
}
else
{
int offset = 0;
while ( copy > 9 ) { copy /= 10; offset++; }
result += offset;
while ( offset >= 0 )
{
dest[offset] = '0' + num % 10; num /= 10; offset--;
}
} }
return Result + 1; return result + 1;
} }
int ConvertUInt64(uint64_t Num, char* Dest) int ConvertInt64(int64_t num, char* dest)
{ {
uint64_t Copy = Num; int result = 0;
int Result = 0; int64_t copy = num;
while ( Copy > 9 ) { Copy /= 10; Result++; } if ( num < 0 )
int Offset = Result;
while ( Offset >= 0 )
{ {
Dest[Offset] = '0' + Num % 10; Num /= 10; Offset--; *dest++ = '-';
result++;
int offset = 0;
while ( copy < -9 ) { copy /= 10; offset++; }
result += offset;
while ( offset >= 0 )
{
dest[offset] = '0' - num % 10; num /= 10; offset--;
}
}
else
{
int offset = 0;
while ( copy > 9 ) { copy /= 10; offset++; }
result += offset;
while ( offset >= 0 )
{
dest[offset] = '0' + num % 10; num /= 10; offset--;
}
} }
return Result + 1; return result + 1;
} }
int ConvertUInt3216(uint32_t Num, char* Dest) int ConvertUInt32(uint32_t num, char* dest)
{ {
uint32_t Copy = Num; int result = 0;
int Result = 0; uint32_t copy = num;
int offset = 0;
while ( Copy > 15 ) { Copy /= 16; Result++; } while ( copy > 9 ) { copy /= 10; offset++; }
result += offset;
int Offset = Result; while ( offset >= 0 )
while ( Offset >= 0 )
{ {
if ( Num % 16 < 10 ) dest[offset] = '0' + num % 10; num /= 10; offset--;
{
Dest[Offset] = '0' + Num % 16;
}
else
{
Dest[Offset] = 'A' + (Num % 16) - 10;
}
Num /= 16; Offset--;
} }
return Result + 1; return result + 1;
} }
int ConvertUInt6416(uint64_t Num, char* Dest) int ConvertUInt64(uint64_t num, char* dest)
{ {
uint64_t Copy = Num; int result = 0;
int Result = 0; uint64_t copy = num;
int offset = 0;
while ( Copy > 15 ) { Copy /= 16; Result++; } while ( copy > 9 ) { copy /= 10; offset++; }
result += offset;
int Offset = Result; while ( offset >= 0 )
while ( Offset >= 0 )
{ {
if ( Num % 16 < 10 ) dest[offset] = '0' + num % 10; num /= 10; offset--;
{
Dest[Offset] = '0' + Num % 16;
}
else
{
Dest[Offset] = 'A' + (Num % 16) - 10;
}
Num /= 16; Offset--;
} }
return Result + 1; return result + 1;
}
int ConvertUInt32Hex(uint32_t num, char* dest)
{
char chars[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F' };
int result = 0;
uint32_t copy = num;
int offset = 0;
while ( copy > 15 ) { copy /= 16; offset++; }
result += offset;
while ( offset >= 0 )
{
dest[offset] = chars[num % 16]; num /= 16; offset--;
}
return result + 1;
}
int ConvertUInt64Hex(uint64_t num, char* dest)
{
char chars[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F' };
int result = 0;
uint64_t copy = num;
int offset = 0;
while ( copy > 15 ) { copy /= 16; offset++; }
result += offset;
while ( offset >= 0 )
{
dest[offset] = chars[num % 16]; num /= 16; offset--;
}
return result + 1;
} }
} }
@ -137,11 +185,14 @@ namespace Maxsi
continue; continue;
} }
if ( *format == '%' ) { continue; }
const nat UNSIGNED = 0; const nat UNSIGNED = 0;
const nat BIT64 = (1<<0); const nat INTEGER = (1<<0);
const nat HEX = (1<<1); const nat BIT64 = (1<<1);
const nat STRING = 4; const nat HEX = (1<<2);
const nat CHARACTER = 5; const nat STRING = 8;
const nat CHARACTER = 9;
#ifdef PLATFORM_X64 #ifdef PLATFORM_X64
const nat WORDWIDTH = BIT64; const nat WORDWIDTH = BIT64;
#else #else
@ -168,8 +219,11 @@ namespace Maxsi
type = WORDWIDTH | HEX; type = WORDWIDTH | HEX;
scanning = false; scanning = false;
break; break;
case 't':
type |= INTEGER;
case 'z': case 'z':
case 'l': case 'l':
if ( type & WORDWIDTH ) { type |= BIT64; }
type |= WORDWIDTH; type |= WORDWIDTH;
break; break;
case 'j': case 'j':
@ -179,6 +233,11 @@ namespace Maxsi
type |= UNSIGNED; type |= UNSIGNED;
scanning = false; scanning = false;
break; break;
case 'd':
case 'i':
type |= INTEGER;
scanning = false;
break;
case 'x': case 'x':
type |= HEX; type |= HEX;
scanning = false; scanning = false;
@ -198,6 +257,13 @@ namespace Maxsi
switch ( type ) switch ( type )
{ {
case INTEGER:
{
if ( READY_SIZE - readylen < 10 ) { READY_FLUSH(); }
int32_t num = va_arg(parameters, int32_t);
readylen += String::ConvertInt32(num, ready + readylen);
break;
}
case UNSIGNED: case UNSIGNED:
{ {
if ( READY_SIZE - readylen < 10 ) { READY_FLUSH(); } if ( READY_SIZE - readylen < 10 ) { READY_FLUSH(); }
@ -205,6 +271,13 @@ namespace Maxsi
readylen += String::ConvertUInt32(num, ready + readylen); readylen += String::ConvertUInt32(num, ready + readylen);
break; break;
} }
case INTEGER | BIT64:
{
if ( READY_SIZE - readylen < 10 ) { READY_FLUSH(); }
int64_t num = va_arg(parameters, int64_t);
readylen += String::ConvertInt64(num, ready + readylen);
break;
}
case UNSIGNED | BIT64: case UNSIGNED | BIT64:
{ {
if ( READY_SIZE - readylen < 20 ) { READY_FLUSH(); } if ( READY_SIZE - readylen < 20 ) { READY_FLUSH(); }
@ -212,18 +285,20 @@ namespace Maxsi
readylen += String::ConvertUInt64(num, ready + readylen); readylen += String::ConvertUInt64(num, ready + readylen);
break; break;
} }
case INTEGER | HEX:
case UNSIGNED | HEX: case UNSIGNED | HEX:
{ {
if ( READY_SIZE - readylen < 8 ) { READY_FLUSH(); } if ( READY_SIZE - readylen < 8 ) { READY_FLUSH(); }
uint32_t num = va_arg(parameters, uint32_t); uint32_t num = va_arg(parameters, uint32_t);
readylen += String::ConvertUInt3216(num, ready + readylen); readylen += String::ConvertUInt32Hex(num, ready + readylen);
break; break;
} }
case INTEGER | BIT64 | HEX:
case UNSIGNED | BIT64 | HEX: case UNSIGNED | BIT64 | HEX:
{ {
if ( READY_SIZE - readylen < 16 ) { READY_FLUSH(); } if ( READY_SIZE - readylen < 16 ) { READY_FLUSH(); }
uint64_t num = va_arg(parameters, uint64_t); uint64_t num = va_arg(parameters, uint64_t);
readylen += String::ConvertUInt6416(num, ready + readylen); readylen += String::ConvertUInt64Hex(num, ready + readylen);
break; break;
} }
case STRING: case STRING: