fixed and cleaned up fp support, optimisation yet to come
[fw/sdcc] / device / lib / vprintf.c
index 57a775adc7e5b6711e1afd120f8422ad79bbcb71..555f4f24f327fa79def530396e38da7ab68aabfe 100644 (file)
    You are forbidden to forbid anyone else to use, share and improve
    what you give them.   Help stamp out software-hoarding!  
 -------------------------------------------------------------------------*/
+
+/* this module uses some global variables instead function parameters, so: */
+#ifdef SDCC_STACK_AUTO
+#warning "this module cannot yet be use as a reentrant one"
+#endif
+
+#ifdef __ds390
 #define USE_FLOATS 1
+#endif
 
 #include <stdarg.h>
 #include <string.h>
 
 #define PTR value.p 
 
+#ifdef SDCC_ds390
+#define NULL_STRING "<NULL>"
+#define NULL_STRING_LENGTH 6
+#endif
+
 /****************************************************************************/
 
-typedef char _generic *ptr_t;
+//typedef char * ptr_t;
+#define ptr_t char *
 
 #ifdef toupper
 #undef toupper
@@ -48,7 +62,7 @@ typedef union
   long           l;
   unsigned long  ul;
   float          f;
-  char _generic *p;
+  char           *p;
 } value_t;
 
 
@@ -62,7 +76,10 @@ static bit   lsd;
 /* this one NEEDS to be in data */
 static data value_t value;
 
-static xdata unsigned short radix;
+static unsigned char radix;
+
+// jwk: TODO: this makes the whole dammed thing nonreentrent
+static int charsOutputted;
 
 /****************************************************************************/
 
@@ -76,13 +93,15 @@ static void output_char( char c ) reentrant
   {
     putchar( c );
   }
+  charsOutputted++;
 }
 
 /*--------------------------------------------------------------------------*/
 
 static void output_digit( unsigned char n ) reentrant
 {
-  output_char( n <= 9 ? '0'+n : (lower_case ? n+(char)('a'-10) : n+(char)('A'-10)) );
+  output_char( n <= 9 ? '0'+n : 
+              (lower_case ? n+(char)('a'-10) : n+(char)('A'-10)) );
 }
 
 /*--------------------------------------------------------------------------*/
@@ -103,7 +122,7 @@ static void calculate_digit( void )
   {
 _asm
   clr  c
-  mov  a,_value+0
+  mov  a,_value+0  
   rlc  a
   mov  _value+0,a
   mov  a,_value+1
@@ -237,20 +256,23 @@ static void output_float (float f, unsigned char reqWidth,
 
 int vsprintf (const char *buf, const char *format, va_list ap)
 {
-  bit            left_justify;
-  bit            zero_padding;
-  bit            prefix_sign;
-  bit            prefix_space;
-  bit            signed_argument;
-  bit            char_argument;
-  bit            long_argument;
-  bit            float_argument;
+  static bit            left_justify;
+  static bit            zero_padding;
+  static bit            prefix_sign;
+  static bit            prefix_space;
+  static bit            signed_argument;
+  static bit            char_argument;
+  static bit            long_argument;
+  static bit            float_argument;
 
   unsigned char  width;
   signed char decimals;
   unsigned char  length;
   char           c;
 
+  // reset output chars
+  charsOutputted=0;
+
   output_ptr = buf;
   if ( !buf )
   {
@@ -261,6 +283,12 @@ int vsprintf (const char *buf, const char *format, va_list ap)
     output_to_string = 1;
   }
 
+#ifdef SDCC_ds390
+  if (format==0) {
+    format=NULL_STRING;
+  }
+#endif
   while( c=*format++ )
   {
     if ( c=='%' )
@@ -331,13 +359,22 @@ get_conversion_spec:
        goto get_conversion_spec;
 
       case 'C':
-               output_char( va_arg(ap,unsigned char) );
+               output_char( va_arg(ap,int) );
        break;
 
       case 'S':
        PTR = va_arg(ap,ptr_t);
 
+#ifdef SDCC_ds390
+       if (PTR==0) {
+         PTR=NULL_STRING;
+         length=NULL_STRING_LENGTH;
+       } else {
+         length = strlen(PTR);
+       }
+#else
        length = strlen(PTR);
+#endif
        if ( ( !left_justify ) && (length < width) )
        {
          width -= length;
@@ -363,7 +400,7 @@ get_conversion_spec:
       case 'P':
        PTR = va_arg(ap,ptr_t);
 
-#ifdef SDCC_MODEL_FLAT24
+#ifdef SDCC_ds390
        output_char(memory_id[(value.byte[3] > 3) ? 4 : value.byte[3]] );
        output_char(':');
        output_char('0');
@@ -376,7 +413,8 @@ get_conversion_spec:
        output_char(':');
        output_char('0');
        output_char('x');
-       if ((value.byte[2] != 0x00 /* DSEG */) && (value.byte[2] != 0x03 /* SSEG */))
+       if ((value.byte[2] != 0x00 /* DSEG */) && 
+           (value.byte[2] != 0x03 /* SSEG */))
          output_2digits( value.byte[1] );
        output_2digits( value.byte[0] );
 #endif
@@ -413,11 +451,14 @@ get_conversion_spec:
       if (float_argument) {
        value.f=va_arg(ap,float);
 #if !USE_FLOATS
+       PTR="<NO FLOAT>";
+       while (c=*PTR++)
+         output_char (c);
        // treat as long hex
-       radix=16;
-       long_argument=1;
-       zero_padding=1;
-       width=8;
+       //radix=16;
+       //long_argument=1;
+       //zero_padding=1;
+       //width=8;
 #else
        // ignore b and l conversion spec for now
        output_float(value.f, width, decimals, left_justify, zero_padding, 
@@ -568,7 +609,12 @@ _endasm;
        
   // Copy \0 to the end of buf
   // Modified by JB 17/12/99
-  if (output_to_string) output_char(0);
+  if (output_to_string) {
+    output_char(0);
+    return charsOutputted-1;
+  } else {
+    return charsOutputted;
+  }
 }
 
 /*--------------------------------------------------------------------------*/