Fixed red build...
[kugel-rb.git] / firmware / common / sprintf.c
blob868394521176edce462d21c567ac9da5b5592bc4
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2002 by Gary Czvitkovicz
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
21 * Minimal printf and snprintf formatting functions
23 * These support %c %s %d and %x
24 * Field width and zero-padding flag only
27 #include <stdarg.h>
28 #include <string.h>
29 #include <stdbool.h>
31 #include "file.h" /* for write(), used in fprintf() */
32 #include "sprintf.h" /* to allow the simulator magic */
34 static const char hexdigit[] = "0123456789ABCDEF";
36 static int format(
37 /* call 'push()' for each output letter */
38 int (*push)(void *userp, unsigned char data),
39 void *userp,
40 const char *fmt,
41 va_list ap)
43 char *str;
44 char tmpbuf[12], pad;
45 int ch, width, val, sign;
46 long lval;
47 unsigned int uval;
48 unsigned long ulval;
49 bool ok = true;
51 tmpbuf[sizeof tmpbuf - 1] = '\0';
53 while ((ch = *fmt++) != '\0' && ok)
55 if (ch == '%')
57 ch = *fmt++;
58 pad = ' ';
59 if (ch == '0')
60 pad = '0';
62 width = 0;
63 while (ch >= '0' && ch <= '9')
65 width = 10*width + ch - '0';
66 ch = *fmt++;
69 str = tmpbuf + sizeof tmpbuf - 1;
70 switch (ch)
72 case 'c':
73 *--str = va_arg (ap, int);
74 break;
76 case 's':
77 str = va_arg (ap, char*);
78 break;
80 case 'd':
81 val = sign = va_arg (ap, int);
82 if (val < 0)
83 val = -val;
86 *--str = (val % 10) + '0';
87 val /= 10;
89 while (val > 0);
90 if (sign < 0)
91 *--str = '-';
92 break;
94 case 'x':
95 case 'X':
96 uval = va_arg (ap, int);
99 *--str = hexdigit[uval & 0xf];
100 uval >>= 4;
102 while (uval);
103 break;
105 case 'l':
106 ch = *fmt++;
107 switch(ch) {
108 case 'x':
109 case 'X':
110 ulval = va_arg (ap, long);
113 *--str = hexdigit[ulval & 0xf];
114 ulval >>= 4;
116 while (ulval);
117 break;
118 case 'd':
119 lval = sign = va_arg (ap, long);
120 if (lval < 0)
121 lval = -lval;
124 *--str = (lval % 10) + '0';
125 lval /= 10;
127 while (lval > 0);
128 if (sign < 0)
129 *--str = '-';
130 break;
132 default:
133 *--str = 'l';
134 *--str = ch;
137 break;
139 default:
140 *--str = ch;
141 break;
144 if (width > 0)
146 width -= strlen (str);
147 while (width-- > 0 && ok)
148 ok=push(userp, pad);
150 while (*str != '\0' && ok)
151 ok=push(userp, *str++);
153 else
154 ok=push(userp, ch);
156 return ok; /* true means good */
159 struct for_snprintf {
160 unsigned char *ptr; /* where to store it */
161 int bytes; /* amount already stored */
162 int max; /* max amount to store */
165 static int sprfunc(void *ptr, unsigned char letter)
167 struct for_snprintf *pr = (struct for_snprintf *)ptr;
168 if(pr->bytes < pr->max) {
169 *pr->ptr = letter;
170 pr->ptr++;
171 pr->bytes++;
172 return true;
174 return false; /* filled buffer */
178 int snprintf(char *buf, size_t size, const char *fmt, ...)
180 bool ok;
181 va_list ap;
182 struct for_snprintf pr;
184 pr.ptr = buf;
185 pr.bytes = 0;
186 pr.max = size;
188 va_start(ap, fmt);
189 ok = format(sprfunc, &pr, fmt, ap);
190 va_end(ap);
192 /* make sure it ends with a trailing zero */
193 pr.ptr[(pr.bytes < pr.max) ? 0 : -1] = '\0';
195 return pr.bytes;
198 int vsnprintf(char *buf, int size, const char *fmt, va_list ap)
200 bool ok;
201 struct for_snprintf pr;
203 pr.ptr = buf;
204 pr.bytes = 0;
205 pr.max = size;
207 ok = format(sprfunc, &pr, fmt, ap);
209 /* make sure it ends with a trailing zero */
210 pr.ptr[(pr.bytes < pr.max) ? 0 : -1] = '\0';
212 return pr.bytes;
215 struct for_fprintf {
216 int fd; /* where to store it */
217 int bytes; /* amount stored */
220 static int fprfunc(void *pr, unsigned char letter)
222 struct for_fprintf *fpr = (struct for_fprintf *)pr;
223 int rc = write(fpr->fd, &letter, 1);
225 if(rc > 0) {
226 fpr->bytes++; /* count them */
227 return true; /* we are ok */
230 return false; /* failure */
234 int fprintf(int fd, const char *fmt, ...)
236 bool ok;
237 va_list ap;
238 struct for_fprintf fpr;
240 fpr.fd=fd;
241 fpr.bytes=0;
243 va_start(ap, fmt);
244 ok = format(fprfunc, &fpr, fmt, ap);
245 va_end(ap);
247 return fpr.bytes; /* return 0 on error */