We just released 2.3...
[kugel-rb.git] / firmware / common / sprintf.c
blob6542c9d993b99b8a837cbc3f626968444d83477f
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 unsigned int uval;
47 bool ok = true;
49 tmpbuf[sizeof tmpbuf - 1] = '\0';
51 while ((ch = *fmt++) != '\0' && ok)
53 if (ch == '%')
55 ch = *fmt++;
56 pad = ' ';
57 if (ch == '0')
58 pad = '0';
60 width = 0;
61 while (ch >= '0' && ch <= '9')
63 width = 10*width + ch - '0';
64 ch = *fmt++;
67 str = tmpbuf + sizeof tmpbuf - 1;
68 switch (ch)
70 case 'c':
71 *--str = va_arg (ap, int);
72 break;
74 case 's':
75 str = va_arg (ap, char*);
76 break;
78 case 'd':
79 val = sign = va_arg (ap, int);
80 if (val < 0)
81 val = -val;
84 *--str = (val % 10) + '0';
85 val /= 10;
87 while (val > 0);
88 if (sign < 0)
89 *--str = '-';
90 break;
92 case 'x':
93 case 'X':
94 uval = va_arg (ap, int);
97 *--str = hexdigit[uval & 0xf];
98 uval >>= 4;
100 while (uval);
101 break;
103 default:
104 *--str = ch;
105 break;
108 if (width > 0)
110 width -= strlen (str);
111 while (width-- > 0 && ok)
112 ok=push(userp, pad);
114 while (*str != '\0' && ok)
115 ok=push(userp, *str++);
117 else
118 ok=push(userp, ch);
120 return ok; /* true means good */
123 struct for_snprintf {
124 unsigned char *ptr; /* where to store it */
125 int bytes; /* amount already stored */
126 int max; /* max amount to store */
129 static int sprfunc(void *ptr, unsigned char letter)
131 struct for_snprintf *pr = (struct for_snprintf *)ptr;
132 if(pr->bytes < pr->max) {
133 *pr->ptr = letter;
134 pr->ptr++;
135 pr->bytes++;
136 return true;
138 return false; /* filled buffer */
142 int snprintf(char *buf, size_t size, const char *fmt, ...)
144 bool ok;
145 va_list ap;
146 struct for_snprintf pr;
148 pr.ptr = buf;
149 pr.bytes = 0;
150 pr.max = size;
152 va_start(ap, fmt);
153 ok = format(sprfunc, &pr, fmt, ap);
154 va_end(ap);
156 /* make sure it ends with a trailing zero */
157 pr.ptr[(pr.bytes < pr.max) ? 0 : -1] = '\0';
159 return pr.bytes;
162 int vsnprintf(char *buf, int size, const char *fmt, va_list ap)
164 bool ok;
165 struct for_snprintf pr;
167 pr.ptr = buf;
168 pr.bytes = 0;
169 pr.max = size;
171 ok = format(sprfunc, &pr, fmt, ap);
173 /* make sure it ends with a trailing zero */
174 pr.ptr[(pr.bytes < pr.max) ? 0 : -1] = '\0';
176 return pr.bytes;
179 struct for_fprintf {
180 int fd; /* where to store it */
181 int bytes; /* amount stored */
184 static int fprfunc(void *pr, unsigned char letter)
186 struct for_fprintf *fpr = (struct for_fprintf *)pr;
187 int rc = write(fpr->fd, &letter, 1);
189 if(rc > 0) {
190 fpr->bytes++; /* count them */
191 return true; /* we are ok */
194 return false; /* failure */
198 int fprintf(int fd, const char *fmt, ...)
200 bool ok;
201 va_list ap;
202 struct for_fprintf fpr;
204 fpr.fd=fd;
205 fpr.bytes=0;
207 va_start(ap, fmt);
208 ok = format(fprfunc, &fpr, fmt, ap);
209 va_end(ap);
211 return fpr.bytes; /* return 0 on error */