Imported Upstream version 2.9.0
[debian/cc1111] / 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 library is free software; you can redistribute it and/or modify it
7     under the terms of the GNU Library 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 library 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 Library General Public License for more details.
15
16     You should have received a copy of the GNU Library 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             char
33      %x        hexadecimal         int
34      %lx       hexadecimal         long
35      %hx       hexadecimal         char
36      %o        octal               int
37      %lo       octal               long
38      %ho       octal               char
39      %c        character           char
40      %s        character           generic pointer
41 */
42
43 #include <stdarg.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #ifndef __ds390
47 /* just for the SP */
48 #include <8051.h>
49 #endif
50
51 static __data char radix ;
52 static __bit  long_flag = 0;
53 static __bit  string_flag =0;
54 static __bit  char_flag = 0;
55 static char * __data str ;
56 static __data long val;
57
58 /* This great loop fails with the ds390 port (2003-01-13).
59
60    At the beginning resp. end of the loop the compiler inserts a "push ar2"
61    resp. "pop ar2", which badly interfers with the push/pop in the source.
62
63    Library functions should be rock solid and portable. There's an _ltoa in
64    the library, so let's use it and don't reinvent the wheel.
65
66    Bernhard
67 */
68
69 #if NICE_LIFO_IMPLEMENTATION_BUT_NOT_PORTABLE
70 static __data volatile char ch;
71 static __bit sign;
72
73 static void pval(void)
74 {
75         volatile char sp;
76         unsigned long lval;
77         sp = SP;
78
79         if (val < 0 && radix != 16)
80         {
81            lval = -val;
82            sign = 1;
83         }
84         else { sign = 0; lval = val;}
85
86         if (!long_flag) {
87           lval &= 0x0000ffff;
88         }
89         if (char_flag) {
90           lval &= 0x000000ff;
91         }
92
93         do
94         {
95
96 #  if 1
97                 if(radix != 16)  ch = (lval % radix) + '0';
98                 else ch = "0123456789ABCDEF"[(unsigned char)lval & 0x0f];
99                 __asm push _ch __endasm;
100                 lval /= radix;
101 #  else
102                 // This only looks more efficient, but isn't. see the .map
103                 ch = (lval % radix) + '0';
104                 if (ch>'9') ch+=7;
105                 __asm push _ch __endasm;
106                 lval /= radix;
107 #  endif
108         }
109         while (lval);
110
111         if (sign) {
112                 ch = '-';
113                 __asm push _ch __endasm;
114         }
115
116         while (sp != SP) {
117                 __asm pop _ch __endasm;
118                 putchar(ch);
119         }
120 }
121 #endif
122
123 void printf_small (char * fmt, ... ) __reentrant
124 {
125     va_list ap ;
126
127     va_start(ap,fmt);
128
129     for (; *fmt ; fmt++ ) {
130         if (*fmt == '%') {
131             long_flag = string_flag = char_flag = 0;
132             fmt++ ;
133             switch (*fmt) {
134             case 'l':
135                 long_flag = 1;
136                 fmt++;
137                 break;
138             case 'h':
139                 char_flag = 1;
140                 fmt++;
141             }
142
143             switch (*fmt) {
144             case 's':
145                 string_flag = 1;
146                 break;
147             case 'd':
148                 radix = 10;
149                 break;
150             case 'x':
151                 radix = 16;
152                 break;
153             case 'c':
154                 radix = 0;
155                 break;
156             case 'o':
157                 radix = 8;
158                 break;
159             }
160
161             if (string_flag) {
162                 str = va_arg(ap, char *);
163                 while (*str) putchar(*str++);
164                 continue ;
165             }
166
167             if (long_flag)
168                 val = va_arg(ap,long);
169             else
170                 if (char_flag)
171                     val = va_arg(ap,char);
172                 else
173                     val = va_arg(ap,int);
174
175 #if NICE_LIFO_IMPLEMENTATION_BUT_NOT_PORTABLE
176             if (radix) pval();
177 #else
178             if (radix)
179             {
180               static char __idata buffer[12]; /* 37777777777(oct) */
181               char __idata * stri;
182
183               _ltoa (val, buffer, radix);
184               stri = buffer;
185               while (*stri)
186                 {
187                   putchar (*stri);
188                   stri++;
189                 }
190             }
191 #endif
192             else
193               putchar((char)val);
194
195         } else
196             putchar(*fmt);
197     }
198 }