Imported Upstream version 2.9.0
[debian/cc1111] / device / lib / pic16 / libc / stdio / printf_tiny.c
1 /*-----------------------------------------------------------------
2     printf_tiny.c - source file for reduced version of printf
3
4     Modified for pic16 port, by Vangelis Rokas, 2004 (vrokas@otenet.gr)
5
6     Written By - Sandeep Dutta . sandeep.dutta@usa.net (1999)
7
8     This library is free software; you can redistribute it and/or modify it
9     under the terms of the GNU Library General Public License as published by the
10     Free Software Foundation; either version 2, or (at your option) any
11     later version.
12
13     This library is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16     GNU Library General Public License for more details.
17
18     You should have received a copy of the GNU Library General Public License
19     along with this program; if not, write to the Free Software
20     Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
22     In other words, you are welcome to use, share and improve this program.
23     You are forbidden to forbid anyone else to use, share and improve
24     what you give them.   Help stamp out software-hoarding!
25
26    As a special exception, if you link this library with other files,
27    some of which are compiled with SDCC, to produce an executable,
28    this library does not by itself cause the resulting executable
29    to be covered by the GNU General Public License.
30    This exception does not however invalidate any other reasons why
31    the executable file might be covered by the GNU General Public License.
32 -------------------------------------------------------------------------*/
33
34 /* This function uses function putchar() to dump a character
35  * to standard output. putchar() is defined in libc18f.lib
36  * as dummy function, which will be linked if no putchar()
37  * function is provided by the user.
38  * The user can write his own putchar() function and link it
39  * with the source *BEFORE* the libc18f.lib library. This way
40  * the linker will link the first function (i.e. the user's function) */
41
42 /* following formats are supported :-
43    format     output type       argument-type
44      %u*       unsigned            *
45
46      %b        binary
47      %d        decimal             int
48      %ld       decimal             long
49      %hd       decimal             char
50      %x        hexadecimal         int
51      %lxX      hexadecimal         long
52      %hxX      hexadecimal         char
53      %o        octal               int
54      %lo       octal               long
55      %ho       octal               char
56      %c        character           char
57      %s        character           generic pointer
58 */
59
60 /*
61  * This macro enables the use of the 'b' binary specifier and
62  * the use of "%b", "%hb" and "%lb"
63  */
64 /* #define BINARY_SPECIFIER */
65
66 #include <ctype.h>
67 #include <stdarg.h>
68 #include <stdio.h>
69 #include <stdlib.h>
70
71 #if 0
72 #define DPUT(c) putchar(c)
73 #else
74 #define DPUT(c)
75 #endif
76
77 #define ISLONG          (flong)
78 #define ISSTR           (fstr)
79 #define ISCHAR          (fchar)
80 #define HAVESIGN        (nosign)
81
82 #ifdef BINARY_SPECIFIER
83 /* "%lb" = "0" - "11111111111111111111111111111111" */
84 # define BUF_SIZE       33
85 #else
86 /* "%lo" = "0" - "37777777777" or  "-21777777777" - "17777777777" */
87 # define BUF_SIZE       13
88 #endif
89
90 void
91 printf_tiny (const char *fmt, ...)
92 {
93   char radix;
94   char flong, fstr;
95   char fchar, nosign;
96   char upcase;
97
98   char *str, *ch;
99   __data char *str1;
100   long val;
101   char buffer[BUF_SIZE];
102   va_list ap;
103
104   va_start (ap, fmt);
105   ch = fmt;
106
107   while (*ch) //for (; *fmt ; fmt++ )
108     {
109       if (*ch == '%')
110         {
111           ISLONG = 0;
112           ISSTR = 0;
113           ISCHAR = 0;
114           HAVESIGN = 0;
115           radix = 0;
116           upcase = 0;
117           ch++;
118
119           if (*ch == 'u')
120             {
121               HAVESIGN = 1;
122               ++ch;
123             }
124
125           if (*ch == 'l')
126             {
127               ISLONG = 1;
128               ++ch;
129             }
130           else if (*ch == 'h')
131             {
132               ISCHAR = 1;
133               ++ch;
134             }
135
136           if (*ch == 's')
137             ISSTR = 1;
138           else if (*ch == 'd')
139             radix = 10;
140           else if (*ch == 'x')
141             {
142               radix = 16;
143               upcase = 0;
144             }
145           else if (*ch == 'X')
146             {
147               radix = 16;
148               upcase = 1;
149             }
150           else if (*ch == 'c')
151             radix = 0;
152           else if (*ch == 'o')
153             radix = 8;
154 #ifdef BINARX_SPECIFIER
155           else if (*ch == 'b')
156             radix = 2;
157 #endif
158
159           if (ISSTR)
160             {
161               str = va_arg (ap, char *);
162               while (*str)
163                 {
164                   putchar (*str);
165                   ++str;
166                 }
167             }
168           else
169             {
170               if (ISLONG)
171                 val = va_arg (ap, long);
172               else if (ISCHAR)
173                 {
174                   val = (unsigned char) va_arg (ap, int);       // FIXME: SDCC casts char arguments into ints
175                   if (!HAVESIGN)
176                     val = (char) val;   // FIXME cont'd: sign-extend if required
177                 }
178               else
179                 val = va_arg (ap, int);
180
181               if (radix)
182                 {
183                   if (HAVESIGN)
184                     ultoa (val, buffer, radix);
185                   else
186                     ltoa (val, buffer, radix);
187
188                   str1 = buffer;
189                   while ((*str1))
190                     {
191                       radix = *str1;
192                       if (upcase)
193                         radix = toupper (radix);
194                       putchar (radix);
195                       ++str1;
196                     }
197                 }
198               else
199                 putchar ((char) val);
200             }
201         }
202       else
203         putchar (*ch);
204
205       ++ch;
206     }
207 }