fixed the printf ("%d\n",0) bug
[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   do {
65     ch = "0123456789ABCDEF"[(unsigned short)lval & 0x0f];
66     _asm push _ch _endasm;
67     lval /= 16;
68   } while (lval);
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   do {
96     ch = (lval % 8) + '0';
97     _asm push _ch _endasm;
98      lval = lval / 8;
99   } while (lval);
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   do {
127     ch = (lval % 10) + '0';
128     _asm push _ch _endasm;
129     lval = lval / 10;
130   } while (lval);
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 }