#include <reg51.h> is replaced by #include <8051.h>
[fw/sdcc] / device / lib / printfl.c
1 /*-----------------------------------------------------------------
2     printfl.c - source file for reduced version of printf
3
4     Written By - Sandeep Dutta . sandeep.dutta@usa.net (1999)
5
6     This program is free software; you can redistribute it and/or modify it
7     under the terms of the GNU General Public License as published by the
8     Free Software Foundation; either version 2, or (at your option) any
9     later version.
10
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
20     In other words, you are welcome to use, share and improve this program.
21     You are forbidden to forbid anyone else to use, share and improve
22     what you give them.   Help stamp out software-hoarding!
23     
24     2001060401: Improved by was@icb.snz.chel.su
25 -------------------------------------------------------------------------*/
26
27
28 /* following formats are supported :-
29    format     output type       argument-type
30      %d        decimal             int
31      %ld       decimal             long
32      %hd       decimal             short/char
33      %x        hexadecimal         int
34      %lx       hexadecimal         long
35      %hx       hexadecimal         short/char
36      %o        octal               int
37      %lo       octal               long
38      %ho       octal               short/char
39      %c        character           char/short
40      %s        character           _generic pointer
41 */
42
43 #include <stdarg.h>
44 #include <stdio.h>
45 #ifndef __ds390
46 #include <8051.h> // for the SP
47 #endif
48
49 static data volatile char ch;
50 static data char radix ;
51 static bit  long_flag = 0;
52 static bit  string_flag =0;
53 static bit  short_flag = 0;
54 static bit sign;
55 static char * data str ;
56 static data long val;
57
58 static void pval(void)
59 {
60         char sp;
61         unsigned long lval;
62         sp = SP;
63
64         if (val < 0 && radix != 16)
65         {
66            lval = -val;
67            sign = 1;
68         }
69         else { sign = 0; lval = val;}
70
71         if (!long_flag) {
72           lval &= 0x0000ffff;
73         }
74         if (short_flag) {
75           lval &= 0x000000ff;
76         }
77
78         do
79         {
80 #if 1
81                 if(radix != 16)  ch = (lval % radix) + '0';
82                 else ch = "0123456789ABCDEF"[(unsigned short)lval & 0x0f];
83                 _asm push _ch _endasm;
84                 lval /= radix;
85 #else
86                 // This only looks more efficient, but isn't. see the .map
87                 ch = (lval % radix) + '0'; 
88                 if (ch>'9') ch+=7; 
89                 _asm push _ch _endasm; 
90                 lval /= radix;
91 #endif
92         }
93         while (lval);
94
95         if (sign) {
96                 ch = '-';
97                 _asm push _ch _endasm;
98         }
99
100         while (sp != SP) {
101                 _asm pop _ch _endasm;
102                 putchar(ch);
103         }
104 }
105
106 void printf_small (char * fmt, ... ) reentrant
107 {
108     va_list ap ;
109
110     va_start(ap,fmt);
111
112     for (; *fmt ; fmt++ ) {
113         if (*fmt == '%') {
114             long_flag = string_flag = short_flag = 0;
115             fmt++ ;
116             switch (*fmt) {
117             case 'l':
118                 long_flag = 1;
119                 fmt++;
120                 break;
121             case 'h':
122                 short_flag = 1;
123                 fmt++;
124             }
125
126             switch (*fmt) {
127             case 's':
128                 string_flag = 1;
129                 break;
130             case 'd':
131                 radix = 10;
132                 break;
133             case 'x':
134                 radix = 16;
135                 break;
136             case 'c':
137                 radix = 0;
138                 break;
139             case 'o':
140                 radix = 8;
141                 break;
142             }
143
144             if (string_flag) {
145                 str = va_arg(ap, char _generic *);
146                 while (*str) putchar(*str++);
147                 continue ;
148             }
149
150             if (long_flag)
151                 val = va_arg(ap,long);
152             else
153                 if (short_flag)
154                     val = va_arg(ap,short);
155                 else
156                     val = va_arg(ap,int);
157
158             if (radix) pval();
159             else putchar((char)val);
160
161         } else
162             putchar(*fmt);
163     }
164 }