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