Initial revision
[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
25 /* following formats are supported :-
26    format     output type       argument-type
27      %d        decimal             int
28      %ld       decimal             long 
29      %hd       decimal             short/char
30      %x        hexadecimal         int
31      %lx       hexadecimal         long 
32      %hx       hexadecimal         short/char
33      %o        octal               int
34      %lo       octal               long 
35      %ho       octal               short/char
36      %c        character           char/short
37      %s        character           _generic pointer
38 */
39
40 #include <stdarg.h>
41 #include <reg51.h>
42 extern void putchar(char );
43
44 static data volatile char ch;
45 static data char radix ;
46 static bit  long_flag = 0;
47 static bit  string_flag =0;
48 static bit  short_flag = 0;
49 static bit sign;
50 static char * data str ;
51 static data long val;
52
53 static void pvalhex( long val)
54 {
55         volatile char sp = SP;
56         unsigned long lval = val;
57
58         if (!long_flag)
59                 lval &= 0x0000ffff;
60
61         if (short_flag)
62                 lval &= 0x000000ff;
63
64         while (lval) {
65                 ch = "0123456789ABCDEF"[(unsigned short)lval & 0x0f];
66                 _asm push _ch _endasm;
67                 lval /= 16;
68         }
69
70         while (sp != SP) {
71                 _asm pop _ch _endasm;
72                 putchar(ch);
73         }
74                 
75 }
76
77 static void pvaloct(long val) 
78 {
79         char sp ; 
80         unsigned long lval;    
81         sp = SP;
82         if (val < 0) {
83                 lval = -val;
84                 sign = 1;
85         } else {
86                 lval = val;
87                 sign = 0;
88         }
89                 
90         if (!long_flag)
91                 lval &= 0x0000ffff;
92         if (short_flag)
93                 lval &= 0x000000ff;
94
95         while (lval) {
96                 ch = (lval % 8) + '0';
97                 _asm push _ch _endasm;  
98                 lval = lval / 8;
99         }
100
101         if (sign) {
102                 ch = '-';
103                 _asm push _ch _endasm;
104         }
105                 
106         
107         while (sp != SP) {
108                 _asm pop _ch _endasm;
109                 putchar(ch);
110         }
111 }
112
113 static void pvaldec(long val )  
114 {
115         char sp ; 
116         unsigned long lval;    
117         sp = SP;
118         if (val < 0) {
119                 lval = -val;
120                 sign = 1;
121         } else {
122                 lval = val;
123                 sign = 0;
124         }
125                 
126         while (lval) {
127                 ch = (lval % 10) + '0';
128                 _asm push _ch _endasm;  
129                 lval = lval / 10;
130         }
131
132         if (sign) {
133                 ch = '-';
134                 _asm push _ch _endasm;
135         }
136                 
137         
138         while (sp != SP) {
139                 _asm pop _ch _endasm;
140                 putchar(ch);
141         }
142 }
143
144 void printf_small (char * fmt, ... ) reentrant
145 {
146     va_list ap ;
147  
148     va_start(ap,fmt);
149      
150     for (; *fmt ; fmt++ ) {
151         if (*fmt == '%') {
152             long_flag = string_flag = short_flag = 0;
153             fmt++ ;
154             switch (*fmt) {
155             case 'l':
156                 long_flag = 1;
157                 fmt++;
158                 break;
159             case 'h':
160                 short_flag = 1;
161                 fmt++;
162             }
163             
164             switch (*fmt) {
165             case 's':
166                 string_flag = 1;
167                 break;
168             case 'd':
169                 radix = 10;
170                 break;
171             case 'x':
172                 radix = 16;
173                 break;
174             case 'c':
175                 radix = 0;
176                 break;
177             case 'o':
178                 radix = 8;
179                 break;
180             }
181
182             if (string_flag) {
183                 str = va_arg(ap,char _generic *);
184                 while (*str) putchar(*str++);          
185                 continue ;
186             }
187             
188             if (long_flag)
189                 val = va_arg(ap,long);
190             else
191                 if (short_flag)
192                     val = va_arg(ap,short);
193                 else
194                     val = va_arg(ap,int);
195             
196             switch (radix) {
197             case 10:
198                 pvaldec(val) ; 
199                 break;
200             case 16:
201                 pvalhex (val); 
202                 break;
203             case 0:
204                 putchar((char)val);
205                 break;
206             case 8:
207                 pvaloct(val) ; 
208                 break;
209             }
210             
211         } else
212             putchar(*fmt);       
213     }    
214 }