f413180b7c9ebcab012546884f9695b37c1143c2
[fw/sdcc] / device / lib / pic16 / libc / stdio / vfprintf.c
1 /*-----------------------------------------------------------------
2     vfprintf.c - source file for reduced version of printf
3
4     Modified for pic16 port, by Vangelis Rokas, 2005 (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
27 /*
28 ** $Id$
29 */
30
31 /* following formats are supported :-
32    format     output type       argument-type
33      %%        -                   -
34      %u*       unsigned            *
35      %b        binary              int
36      %lb       binary              long
37      %hb       binary              char
38      %d        decimal             int
39      %ld       decimal             long
40      %hd       decimal             char
41      %[xX]     hexadecimal         int
42      %l[xX]    hexadecimal         long
43      %h[xX]    hexadecimal         char
44      %o        octal               int
45      %lo       octal               long
46      %ho       octal               char
47      %c        character           char
48      %s        character           generic pointer
49 */
50
51 #include <ctype.h>
52 #include <stdarg.h>
53 #include <stdio.h>
54 #include <stdlib.h>
55
56 #if _DEBUG
57 extern void io_long(unsigned long);
58 extern void io_str(char *);
59 extern void io_int(unsigned int);
60 #endif
61
62 unsigned int vfprintf(FILE *stream, char *fmt, va_list ap)
63 {
64   unsigned char radix;
65   unsigned char flong, fstr;
66   unsigned char fchar, nosign;
67   unsigned char upcase;
68   unsigned int count=0;
69   char *str, *ch;
70   __data char *str1;
71   long val;
72 //  static char buffer[16];
73   char buffer[16];
74
75
76 #if _DEBUG
77   io_str( "vfprintf: " );
78   io_long( (unsigned long)stream );
79   io_long( (unsigned long)fmt );
80 #endif
81
82 //    va_start(ap,fmt);
83   ch = fmt;
84
85   while( *ch ) {      //for (; *fmt ; fmt++ )
86     if (*ch == '%') {
87       flong = 0;
88       fstr = 0;
89       fchar = 0;
90       nosign = 0;
91       radix = 0;
92       upcase = 0;
93       ch++;
94
95       if(*ch == '%') {
96         __stream_putchar(stream, *ch);
97         ++count;
98         ++ch;
99         continue;
100       }
101
102       if(*ch == 'u') {
103         nosign = 1;
104         ch++;
105       }
106
107       if(*ch == 'l') {
108         flong = 1;
109         ch++;
110       } else if(*ch == 'h') {
111         fchar = 1;
112         ch++;
113       }
114
115       if(*ch == 's')fstr = 1;
116       else if(*ch == 'd')radix = 10;
117       else if(*ch == 'x'){ radix = 16; upcase = 0; }
118       else if(*ch == 'X'){ radix = 16; upcase = 1; }
119       else if(*ch == 'c')radix = 0;
120       else if(*ch == 'o')radix = 8;
121       else if(*ch == 'b')radix = 2;
122       else {
123         __stream_putchar(stream, *ch);
124         ++count;
125         ++ch;
126         continue;
127       }
128
129       if(fstr) {
130         str = va_arg(ap, char *);
131         while(*str) { __stream_putchar(stream, *str); str++; count++; }
132       } else {
133         val = 0;
134         if(flong) {
135           val = va_arg(ap, long);
136 #if _DEBUG
137           io_long(val);
138 #endif
139         }
140         else if(fchar) {
141           val = (unsigned char)va_arg(ap, int); // FIXME: SDCC passes 1-byte char varargs as 2-byte ints...
142           if (!nosign) val = (char) val; // (FIXME cont'd) sign extend if required
143 #if _DEBUG
144           io_long(val);
145 #endif
146         }
147         else {
148           val = va_arg(ap, int);
149 #if _DEBUG
150           io_long(val);
151 #endif
152         }
153
154         if(radix) {
155           if(nosign)
156             ultoa(val, buffer, radix);
157           else
158             ltoa (val, buffer, radix);
159
160           str1 = buffer;
161           while( (*str1) ) {
162             radix = *str1;
163             if(upcase)
164               radix = toupper( radix );
165             __stream_putchar(stream, (unsigned char)radix);
166             count++;
167             str1++;
168           }
169         } else {
170           __stream_putchar(stream, (unsigned char)val);
171           count++;
172         }
173       }
174     } else {
175       __stream_putchar(stream, *ch);
176       count++;
177     }
178
179     ch++;
180   }
181
182   return (count);
183 }