Move c/h files implementing/defining standard library stuff into a new libc directory...
[kugel-rb.git] / firmware / common / format.c
blob987af417da8abf31d9d3a39fc4f1d102c4b42e83
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 #include <stdarg.h>
24 #include <stdbool.h>
25 #include <limits.h>
26 #include <string.h>
27 #include "file.h"
29 static const char hexdigit[] = "0123456789ABCDEF";
31 int format(
32 /* call 'push()' for each output letter */
33 int (*push)(void *userp, unsigned char data),
34 void *userp,
35 const char *fmt,
36 va_list ap)
38 char *str;
39 char tmpbuf[12], pad;
40 int ch, width, val, sign, precision;
41 long lval, lsign;
42 unsigned int uval;
43 unsigned long ulval;
44 bool ok = true;
46 tmpbuf[sizeof tmpbuf - 1] = '\0';
48 while ((ch = *fmt++) != '\0' && ok)
50 if (ch == '%')
52 ch = *fmt++;
53 pad = ' ';
54 if (ch == '0')
55 pad = '0';
57 width = 0;
58 while (ch >= '0' && ch <= '9')
60 width = 10*width + ch - '0';
61 ch = *fmt++;
64 precision = 0;
65 if(ch == '.')
67 ch = *fmt++;
68 while (ch >= '0' && ch <= '9')
70 precision = 10*precision + ch - '0';
71 ch = *fmt++;
73 } else {
74 precision = INT_MAX;
77 str = tmpbuf + sizeof tmpbuf - 1;
78 switch (ch)
80 case 'c':
81 *--str = va_arg (ap, int);
82 break;
84 case 's':
85 str = va_arg (ap, char*);
86 break;
88 case 'd':
89 val = sign = va_arg (ap, int);
90 if (val < 0)
91 val = -val;
94 *--str = (val % 10) + '0';
95 val /= 10;
97 while (val > 0);
98 if (sign < 0)
99 *--str = '-';
100 break;
102 case 'u':
103 uval = va_arg(ap, unsigned int);
106 *--str = (uval % 10) + '0';
107 uval /= 10;
109 while (uval > 0);
110 break;
112 case 'x':
113 case 'X':
114 pad='0';
115 uval = va_arg (ap, int);
118 *--str = hexdigit[uval & 0xf];
119 uval >>= 4;
121 while (uval);
122 break;
124 case 'l':
125 ch = *fmt++;
126 switch(ch) {
127 case 'x':
128 case 'X':
129 pad='0';
130 ulval = va_arg (ap, long);
133 *--str = hexdigit[ulval & 0xf];
134 ulval >>= 4;
136 while (ulval);
137 break;
138 case 'd':
139 lval = lsign = va_arg (ap, long);
140 if (lval < 0)
141 lval = -lval;
144 *--str = (lval % 10) + '0';
145 lval /= 10;
147 while (lval > 0);
148 if (lsign < 0)
149 *--str = '-';
150 break;
152 case 'u':
153 ulval = va_arg(ap, unsigned long);
156 *--str = (ulval % 10) + '0';
157 ulval /= 10;
159 while (ulval > 0);
160 break;
162 default:
163 *--str = 'l';
164 *--str = ch;
167 break;
169 default:
170 *--str = ch;
171 break;
174 if (width > 0)
176 width -= strlen (str);
177 while (width-- > 0 && ok)
178 ok=push(userp, pad);
180 while (*str != '\0' && ok && precision--)
181 ok=push(userp, *str++);
183 else
184 ok=push(userp, ch);
186 return ok; /* true means good */
189 struct for_fprintf {
190 int fd; /* where to store it */
191 int bytes; /* amount stored */
194 static int fprfunc(void *pr, unsigned char letter)
196 struct for_fprintf *fpr = (struct for_fprintf *)pr;
197 int rc = write(fpr->fd, &letter, 1);
199 if(rc > 0) {
200 fpr->bytes++; /* count them */
201 return true; /* we are ok */
204 return false; /* failure */
208 int fdprintf(int fd, const char *fmt, ...)
210 bool ok;
211 va_list ap;
212 struct for_fprintf fpr;
214 fpr.fd=fd;
215 fpr.bytes=0;
217 va_start(ap, fmt);
218 ok = format(fprfunc, &fpr, fmt, ap);
219 va_end(ap);
221 return fpr.bytes; /* return 0 on error */
224 int vuprintf(int (*push)(void *userp, unsigned char data), void *userp, const char *fmt, va_list ap)
226 return format(push, userp, fmt, ap);