clean up some debugging output.
[Rockbox.git] / firmware / common / sprintf.c
blob768d69ca610d55072457c3834eb6575c060b3c1f
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2002 by Gary Czvitkovicz
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
23 * Minimal printf and snprintf formatting functions
25 * These support %c %s %d and %x
26 * Field width and zero-padding flag only
29 #include <stdarg.h>
30 #include <string.h>
31 #include <stdbool.h>
32 #include <limits.h>
34 #include "file.h" /* for write(), used in fprintf() */
35 #include "sprintf.h" /* to allow the simulator magic */
37 static const char hexdigit[] = "0123456789ABCDEF";
39 static int format(
40 /* call 'push()' for each output letter */
41 int (*push)(void *userp, unsigned char data),
42 void *userp,
43 const char *fmt,
44 va_list ap)
46 char *str;
47 char tmpbuf[12], pad;
48 int ch, width, val, sign, precision;
49 long lval, lsign;
50 unsigned int uval;
51 unsigned long ulval;
52 bool ok = true;
54 tmpbuf[sizeof tmpbuf - 1] = '\0';
56 while ((ch = *fmt++) != '\0' && ok)
58 if (ch == '%')
60 ch = *fmt++;
61 pad = ' ';
62 if (ch == '0')
63 pad = '0';
65 width = 0;
66 while (ch >= '0' && ch <= '9')
68 width = 10*width + ch - '0';
69 ch = *fmt++;
72 precision = 0;
73 if(ch == '.')
75 ch = *fmt++;
76 while (ch >= '0' && ch <= '9')
78 precision = 10*precision + ch - '0';
79 ch = *fmt++;
81 } else {
82 precision = INT_MAX;
85 str = tmpbuf + sizeof tmpbuf - 1;
86 switch (ch)
88 case 'c':
89 *--str = va_arg (ap, int);
90 break;
92 case 's':
93 str = va_arg (ap, char*);
94 break;
96 case 'd':
97 val = sign = va_arg (ap, int);
98 if (val < 0)
99 val = -val;
102 *--str = (val % 10) + '0';
103 val /= 10;
105 while (val > 0);
106 if (sign < 0)
107 *--str = '-';
108 break;
110 case 'u':
111 uval = va_arg(ap, unsigned int);
114 *--str = (uval % 10) + '0';
115 uval /= 10;
117 while (uval > 0);
118 break;
120 case 'x':
121 case 'X':
122 uval = va_arg (ap, int);
125 *--str = hexdigit[uval & 0xf];
126 uval >>= 4;
128 while (uval);
129 break;
131 case 'l':
132 ch = *fmt++;
133 switch(ch) {
134 case 'x':
135 case 'X':
136 ulval = va_arg (ap, long);
139 *--str = hexdigit[ulval & 0xf];
140 ulval >>= 4;
142 while (ulval);
143 break;
144 case 'd':
145 lval = lsign = va_arg (ap, long);
146 if (lval < 0)
147 lval = -lval;
150 *--str = (lval % 10) + '0';
151 lval /= 10;
153 while (lval > 0);
154 if (lsign < 0)
155 *--str = '-';
156 break;
158 case 'u':
159 ulval = va_arg(ap, unsigned long);
162 *--str = (ulval % 10) + '0';
163 ulval /= 10;
165 while (ulval > 0);
166 break;
168 default:
169 *--str = 'l';
170 *--str = ch;
173 break;
175 default:
176 *--str = ch;
177 break;
180 if (width > 0)
182 width -= strlen (str);
183 while (width-- > 0 && ok)
184 ok=push(userp, pad);
186 while (*str != '\0' && ok && precision--)
187 ok=push(userp, *str++);
189 else
190 ok=push(userp, ch);
192 return ok; /* true means good */
195 #if !defined(SIMULATOR) || !defined(linux)
196 /* ALSA library requires a more advanced snprintf, so let's not
197 override it in simulator for Linux. Note that Cygwin requires
198 our snprintf or it produces garbled output after a while. */
200 struct for_snprintf {
201 unsigned char *ptr; /* where to store it */
202 int bytes; /* amount already stored */
203 int max; /* max amount to store */
206 static int sprfunc(void *ptr, unsigned char letter)
208 struct for_snprintf *pr = (struct for_snprintf *)ptr;
209 if(pr->bytes < pr->max) {
210 *pr->ptr = letter;
211 pr->ptr++;
212 pr->bytes++;
213 return true;
215 return false; /* filled buffer */
219 int snprintf(char *buf, size_t size, const char *fmt, ...)
221 bool ok;
222 va_list ap;
223 struct for_snprintf pr;
225 pr.ptr = (unsigned char *)buf;
226 pr.bytes = 0;
227 pr.max = size;
229 va_start(ap, fmt);
230 ok = format(sprfunc, &pr, fmt, ap);
231 va_end(ap);
233 /* make sure it ends with a trailing zero */
234 pr.ptr[(pr.bytes < pr.max) ? 0 : -1] = '\0';
236 return pr.bytes;
239 int vsnprintf(char *buf, int size, const char *fmt, va_list ap)
241 bool ok;
242 struct for_snprintf pr;
244 pr.ptr = (unsigned char *)buf;
245 pr.bytes = 0;
246 pr.max = size;
248 ok = format(sprfunc, &pr, fmt, ap);
250 /* make sure it ends with a trailing zero */
251 pr.ptr[(pr.bytes < pr.max) ? 0 : -1] = '\0';
253 return pr.bytes;
256 #endif /* Linux SIMULATOR */
258 struct for_fprintf {
259 int fd; /* where to store it */
260 int bytes; /* amount stored */
263 static int fprfunc(void *pr, unsigned char letter)
265 struct for_fprintf *fpr = (struct for_fprintf *)pr;
266 int rc = write(fpr->fd, &letter, 1);
268 if(rc > 0) {
269 fpr->bytes++; /* count them */
270 return true; /* we are ok */
273 return false; /* failure */
277 int fdprintf(int fd, const char *fmt, ...)
279 bool ok;
280 va_list ap;
281 struct for_fprintf fpr;
283 fpr.fd=fd;
284 fpr.bytes=0;
286 va_start(ap, fmt);
287 ok = format(fprfunc, &fpr, fmt, ap);
288 va_end(ap);
290 return fpr.bytes; /* return 0 on error */