what you give them. Help stamp out software-hoarding!
-------------------------------------------------------------------------*/
-#ifdef SDCC_STACK_AUTO
- #ifdef ASM_ALLOWED
- /* Eventually we should get rid of ASM_ALLOWED completely as it */
- /* prevents portability, clobbers this source and brings only 2% */
- /* optimization. A better alternative is a completely handcrafted */
- /* asm version if needed. */
- #undef ASM_ALLOWED
- #endif
-#endif
-
-#if defined(SDCC_mcs51)
- #if defined(SDCC_STACK_AUTO)
- #if defined(SDCC_USE_XSTACK)
- #define NEAR pdata
- #else
- //strange enough "idata" doesn't work
- #define NEAR data
- #endif
- #elif defined(SDCC_MODEL_LARGE)
- #define NEAR xdata
- #else
- #define NEAR data
- #endif
-#else
- #define NEAR
-#endif
-
-#if defined(__ds390)
+#if defined (SDCC_ds390)
#define USE_FLOATS 1
#endif
#include <ctype.h>
#include <stdio.h>
#include <stdbool.h>
+#include <sdcc-lib.h>
#define PTR value.ptr
#define NULL_STRING_LENGTH 6
#endif
+#if defined (SDCC_mcs51) && defined (SDCC_MODEL_SMALL) && !defined (SDCC_STACK_AUTO)
+# define MEM_SPACE_BUF __idata
+# define MEM_SPACE_BUF_PP __idata
+#else
+# define MEM_SPACE_BUF
+# define MEM_SPACE_BUF_PP _AUTOMEM
+#endif
+
/****************************************************************************/
//typedef char * ptr_t;
#ifdef toupper
#undef toupper
#endif
+#ifdef tolower
+#undef tolower
+#endif
+#ifdef islower
+#undef islower
+#endif
+#ifdef isdigit
+#undef isdigit
+#endif
//#define toupper(c) ((c)&=~0x20)
#define toupper(c) ((c)&=0xDF)
+#define tolower(c) ((c)|=0x20)
+#define islower(c) ((unsigned char)c >= (unsigned char)'a' && (unsigned char)c <= (unsigned char)'z')
+#define isdigit(c) ((unsigned char)c >= (unsigned char)'0' && (unsigned char)c <= (unsigned char)'9')
typedef union
{
char *ptr;
} value_t;
-static const char memory_id[] = "IXCP-";
-
#ifndef SDCC_STACK_AUTO
static BOOL lower_case;
static pfn_outputchar output_char;
static void* p;
+ static value_t value;
+ static int charsOutputted;
+#endif
- #ifdef ASM_ALLOWED
- static bool lsd;
+/****************************************************************************/
- /* this one NEEDS to be in data */
- static data value_t value;
- #else
- static value_t value;
- #endif
+#ifdef SDCC_STACK_AUTO
+ #define OUTPUT_CHAR(c, p) { output_char (c, p); charsOutputted++; }
+#else
+ #define OUTPUT_CHAR(c, p) _output_char (c)
+ static void _output_char( unsigned char c )
+ {
+ output_char( c, p );
+ charsOutputted++;
+ }
#endif
-/****************************************************************************/
+/*--------------------------------------------------------------------------*/
#ifdef SDCC_STACK_AUTO
static void output_digit( unsigned char n, BOOL lower_case, pfn_outputchar output_char, void* p )
+ {
+ register unsigned char c = n + (unsigned char)'0';
+
+ if (c > (unsigned char)'9')
+ {
+ c += (unsigned char)('A' - '0' - 10);
+ if (lower_case)
+ c += (unsigned char)('a' - 'A');
+ }
+ output_char( c, p );
+ }
#else
static void output_digit( unsigned char n )
-#endif
{
- output_char( n <= 9 ? '0'+n :
- (lower_case ? n+(char)('a'-10) : n+(char)('A'-10)), p );
+ register unsigned char c = n + (unsigned char)'0';
+
+ if (c > (unsigned char)'9')
+ {
+ c += (unsigned char)('A' - '0' - 10);
+ if (lower_case)
+ c = tolower(c);
+ }
+ _output_char( c );
}
+#endif
/*--------------------------------------------------------------------------*/
#ifdef SDCC_STACK_AUTO
- #define OUTPUT_2DIGITS( B ) output_2digits( B, lower_case, output_char, p )
+ #define OUTPUT_2DIGITS( B ) { output_2digits( B, lower_case, output_char, p ); charsOutputted += 2; }
static void output_2digits( unsigned char b, BOOL lower_case, pfn_outputchar output_char, void* p )
{
output_digit( b>>4, lower_case, output_char, p );
/*--------------------------------------------------------------------------*/
-#if defined ASM_ALLOWED
-static void calculate_digit( unsigned char radix )
-{
- unsigned char i;
-
- for( i = 32; i != 0; i-- )
- {
-_asm
- clr c
- mov a,_value+0
- rlc a
- mov _value+0,a
- mov a,_value+1
- rlc a
- mov _value+1,a
- mov a,_value+2
- rlc a
- mov _value+2,a
- mov a,_value+3
- rlc a
- mov _value+3,a
- mov a,_value+4
- rlc a
- mov _value+4,a
-_endasm;
- if (radix <= value.byte[4] )
- {
- value.byte[4] -= radix;
- value.byte[0]++;
- }
- }
-}
-#elif defined SDCC_STACK_AUTO
-static void calculate_digit( value_t* value, unsigned char radix )
+#if defined SDCC_STACK_AUTO
+static void calculate_digit( value_t _AUTOMEM * value, unsigned char radix )
{
- unsigned char i;
+ unsigned long ul = value->ul;
+ unsigned char _AUTOMEM * pb4 = &value->byte[4];
+ unsigned char i = 32;
- for( i = 32; i != 0; i-- )
+ do
{
- value->byte[4] = (value->byte[4] << 1) | ((value->ul >> 31) & 0x01);
- value->ul <<= 1;
+ *pb4 = (*pb4 << 1) | ((ul >> 31) & 0x01);
+ ul <<= 1;
- if (radix <= value->byte[4] )
+ if (radix <= *pb4 )
{
- value->byte[4] -= radix;
- value->ul |= 1;
+ *pb4 -= radix;
+ ul |= 1;
}
- }
+ } while (--i);
+ value->ul = ul;
}
#else
static void calculate_digit( unsigned char radix )
{
- unsigned char i;
+ register unsigned long ul = value.ul;
+ register unsigned char b4 = value.byte[4];
+ register unsigned char i = 32;
- for( i = 32; i != 0; i-- )
+ do
{
- value.byte[4] = (value.byte[4] << 1) | ((value.ul >> 31) & 0x01);
- value.ul <<= 1;
+ b4 = (b4 << 1);
+ b4 |= (ul >> 31) & 0x01;
+ ul <<= 1;
- if (radix <= value.byte[4] )
+ if (radix <= b4 )
{
- value.byte[4] -= radix;
- value.ul |= 1;
+ b4 -= radix;
+ ul |= 1;
}
- }
+ } while (--i);
+ value.ul = ul;
+ value.byte[4] = b4;
}
#endif
#ifdef SDCC_STACK_AUTO
#define OUTPUT_FLOAT(F, W, D, L, Z, S, P) output_float(F, W, D, L, Z, S, P, output_char, p)
-static int output_float (float f, unsigned char reqWidth,
- signed char reqDecimals,
- BOOL left, BOOL zero, BOOL sign, BOOL space,
- pfn_outputchar output_char, void* p)
+static unsigned char
+output_float (float f, unsigned char reqWidth,
+ signed char reqDecimals,
+ BOOL left, BOOL zero, BOOL sign, BOOL space,
+ pfn_outputchar output_char, void* p)
+{
+ unsigned char charsOutputted = 0;
+ #if defined (SDCC_mcs51)
+ char fpBuffer[16]; //mcs51 has only a small stack
+ #else
+ char fpBuffer[128];
+ #endif
#else
#define OUTPUT_FLOAT(F, W, D, L, Z, S, P) output_float(F, W, D, L, Z, S, P)
-static int output_float (float f, unsigned char reqWidth,
- signed char reqDecimals,
- BOOL left, BOOL zero, BOOL sign, BOOL space)
-#endif
+static void
+output_float (float f, unsigned char reqWidth,
+ signed char reqDecimals,
+ BOOL left, BOOL zero, BOOL sign, BOOL space)
{
- char negative=0;
+ __xdata char fpBuffer[128];
+#endif //SDCC_STACK_AUTO
+ BOOL negative = 0;
unsigned long integerPart;
+ float rounding;
float decimalPart;
- char fpBuffer[128];
char fpBI=0, fpBD;
unsigned char minWidth, i;
- int charsOutputted=0;
+ signed char exp = -128;
// save the sign
if (f<0) {
if (f>0x00ffffff) {
// this part is from Frank van der Hulst
- signed char exp;
for (exp = 0; f >= 10.0; exp++) f /=10.0;
for ( ; f < 1.0; exp--) f *=10.0;
if (negative) {
- output_char ('-', p);
- charsOutputted++;
+ OUTPUT_CHAR ('-', p);
} else {
if (sign) {
- output_char ('+', p);
- charsOutputted++;
+ OUTPUT_CHAR ('+', p);
}
}
- charsOutputted += OUTPUT_FLOAT(f, 0, reqDecimals, 0, 0, 0, 0);
- output_char ('e', p);
- charsOutputted++;
- if (exp<0) {
- output_char ('-', p);
- charsOutputted++;
- exp = -exp;
- }
- output_char ('0'+exp/10, p);
- output_char ('0'+exp%10, p);
- charsOutputted += 2;
- return charsOutputted;
+ reqWidth = 0;
+ left = 0;
+ zero = 0;
+ sign = 0;
+ space = 0;
}
+ // display some decimals as default
+ if (reqDecimals==-1)
+ reqDecimals=DEFAULT_FLOAT_PRECISION;
+
+ // round the float
+ rounding = 0.5;
+ for (i=reqDecimals; i>0; i--) {
+ rounding /= 10.0;
+ }
+ f += rounding;
+
// split the float
- integerPart=f;
- decimalPart=f-integerPart;
+ integerPart = f;
+ decimalPart = f - integerPart;
// fill the buffer with the integerPart (in reversed order!)
while (integerPart) {
fpBuffer[fpBI++]='0';
}
- // display some decimals as default
- if (reqDecimals==-1)
- reqDecimals=DEFAULT_FLOAT_PRECISION;
-
// fill buffer with the decimalPart (in normal order)
fpBD=fpBI;
- if (i=reqDecimals /* that's an assignment */) {
- do {
+
+ for (i=reqDecimals; i>0; i--) {
decimalPart *= 10.0;
// truncate the float
- integerPart=decimalPart;
- fpBuffer[fpBD++]='0' + integerPart;
- decimalPart-=integerPart;
- } while (--i);
+ integerPart = decimalPart;
+ fpBuffer[fpBD++] = '0' + integerPart;
+ decimalPart -= integerPart;
}
minWidth=fpBI; // we need at least these
if (zero) {
if (negative)
{
- output_char('-', p);
- charsOutputted++;
+ OUTPUT_CHAR('-', p);
}
else if (sign)
{
- output_char('+', p);
- charsOutputted++;
+ OUTPUT_CHAR('+', p);
}
else if (space)
{
- output_char(' ', p);
- charsOutputted++;
+ OUTPUT_CHAR(' ', p);
}
while (reqWidth-->minWidth)
{
- output_char('0', p);
- charsOutputted++;
+ OUTPUT_CHAR('0', p);
}
} else {
while (reqWidth-->minWidth)
{
- output_char(' ', p);
- charsOutputted++;
+ OUTPUT_CHAR(' ', p);
}
if (negative)
{
- output_char('-', p);
- charsOutputted++;
+ OUTPUT_CHAR('-', p);
}
else if (sign)
{
- output_char('+', p);
- charsOutputted++;
+ OUTPUT_CHAR('+', p);
}
else if (space)
{
- output_char(' ', p);
- charsOutputted++;
+ OUTPUT_CHAR(' ', p);
}
}
} else {
if (negative)
{
- output_char('-', p);
- charsOutputted++;
+ OUTPUT_CHAR('-', p);
}
else if (sign)
{
- output_char('+', p);
- charsOutputted++;
+ OUTPUT_CHAR('+', p);
}
else if (space)
{
- output_char(' ', p);
- charsOutputted++;
+ OUTPUT_CHAR(' ', p);
}
}
// output the integer part
i=fpBI-1;
do {
- output_char (fpBuffer[i], p);
- charsOutputted++;
+ OUTPUT_CHAR (fpBuffer[i], p);
} while (i--);
// ouput the decimal part
if (reqDecimals) {
- output_char ('.', p);
- charsOutputted++;
+ OUTPUT_CHAR ('.', p);
i=fpBI;
while (reqDecimals--)
{
- output_char (fpBuffer[i++], p);
- charsOutputted++;
+ OUTPUT_CHAR (fpBuffer[i++], p);
}
}
if (left && reqWidth>minWidth) {
while (reqWidth-->minWidth)
{
- output_char(' ', p);
- charsOutputted++;
+ OUTPUT_CHAR(' ', p);
+ }
+ }
+
+ if (exp != -128) {
+ OUTPUT_CHAR ('e', p);
+ if (exp<0) {
+ OUTPUT_CHAR ('-', p);
+ exp = -exp;
}
+ OUTPUT_CHAR ('0'+exp/10, p);
+ OUTPUT_CHAR ('0'+exp%10, p);
}
+#ifdef SDCC_STACK_AUTO
return charsOutputted;
+#else
+ return;
+#endif //SDCC_STACK_AUTO
}
-#endif
+#endif //USE_FLOATS
int _print_format (pfn_outputchar pfn, void* pvoid, const char *format, va_list ap)
{
#ifdef SDCC_STACK_AUTO
BOOL lower_case;
value_t value;
+ int charsOutputted;
#endif
-#ifndef ASM_ALLOWED
BOOL lsd;
-#endif
unsigned char radix;
- int charsOutputted;
unsigned char width;
signed char decimals;
unsigned char length;
#endif
// reset output chars
- charsOutputted=0;
+ charsOutputted = 0;
#ifdef SDCC_ds390
if (format==0) {
prefix_sign = 0;
prefix_space = 0;
signed_argument = 0;
- radix = 0;
char_argument = 0;
long_argument = 0;
float_argument = 0;
+ radix = 0;
width = 0;
decimals = -1;
c = *format++;
if (c=='%') {
- output_char(c, p);
- charsOutputted++;
+ OUTPUT_CHAR(c, p);
continue;
}
}
if (c=='.') {
- if (decimals=-1) decimals=0;
+ if (decimals==-1) decimals=0;
else
; // duplicate, ignore
goto get_conversion_spec;
}
- lower_case = islower(c);
- if (lower_case)
+ if (islower(c))
{
c = toupper(c);
+ lower_case = 1;
}
+ else
+ lower_case = 0;
switch( c )
{
goto get_conversion_spec;
case 'C':
- output_char( va_arg(ap,int), p );
- charsOutputted++;
+ if( char_argument )
+ c = va_arg(ap,char);
+ else
+ c = va_arg(ap,int);
+ OUTPUT_CHAR( c, p );
break;
case 'S':
#else
length = strlen(PTR);
#endif
+ if ( decimals == -1 )
+ {
+ decimals = length;
+ }
if ( ( !left_justify ) && (length < width) )
{
width -= length;
while( width-- != 0 )
{
- output_char( ' ', p );
- charsOutputted++;
+ OUTPUT_CHAR( ' ', p );
}
}
- while ( *PTR )
+ while ( (c = *PTR) && (decimals-- > 0))
{
- output_char( *PTR++, p );
- charsOutputted++;
+ OUTPUT_CHAR( c, p );
+ PTR++;
}
if ( left_justify && (length < width))
width -= length;
while( width-- != 0 )
{
- output_char( ' ', p );
- charsOutputted++;
+ OUTPUT_CHAR( ' ', p );
}
}
break;
case 'P':
PTR = va_arg(ap,ptr_t);
-#ifdef SDCC_ds390
- output_char(memory_id[(value.byte[3] > 3) ? 4 : value.byte[3]], p );
- output_char(':', p);
- output_char('0', p);
- output_char('x', p);
+#if defined (SDCC_ds390)
+ {
+ unsigned char memtype = value.byte[3];
+ if (memtype > 0x80)
+ c = 'C';
+ else if (memtype > 0x60)
+ c = 'P';
+ else if (memtype > 0x40)
+ c = 'I';
+ else
+ c = 'X';
+ }
+ OUTPUT_CHAR(c, p);
+ OUTPUT_CHAR(':', p);
+ OUTPUT_CHAR('0', p);
+ OUTPUT_CHAR('x', p);
OUTPUT_2DIGITS( value.byte[2] );
OUTPUT_2DIGITS( value.byte[1] );
OUTPUT_2DIGITS( value.byte[0] );
- charsOutputted += 10;
-#else
- output_char( memory_id[(value.byte[2] > 3) ? 4 : value.byte[2]], p );
- output_char(':', p);
- output_char('0', p);
- output_char('x', p);
- if ((value.byte[2] != 0x00 /* DSEG */) &&
- (value.byte[2] != 0x03 /* SSEG */))
+#elif defined (SDCC_mcs51)
+ {
+ unsigned char memtype = value.byte[2];
+ if (memtype > 0x80)
+ c = 'C';
+ else if (memtype > 0x60)
+ c = 'P';
+ else if (memtype > 0x40)
+ c = 'I';
+ else
+ c = 'X';
+ }
+ OUTPUT_CHAR(c, p);
+ OUTPUT_CHAR(':', p);
+ OUTPUT_CHAR('0', p);
+ OUTPUT_CHAR('x', p);
+ if ((c != 'I' /* idata */) &&
+ (c != 'P' /* pdata */))
{
OUTPUT_2DIGITS( value.byte[1] );
- charsOutputted += 2;
}
OUTPUT_2DIGITS( value.byte[0] );
- charsOutputted += 6;
+#else
+ OUTPUT_CHAR('0', p);
+ OUTPUT_CHAR('x', p);
+ OUTPUT_2DIGITS( value.byte[1] );
+ OUTPUT_2DIGITS( value.byte[0] );
#endif
break;
default:
// nothing special, just output the character
- output_char( c, p );
- charsOutputted++;
+ OUTPUT_CHAR( c, p );
break;
}
PTR="<NO FLOAT>";
while (c=*PTR++)
{
- output_char (c, p);
- charsOutputted++;
+ OUTPUT_CHAR (c, p);
}
// treat as long hex
//radix=16;
//width=8;
#else
// ignore b and l conversion spec for now
+#ifdef SDCC_STACK_AUTO
charsOutputted += OUTPUT_FLOAT(value.f, width, decimals, left_justify,
zero_padding, prefix_sign, prefix_space);
-#endif
+#else
+ OUTPUT_FLOAT(value.f, width, decimals, left_justify,
+ zero_padding, prefix_sign, prefix_space);
+#endif //SDCC_STACK_AUTO
+#endif //USE_FLOATS
} else if (radix != 0)
{
- // Apperently we have to output an integral type
+ // Apparently we have to output an integral type
// with radix "radix"
-#ifndef ASM_ALLOWED
- unsigned char store[6];
- unsigned char NEAR *pstore = &store[5];
-#endif
+ unsigned char MEM_SPACE_BUF store[6];
+ unsigned char MEM_SPACE_BUF_PP *pstore = &store[5];
// store value in byte[0] (LSB) ... byte[3] (MSB)
if (char_argument)
{
value.l = va_arg(ap,char);
+ if (!signed_argument)
+ {
+ value.l &= 0xFF;
+ }
}
else if (long_argument)
{
else // must be int
{
value.l = va_arg(ap,int);
+ if (!signed_argument)
+ {
+ value.l &= 0xFFFF;
+ }
}
if ( signed_argument )
#else
calculate_digit(radix);
#endif
-#if defined ASM_ALLOWED
-_asm
- jb _lsd,1$
- pop b ; b = <lsd>
- mov a,_value+4 ; a = <msd>
- swap a
- orl b,a ; b = <msd><lsd>
- push b
- sjmp 2$
-1$:
- mov a,_value+4 ; a = <lsd>
- push acc
-2$:
-_endasm;
-#else
if (!lsd)
{
*pstore = (value.byte[4] << 4) | (value.byte[4] >> 4) | *pstore;
{
*pstore = value.byte[4];
}
-#endif
length++;
lsd = !lsd;
- } while( (value.byte[0] != 0) || (value.byte[1] != 0) ||
- (value.byte[2] != 0) || (value.byte[3] != 0) );
+ } while( value.ul );
if (width == 0)
{
{
while ( width > (unsigned char) (length+1) )
{
- output_char( ' ', p );
- charsOutputted++;
+ OUTPUT_CHAR( ' ', p );
width--;
}
}
if (signed_argument) // this now means the original value was negative
{
- output_char( '-', p );
- charsOutputted++;
+ OUTPUT_CHAR( '-', p );
// adjust width to compensate for this character
width--;
}
// value > 0
if (prefix_sign)
{
- output_char( '+', p );
- charsOutputted++;
+ OUTPUT_CHAR( '+', p );
// adjust width to compensate for this character
width--;
}
else if (prefix_space)
{
- output_char( ' ', p );
- charsOutputted++;
+ OUTPUT_CHAR( ' ', p );
// adjust width to compensate for this character
width--;
}
if (!left_justify)
while ( width-- > length )
{
- output_char( zero_padding ? '0' : ' ', p );
- charsOutputted++;
+ OUTPUT_CHAR( zero_padding ? '0' : ' ', p );
}
else
{
while( length-- )
{
lsd = !lsd;
-#ifdef ASM_ALLOWED
-_asm
- jb _lsd,3$
- pop acc ; a = <msd><lsd>
- nop ; to disable the "optimizer"
- push acc
- swap a
- anl a,#0x0F ; a = <msd>
- sjmp 4$
-3$:
- pop acc
- anl a,#0x0F ; a = <lsd>
-4$:
- mov _value+4,a
-_endasm;
-#else
if (!lsd)
{
pstore++;
{
value.byte[4] = *pstore & 0x0F;
}
-#endif
#ifdef SDCC_STACK_AUTO
output_digit( value.byte[4], lower_case, output_char, p );
+ charsOutputted++;
#else
output_digit( value.byte[4] );
#endif
- charsOutputted++;
}
if (left_justify)
while (width-- > 0)
{
- output_char(' ', p);
- charsOutputted++;
+ OUTPUT_CHAR(' ', p);
}
}
}
else
{
// nothing special, just output the character
- output_char( c, p );
- charsOutputted++;
+ OUTPUT_CHAR( c, p );
}
}