Was's (was@icb.snz.chel.su) efficiency patch.
[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 <reg51.h>
45 #include <stdio.h>
46
47 static data volatile char ch;
48 static data char radix ;
49 static bit  long_flag = 0;
50 static bit  string_flag =0;
51 static bit  short_flag = 0;
52 static bit sign;
53 static char * data str ;
54 static data long val;
55
56 static void pval(void)
57 {
58         char sp;
59         unsigned long lval;
60         sp = SP;
61
62         if (val < 0 && radix != 16)
63         {
64            lval = -val;
65            sign = 1;
66         }
67         else { sign = 0; lval = val;}
68
69         if (!long_flag) {
70           lval &= 0x0000ffff;
71         }
72         if (short_flag) {
73           lval &= 0x000000ff;
74         }
75
76         do
77         {
78 #if 1
79                 if(radix != 16)  ch = (lval % radix) + '0';
80                 else ch = "0123456789ABCDEF"[(unsigned short)lval & 0x0f];
81                 _asm push _ch _endasm;
82                 lval /= radix;
83 #else
84                 // This only looks more efficient, but isn't. see the .map
85                 ch = (lval % radix) + '0'; 
86                 if (ch>'9') ch+=7; 
87                 _asm push _ch _endasm; 
88                 lval /= radix;
89 #endif
90         }
91         while (lval);
92
93         if (sign) {
94                 ch = '-';
95                 _asm push _ch _endasm;
96         }
97
98         while (sp != SP) {
99                 _asm pop _ch _endasm;
100                 putchar(ch);
101         }
102 }
103
104 void printf_small (char * fmt, ... ) reentrant
105 {
106     va_list ap ;
107
108     va_start(ap,fmt);
109
110     for (; *fmt ; fmt++ ) {
111         if (*fmt == '%') {
112             long_flag = string_flag = short_flag = 0;
113             fmt++ ;
114             switch (*fmt) {
115             case 'l':
116                 long_flag = 1;
117                 fmt++;
118                 break;
119             case 'h':
120                 short_flag = 1;
121                 fmt++;
122             }
123
124             switch (*fmt) {
125             case 's':
126                 string_flag = 1;
127                 break;
128             case 'd':
129                 radix = 10;
130                 break;
131             case 'x':
132                 radix = 16;
133                 break;
134             case 'c':
135                 radix = 0;
136                 break;
137             case 'o':
138                 radix = 8;
139                 break;
140             }
141
142             if (string_flag) {
143                 str = va_arg(ap, char _generic *);
144                 while (*str) putchar(*str++);
145                 continue ;
146             }
147
148             if (long_flag)
149                 val = va_arg(ap,long);
150             else
151                 if (short_flag)
152                     val = va_arg(ap,short);
153                 else
154                     val = va_arg(ap,int);
155
156             if (radix) pval();
157             else putchar((char)val);
158
159         } else
160             putchar(*fmt);
161     }
162 }