* device/include/pic16/pic18f*.h: add bit aliases in INTCONbits_t
[fw/sdcc] / device / lib / printfl.c
index 7cf18ea0dfc2f2a09a48f855623b4a1065829193..a5d2211176f6cd9a12256f22fd874ab66e8fa7a4 100644 (file)
 /*-----------------------------------------------------------------
-    printfl.c - source file for reduced version of printf 
-                
+    printfl.c - source file for reduced version of printf
+
     Written By - Sandeep Dutta . sandeep.dutta@usa.net (1999)
 
-    This program is free software; you can redistribute it and/or modify it
-    under the terms of the GNU General Public License as published by the
+    This library is free software; you can redistribute it and/or modify it
+    under the terms of the GNU Library General Public License as published by the
     Free Software Foundation; either version 2, or (at your option) any
     later version.
-    
-    This program is distributed in the hope that it will be useful,
+
+    This library is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-    
-    You should have received a copy of the GNU General Public License
+    GNU Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
     along with this program; if not, write to the Free Software
     Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-    
+
     In other words, you are welcome to use, share and improve this program.
     You are forbidden to forbid anyone else to use, share and improve
-    what you give them.   Help stamp out software-hoarding!  
+    what you give them.   Help stamp out software-hoarding!
+
+    2001060401: Improved by was@icb.snz.chel.su
 -------------------------------------------------------------------------*/
 
+
 /* following formats are supported :-
    format     output type       argument-type
      %d        decimal             int
-     %ld       decimal             long 
-     %hd       decimal             short/char
+     %ld       decimal             long
+     %hd       decimal             char
      %x        hexadecimal         int
-     %lx       hexadecimal         long 
-     %hx       hexadecimal         short/char
+     %lx       hexadecimal         long
+     %hx       hexadecimal         char
      %o        octal               int
-     %lo       octal               long 
-     %ho       octal               short/char
-     %c        character           char/short
-     %s        character           _generic pointer
+     %lo       octal               long
+     %ho       octal               char
+     %c        character           char
+     %s        character           generic pointer
 */
 
 #include <stdarg.h>
-#include <reg51.h>
-extern void putchar(char );
-
-static data volatile char ch;
-static data char radix ;
-static bit  long_flag = 0;
-static bit  string_flag =0;
-static bit  short_flag = 0;
-static bit sign;
-static char * data str ;
-static data long val;
-
-static void pvalhex( long val)
-{
-       volatile char sp = SP;
-       unsigned long lval = val;
+#include <stdio.h>
+#include <stdlib.h>
+#ifndef __ds390
+/* just for the SP */
+#include <8051.h>
+#endif
 
-       if (!long_flag)
-               lval &= 0x0000ffff;
+static __data char radix ;
+static __bit  long_flag = 0;
+static __bit  string_flag =0;
+static __bit  char_flag = 0;
+static char * __data str ;
+static __data long val;
 
-        if (short_flag)
-               lval &= 0x000000ff;
+/* This great loop fails with the ds390 port (2003-01-13).
 
-       while (lval) {
-               ch = "0123456789ABCDEF"[(unsigned short)lval & 0x0f];
-               _asm push _ch _endasm;
-               lval /= 16;
-       }
+   At the beginning resp. end of the loop the compiler inserts a "push ar2"
+   resp. "pop ar2", which badly interfers with the push/pop in the source.
 
-       while (sp != SP) {
-               _asm pop _ch _endasm;
-               putchar(ch);
-        }
-               
-}
+   Library functions should be rock solid and portable. There's an _ltoa in
+   the library, so let's use it and don't reinvent the wheel.
+
+   Bernhard
+*/
 
-static void pvaloct(long val) 
+#if NICE_LIFO_IMPLEMENTATION_BUT_NOT_PORTABLE
+static __data volatile char ch;
+static __bit sign;
+
+static void pval(void)
 {
-       char sp ; 
-       unsigned long lval;    
-       sp = SP;
-       if (val < 0) {
-               lval = -val;
-               sign = 1;
-       } else {
-               lval = val;
-               sign = 0;
+        volatile char sp;
+        unsigned long lval;
+        sp = SP;
+
+        if (val < 0 && radix != 16)
+        {
+           lval = -val;
+           sign = 1;
+        }
+        else { sign = 0; lval = val;}
+
+       if (!long_flag) {
+         lval &= 0x0000ffff;
        }
-               
-       if (!long_flag)
-               lval &= 0x0000ffff;
-        if (short_flag)
-               lval &= 0x000000ff;
-
-        while (lval) {
-               ch = (lval % 8) + '0';
-               _asm push _ch _endasm;  
-                lval = lval / 8;
+        if (char_flag) {
+         lval &= 0x000000ff;
        }
 
-       if (sign) {
-               ch = '-';
-               _asm push _ch _endasm;
-       }
-               
-       
-       while (sp != SP) {
-               _asm pop _ch _endasm;
-               putchar(ch);
+        do
+        {
+
+#  if 1
+                if(radix != 16)  ch = (lval % radix) + '0';
+                else ch = "0123456789ABCDEF"[(unsigned char)lval & 0x0f];
+                __asm push _ch __endasm;
+                lval /= radix;
+#  else
+               // This only looks more efficient, but isn't. see the .map
+                ch = (lval % radix) + '0';
+                if (ch>'9') ch+=7;
+                __asm push _ch __endasm;
+                lval /= radix;
+#  endif
         }
-}
+        while (lval);
 
-static void pvaldec(long val )  
-{
-       char sp ; 
-       unsigned long lval;    
-       sp = SP;
-       if (val < 0) {
-               lval = -val;
-               sign = 1;
-       } else {
-               lval = val;
-               sign = 0;
-       }
-               
-        while (lval) {
-               ch = (lval % 10) + '0';
-               _asm push _ch _endasm;  
-                lval = lval / 10;
-       }
+        if (sign) {
+                ch = '-';
+                __asm push _ch __endasm;
+        }
 
-       if (sign) {
-               ch = '-';
-               _asm push _ch _endasm;
-       }
-               
-       
-       while (sp != SP) {
-               _asm pop _ch _endasm;
-               putchar(ch);
+        while (sp != SP) {
+                __asm pop _ch __endasm;
+                putchar(ch);
         }
 }
+#endif
 
-void printf_small (char * fmt, ... ) reentrant
+void printf_small (char * fmt, ... ) __reentrant
 {
     va_list ap ;
+
     va_start(ap,fmt);
-     
+
     for (; *fmt ; fmt++ ) {
-       if (*fmt == '%') {
-           long_flag = string_flag = short_flag = 0;
-           fmt++ ;
-           switch (*fmt) {
-           case 'l':
-               long_flag = 1;
-               fmt++;
-               break;
-           case 'h':
-               short_flag = 1;
-               fmt++;
-           }
-           
-           switch (*fmt) {
-           case 's':
-               string_flag = 1;
-               break;
-           case 'd':
-               radix = 10;
-               break;
-           case 'x':
-               radix = 16;
-               break;
-           case 'c':
-               radix = 0;
-               break;
-           case 'o':
-               radix = 8;
-               break;
-           }
-
-           if (string_flag) {
-               str = va_arg(ap,char _generic *);
-               while (*str) putchar(*str++);          
-               continue ;
-           }
-           
-           if (long_flag)
-               val = va_arg(ap,long);
-           else
-               if (short_flag)
-                   val = va_arg(ap,short);
-               else
-                   val = va_arg(ap,int);
-           
-            switch (radix) {
-           case 10:
-               pvaldec(val) ; 
-               break;
-           case 16:
-               pvalhex (val); 
-               break;
-           case 0:
-               putchar((char)val);
-               break;
-           case 8:
-               pvaloct(val) ; 
-               break;
-           }
-           
-       } else
-           putchar(*fmt);       
-    }    
+        if (*fmt == '%') {
+            long_flag = string_flag = char_flag = 0;
+            fmt++ ;
+            switch (*fmt) {
+            case 'l':
+                long_flag = 1;
+                fmt++;
+                break;
+            case 'h':
+                char_flag = 1;
+                fmt++;
+            }
+
+            switch (*fmt) {
+            case 's':
+                string_flag = 1;
+                break;
+            case 'd':
+                radix = 10;
+                break;
+            case 'x':
+                radix = 16;
+                break;
+            case 'c':
+                radix = 0;
+                break;
+            case 'o':
+                radix = 8;
+                break;
+            }
+
+            if (string_flag) {
+                str = va_arg(ap, char *);
+                while (*str) putchar(*str++);
+                continue ;
+            }
+
+            if (long_flag)
+                val = va_arg(ap,long);
+            else
+                if (char_flag)
+                    val = va_arg(ap,char);
+                else
+                    val = va_arg(ap,int);
+
+#if NICE_LIFO_IMPLEMENTATION_BUT_NOT_PORTABLE
+            if (radix) pval();
+#else
+            if (radix)
+            {
+              static char __idata buffer[12]; /* 37777777777(oct) */
+              char __idata * stri;
+
+              _ltoa (val, buffer, radix);
+              stri = buffer;
+              while (*stri)
+                {
+                  putchar (*stri);
+                  stri++;
+                }
+            }
+#endif
+            else
+              putchar((char)val);
+
+        } else
+            putchar(*fmt);
+    }
 }