struct / union in initializer, RFE #901.
[sdcc.git] / sdcc / device / lib / pic14 / libc / printfl.c
blob9138f5eff22ca219e5dfa5fbb79e79962089fb53
1 /*-----------------------------------------------------------------
2 printfl.c - source file for reduced version of printf
4 Copyright (C) 1999, Sandeep Dutta . sandeep.dutta@usa.net
5 2001060401: Improved by was@icb.snz.chel.su
7 Modifications for PIC14 by
8 Copyright (C) 2019 Gonzalo Pérez de Olaguer Córdoba <salo@gpoc.es>
10 This library is free software; you can redistribute it and/or modify it
11 under the terms of the GNU General Public License as published by the
12 Free Software Foundation; either version 2, or (at your option) any
13 later version.
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this library; see the file COPYING. If not, write to the
22 Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
23 MA 02110-1301, USA.
25 As a special exception, if you link this library with other files,
26 some of which are compiled with SDCC, to produce an executable,
27 this library does not by itself cause the resulting executable to
28 be covered by the GNU General Public License. This exception does
29 not however invalidate any other reasons why the executable file
30 might be covered by the GNU General Public License.
31 -------------------------------------------------------------------------*/
33 /* following formats are supported :-
34 format output type argument-type
35 %d decimal int
36 %ld decimal long
37 %hd decimal char
38 %x hexadecimal int
39 %lx hexadecimal long
40 %hx hexadecimal char
41 %o octal int
42 %lo octal long
43 %ho octal char
44 %c character char
45 %s character generic pointer
48 #include <stdarg.h>
49 #include <stdio.h>
50 #include <stdlib.h>
52 #if !(defined(__SDCC_pic14) && !defined(__SDCC_PIC14_HAS_VARARGS))
54 #if defined(__SDCC_pic14)
55 #include <stdbool.h>
56 #define __reentrant
57 #define __idata __data
58 #define __bit bool
59 #endif
61 static __data char radix ;
62 static __bit long_flag = 0;
63 static __bit string_flag =0;
64 static __bit char_flag = 0;
65 static char * __data str ;
66 static __data long val;
68 /* This great loop fails with the ds390 port (2003-01-13).
70 At the beginning resp. end of the loop the compiler inserts a "push ar2"
71 resp. "pop ar2", which badly interferes with the push/pop in the source.
73 Library functions should be rock solid and portable. There's an _ltoa in
74 the library, so let's use it and don't reinvent the wheel.
76 Bernhard
79 #if NICE_LIFO_IMPLEMENTATION_BUT_NOT_PORTABLE
80 /* just for the SP */
81 #include <8051.h>
83 static __data volatile char ch;
84 static __bit sign;
86 static void pval(void)
88 volatile char sp;
89 unsigned long lval;
90 sp = SP;
92 if (val < 0 && radix != 16)
94 lval = -val;
95 sign = 1;
97 else { sign = 0; lval = val;}
99 if (!long_flag) {
100 lval &= 0x0000ffff;
102 if (char_flag) {
103 lval &= 0x000000ff;
109 # if 1
110 if(radix != 16) ch = (lval % radix) + '0';
111 else ch = "0123456789ABCDEF"[(unsigned char)lval & 0x0f];
112 __asm push _ch __endasm;
113 lval /= radix;
114 # else
115 // This only looks more efficient, but isn't. see the .map
116 ch = (lval % radix) + '0';
117 if (ch>'9') ch+=7;
118 __asm push _ch __endasm;
119 lval /= radix;
120 # endif
122 while (lval);
124 if (sign) {
125 ch = '-';
126 __asm push _ch __endasm;
129 while (sp != SP) {
130 __asm pop _ch __endasm;
131 putchar(ch);
134 #endif
136 #if defined(__SDCC_pic14)
137 void printf_small (const char *fmt, ...)
138 #else
139 void printf_small (char * fmt, ... ) __reentrant
140 #endif
142 va_list ap ;
144 va_start(ap,fmt);
146 for (; *fmt ; fmt++ ) {
147 if (*fmt == '%') {
148 long_flag = string_flag = char_flag = 0;
149 fmt++ ;
150 switch (*fmt) {
151 case 'l':
152 long_flag = 1;
153 fmt++;
154 break;
155 case 'h':
156 char_flag = 1;
157 fmt++;
160 switch (*fmt) {
161 case 's':
162 string_flag = 1;
163 break;
164 case 'd':
165 radix = 10;
166 break;
167 case 'x':
168 radix = 16;
169 break;
170 case 'c':
171 radix = 0;
172 break;
173 case 'o':
174 radix = 8;
175 break;
178 if (string_flag) {
179 str = va_arg(ap, char *);
180 while (*str) putchar(*str++);
181 continue ;
184 if (long_flag)
185 val = va_arg(ap,long);
186 else
187 if (char_flag)
188 val = va_arg(ap,char);
189 else
190 val = va_arg(ap,int);
192 #if NICE_LIFO_IMPLEMENTATION_BUT_NOT_PORTABLE
193 if (radix) pval();
194 #else
195 if (radix)
197 static char __idata buffer[12]; /* 37777777777(oct) */
198 char __idata * stri;
200 _ltoa (val, buffer, radix);
201 stri = buffer;
202 while (*stri)
204 putchar (*stri);
205 stri++;
208 #endif
209 else
210 putchar((char)val);
212 } else
213 putchar(*fmt);
216 #endif /* __SDCC_pic14 */