summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'firmware')
-rw-r--r--firmware/SOURCES3
-rw-r--r--firmware/common/fdprintf.c56
-rw-r--r--firmware/common/format.c267
-rw-r--r--firmware/common/vuprintf.c974
-rw-r--r--firmware/include/vuprintf.h (renamed from firmware/include/format.h)34
-rw-r--r--firmware/libc/sprintf.c110
-rw-r--r--firmware/logf.c12
-rw-r--r--firmware/target/arm/s3c2440/uart-s3c2440.c2
8 files changed, 1125 insertions, 333 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES
index 9337c14234..1310fa0434 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -204,7 +204,7 @@ common/fileobj_mgr.c
204common/dircache.c 204common/dircache.c
205#endif /* HAVE_DIRCACHE */ 205#endif /* HAVE_DIRCACHE */
206common/pathfuncs.c 206common/pathfuncs.c
207common/format.c 207common/fdprintf.c
208common/linked_list.c 208common/linked_list.c
209common/strcasecmp.c 209common/strcasecmp.c
210common/strcasestr.c 210common/strcasestr.c
@@ -214,6 +214,7 @@ common/strlcpy.c
214common/structec.c 214common/structec.c
215common/timefuncs.c 215common/timefuncs.c
216common/unicode.c 216common/unicode.c
217common/vuprintf.c
217 218
218/* Display */ 219/* Display */
219scroll_engine.c 220scroll_engine.c
diff --git a/firmware/common/fdprintf.c b/firmware/common/fdprintf.c
new file mode 100644
index 0000000000..21d0a72e58
--- /dev/null
+++ b/firmware/common/fdprintf.c
@@ -0,0 +1,56 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Felix Arends
11 *
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.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include <limits.h>
22#include "file.h"
23#include "vuprintf.h"
24
25struct for_fprintf {
26 int fd; /* where to store it */
27 int rem; /* amount remaining */
28};
29
30static int fprfunc(void *pr, int letter)
31{
32 struct for_fprintf *fpr = (struct for_fprintf *)pr;
33
34 /* TODO: add a small buffer to reduce write() calls */
35 if (write(fpr->fd, &(char){ letter }, 1) > 0) {
36 return --fpr->rem;
37 }
38
39 return -1;
40}
41
42int fdprintf(int fd, const char *fmt, ...)
43{
44 int bytes;
45 struct for_fprintf fpr;
46 va_list ap;
47
48 fpr.fd = fd;
49 fpr.rem = INT_MAX;
50
51 va_start(ap, fmt);
52 bytes = vuprintf(fprfunc, &fpr, fmt, ap);
53 va_end(ap);
54
55 return bytes;
56}
diff --git a/firmware/common/format.c b/firmware/common/format.c
deleted file mode 100644
index 60c50ccd89..0000000000
--- a/firmware/common/format.c
+++ /dev/null
@@ -1,267 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Gary Czvitkovicz
11 *
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.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22
23#include <stdarg.h>
24#include <stdbool.h>
25#include <limits.h>
26#include <string.h>
27#include "file.h"
28#include "format.h"
29
30static const char hexdigit[] = "0123456789ABCDEF";
31
32void format(
33 /* call 'push()' for each output letter */
34 int (*push)(void *userp, unsigned char data),
35 void *userp,
36 const char *fmt,
37 va_list ap)
38{
39 char *str;
40 char tmpbuf[12], pad;
41 int ch, width, val, sign, precision;
42 long lval, lsign;
43 unsigned int uval;
44 unsigned long ulval;
45 size_t uszval;
46 ssize_t szval, szsign;
47 bool ok = true;
48
49 tmpbuf[sizeof tmpbuf - 1] = '\0';
50
51 while ((ch = *fmt++) != '\0' && ok)
52 {
53 if (ch == '%')
54 {
55 ch = *fmt++;
56 pad = ' ';
57 if (ch == '0')
58 pad = '0';
59
60 width = 0;
61 while (ch >= '0' && ch <= '9')
62 {
63 width = 10*width + ch - '0';
64 ch = *fmt++;
65 }
66
67 precision = 0;
68 if(ch == '.')
69 {
70 ch = *fmt++;
71 while (ch >= '0' && ch <= '9')
72 {
73 precision = 10*precision + ch - '0';
74 ch = *fmt++;
75 }
76 } else {
77 precision = INT_MAX;
78 }
79
80 str = tmpbuf + sizeof tmpbuf - 1;
81 switch (ch)
82 {
83 case 'c':
84 *--str = va_arg (ap, int);
85 break;
86
87 case 's':
88 str = va_arg (ap, char*);
89 break;
90
91 case 'd':
92 val = sign = va_arg (ap, int);
93 if (val < 0)
94 val = -val;
95 do
96 {
97 *--str = (val % 10) + '0';
98 val /= 10;
99 }
100 while (val > 0);
101 if (sign < 0)
102 *--str = '-';
103 break;
104
105 case 'u':
106 uval = va_arg(ap, unsigned int);
107 do
108 {
109 *--str = (uval % 10) + '0';
110 uval /= 10;
111 }
112 while (uval > 0);
113 break;
114 case 'p':
115 case 'P':
116 /* for pointers prepend 0x and act like 'X' */
117 push(userp, '0');
118 push(userp, 'x');
119 /* fall through */
120 case 'x':
121 case 'X':
122 pad='0';
123 uval = va_arg (ap, int);
124 do
125 {
126 *--str = hexdigit[uval & 0xf];
127 uval >>= 4;
128 }
129 while (uval);
130 break;
131
132 case 'l':
133 ch = *fmt++;
134 switch(ch) {
135 case 'x':
136 case 'X':
137 pad='0';
138 ulval = va_arg (ap, long);
139 do
140 {
141 *--str = hexdigit[ulval & 0xf];
142 ulval >>= 4;
143 }
144 while (ulval);
145 break;
146 case 'd':
147 lval = lsign = va_arg (ap, long);
148 if (lval < 0)
149 lval = -lval;
150 do
151 {
152 *--str = (lval % 10) + '0';
153 lval /= 10;
154 }
155 while (lval > 0);
156 if (lsign < 0)
157 *--str = '-';
158 break;
159
160 case 'u':
161 ulval = va_arg(ap, unsigned long);
162 do
163 {
164 *--str = (ulval % 10) + '0';
165 ulval /= 10;
166 }
167 while (ulval > 0);
168 break;
169
170 default:
171 *--str = 'l';
172 *--str = ch;
173 }
174
175 break;
176
177 case 'z':
178 ch = *fmt++;
179 switch(ch) {
180 case 'd':
181 szval = szsign = va_arg (ap, ssize_t);
182 if (szval < 0)
183 szval = -szval;
184 do
185 {
186 *--str = (szval % 10) + '0';
187 szval /= 10;
188 }
189 while (szval > 0);
190 if (szsign < 0)
191 *--str = '-';
192 break;
193
194 case 'u':
195 uszval = va_arg(ap, size_t);
196 do
197 {
198 *--str = (uszval % 10) + '0';
199 uszval /= 10;
200 }
201 while (uszval > 0);
202 break;
203
204 default:
205 *--str = 'z';
206 *--str = ch;
207 }
208
209 break;
210
211 default:
212 *--str = ch;
213 break;
214 }
215
216 if (width > 0)
217 {
218 width -= strlen (str);
219 while (width-- > 0 && ok)
220 ok=push(userp, pad);
221 }
222 while (*str != '\0' && ok && precision--)
223 ok=push(userp, *str++);
224 }
225 else
226 ok=push(userp, ch);
227 }
228}
229
230struct for_fprintf {
231 int fd; /* where to store it */
232 int bytes; /* amount stored */
233};
234
235static int fprfunc(void *pr, unsigned char letter)
236{
237 struct for_fprintf *fpr = (struct for_fprintf *)pr;
238 int rc = write(fpr->fd, &letter, 1);
239
240 if(rc > 0) {
241 fpr->bytes++; /* count them */
242 return true; /* we are ok */
243 }
244
245 return false; /* failure */
246}
247
248
249int fdprintf(int fd, const char *fmt, ...)
250{
251 va_list ap;
252 struct for_fprintf fpr;
253
254 fpr.fd=fd;
255 fpr.bytes=0;
256
257 va_start(ap, fmt);
258 format(fprfunc, &fpr, fmt, ap);
259 va_end(ap);
260
261 return fpr.bytes; /* return 0 on error */
262}
263
264void vuprintf(int (*push)(void *userp, unsigned char data), void *userp, const char *fmt, va_list ap)
265{
266 format(push, userp, fmt, ap);
267}
diff --git a/firmware/common/vuprintf.c b/firmware/common/vuprintf.c
new file mode 100644
index 0000000000..c32b690cf8
--- /dev/null
+++ b/firmware/common/vuprintf.c
@@ -0,0 +1,974 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Gary Czvitkovicz
11 * Copyright (C) 2017 by Michael A. Sevakis
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ****************************************************************************/
22#include <sys/types.h>
23#include <limits.h>
24#include <string.h>
25#include "system.h"
26#include "vuprintf.h"
27
28#if 0
29/* turn everything on */
30#define FMT_LENMOD (0xffffffff)
31#define FMT_RADIX (0xffffffff)
32#endif
33
34/* these are the defaults if no other preference is given */
35#ifndef FMT_LENMOD
36#define FMT_LENMOD (FMT_LENMOD_l | \
37 FMT_LENMOD_z)
38#endif /* FMT_LENMOD */
39
40#ifndef FMT_RADIX
41#define FMT_RADIX (FMT_RADIX_c | \
42 FMT_RADIX_d | \
43 FMT_RADIX_p | \
44 FMT_RADIX_s | \
45 FMT_RADIX_u | \
46 FMT_RADIX_x)
47#endif /* FMT_RADIX */
48
49/** Length modifier and radix flags **/
50
51/* compulsory length modifiers: NONE
52 * however a compatible 'l' or 'll' must be defined if another requires it */
53#define FMT_LENMOD_h 0x001 /* signed/unsigned short (%h<radix>) */
54#define FMT_LENMOD_hh 0x002 /* signed/unsigned char (%hh<radix>) */
55#define FMT_LENMOD_j 0x004 /* intmax_t/uintmax_t (%j<radix>) */
56#define FMT_LENMOD_l 0x008 /* signed/unsigned long (%l<radix>) */
57#define FMT_LENMOD_ll 0x010 /* signed/unsigned long long (%ll<radix>) */
58#define FMT_LENMOD_t 0x020 /* signed/unsigned ptrdiff_t (%t<radix>) */
59#define FMT_LENMOD_z 0x040 /* size_t/ssize_t (%z<radix>) */
60#define FMT_LENMOD_L 0x080 /* long double (instead of double) */
61
62/* compulsory radixes: c, d, i, u, s */
63#define FMT_RADIX_c 0x001 /* single character (%c) */
64#define FMT_RADIX_d 0x002 /* signed integer type, decimal (%d %i) */
65#define FMT_RADIX_n 0x004 /* bytes output so far (%n) */
66#define FMT_RADIX_o 0x008 /* unsigned integer type, octal (%o) */
67#define FMT_RADIX_p 0x010 /* pointer (%p %P) */
68#define FMT_RADIX_s 0x020 /* string (%s) */
69#define FMT_RADIX_u 0x040 /* unsigned integer type, decimal (%u) */
70#define FMT_RADIX_x 0x080 /* unsigned integer type, hex (%x %X) */
71#define FMT_RADIX_a 0x100 /* hex floating point "[-]0xh.hhhhp±d" */
72#define FMT_RADIX_e 0x200 /* floating point with exponent "[-]d.ddde±dd" */
73#define FMT_RADIX_f 0x400 /* floating point "[-]ddd.ddd" */
74#define FMT_RADIX_g 0x800 /* floating point exponent or decimal depending
75 upon value and precision */
76
77/* avoid defining redundant functions if two or more types can use the same
78 * something not getting a macro means it gets assigned its own value and
79 * formatter */
80
81/* l */
82#if LONG_MIN == INT_MIN && LONG_MAX == INT_MAX
83#define val_ld val_d
84#define format_ld format_d
85#define branch_fmt_ld branch_fmt_d
86#elif !(FMT_LENMOD & FMT_LENMOD_l) /* unique */
87#define val_ld
88#endif /* LONG_ */
89
90#if ULONG_MAX == UINT_MAX
91#define val_lu val_u
92#define format_lu format_u
93#define branch_fmt_lu branch_fmt_u
94#elif !(FMT_LENMOD & FMT_LENMOD_l) /* unique */
95#define val_lu
96#endif /* ULONG_ */
97
98/* ll */
99#if LLONG_MIN == INT_MIN && LLONG_MAX == INT_MAX
100#define val_lld val_d
101#define format_lld format_d
102#define branch_fmt_lld branch_fmt_d
103#elif LLONG_MIN == LONG_MIN && LLONG_MAX == LONG_MAX
104#define val_lld val_ld
105#define format_lld format_ld
106#define branch_fmt_lld branch_fmt_ld
107#elif !(FMT_LENMOD & FMT_LENMOD_ll) /* unique */
108#define val_lld
109#endif /* LLONG_ */
110
111#if ULLONG_MAX == UINT_MAX
112#define val_llu val_u
113#define format_llu format_u
114#define branch_fmt_llu branch_fmt_u
115#elif ULLONG_MAX == ULONG_MAX
116#define val_llu val_lu
117#define format_llu format_lu
118#define branch_fmt_llu branch_fmt_lu
119#elif !(FMT_LENMOD & FMT_LENMOD_ll) /* unique */
120#define val_llu
121#endif /* ULLONG_ */
122
123/* char/short parameter type promotions */
124#define SCHAR_INT_ARG int
125#define UCHAR_INT_ARG int
126#define SSHRT_INT_ARG int
127#if USHRT_MAX == UINT_MAX
128#define USHRT_INT_ARG unsigned int
129#else
130#define USHRT_INT_ARG int
131#endif
132
133/* some macros to have conditional work inside macros */
134#if (FMT_LENMOD & FMT_LENMOD_l)
135#define IF_FMT_LENMOD_l(...) __VA_ARGS__
136#else
137#define IF_FMT_LENMOD_l(...)
138#endif
139
140#if (FMT_LENMOD & FMT_LENMOD_ll)
141#define IF_FMT_LENMOD_ll(...) __VA_ARGS__
142#else
143#define IF_FMT_LENMOD_ll(...)
144#endif
145
146#if (FMT_RADIX & FMT_RADIX_o)
147#define IF_FMT_RADIX_o(...) __VA_ARGS__
148#else
149#define IF_FMT_RADIX_o(...)
150#endif
151
152#if (FMT_RADIX & FMT_RADIX_x)
153#define IF_FMT_RADIX_x(...) __VA_ARGS__
154#else
155#define IF_FMT_RADIX_x(...)
156#endif
157
158/* synthesize multicharacter constant */
159#define LENMOD2(cv, ch) \
160 (((cv) << CHAR_BIT) | (ch))
161
162#define LENMOD_NONE 0
163
164#if (FMT_LENMOD & FMT_LENMOD_h)
165#define LENMOD_h 'h'
166#endif
167#if (FMT_LENMOD & FMT_LENMOD_hh)
168#define LENMOD_hh LENMOD2('h', 'h') /* 'hh' */
169#endif
170#if (FMT_LENMOD & FMT_LENMOD_j)
171#define LENMOD_j 'j'
172#endif
173#if (FMT_LENMOD & FMT_LENMOD_l)
174#define LENMOD_l 'l'
175#endif
176#if (FMT_LENMOD & FMT_LENMOD_ll)
177#undef FMT_MAX_L
178#define LENMOD_ll LENMOD2('l', 'l') /* 'll' */
179#endif
180#if (FMT_LENMOD & FMT_LENMOD_t)
181#define LENMOD_t 't'
182#endif
183#if (FMT_LENMOD & FMT_LENMOD_z)
184#define LENMOD_z 'z'
185#endif
186
187/* select type-compatible length modifier
188 * (a bit hacky; it should be range-based) */
189#define LENMOD_INTCOMPAT_SEL(type, signd) \
190 ({ int __lenmod; \
191 size_t __size = sizeof (type); \
192 if (__size == ((signd) ? sizeof (int) : \
193 sizeof (unsigned int))) { \
194 __lenmod = LENMOD_NONE; \
195 } \
196 else if (__size == ((signd) ? sizeof (long) : \
197 sizeof (unsigned long))) { \
198 IF_FMT_LENMOD_l(__lenmod = LENMOD_l;) \
199 } \
200 else if (__size == ((signd) ? sizeof (long long) : \
201 sizeof (unsigned long long))) { \
202 IF_FMT_LENMOD_ll(__lenmod = LENMOD_ll;) \
203 } \
204 __lenmod; })
205
206/* call formatting function for the compatible integer type */
207#define LENMOD_INTCOMPAT_CALL(inteqv, val, fmt_buf, x, signd) \
208 ({ const char *__buf; \
209 switch (inteqv) { \
210 case LENMOD_NONE: \
211 __buf = (signd) ? \
212 format_d((val), (fmt_buf), (x)) : \
213 format_u((val), (fmt_buf), (x)); \
214 break; \
215 IF_FMT_LENMOD_l( \
216 case LENMOD_l: \
217 __buf = (signd) ? \
218 format_ld((val), (fmt_buf), (x)) : \
219 format_lu((val), (fmt_buf), (x)); \
220 break; \
221 ) \
222 IF_FMT_LENMOD_ll( \
223 case LENMOD_ll: \
224 __buf = (signd) ? \
225 format_lld((val), (fmt_buf), (x)) : \
226 format_llu((val), (fmt_buf), (x)); \
227 break; \
228 ) \
229 } \
230 __buf; \
231 })
232
233/* execute formatting branch for the compatible integer type */
234#define LENMOD_INTCOMPAT_BRANCH(inteqv, val, signd) \
235 ({ switch (inteqv) { \
236 case LENMOD_NONE: \
237 if (signd) { \
238 val_d = (val); \
239 goto branch_fmt_d; \
240 } \
241 else { \
242 val_u = (val); \
243 goto branch_fmt_u; \
244 } \
245 IF_FMT_LENMOD_l( \
246 case LENMOD_l: \
247 if (signd) { \
248 val_ld = (val); \
249 goto branch_fmt_ld; \
250 } \
251 else { \
252 val_lu = (val); \
253 goto branch_fmt_lu; \
254 } \
255 ) \
256 IF_FMT_LENMOD_ll( \
257 case LENMOD_ll: \
258 if (signd) { \
259 val_lld = (val); \
260 goto branch_fmt_lld; \
261 } \
262 else { \
263 val_llu = (val); \
264 goto branch_fmt_llu; \
265 } \
266 ) \
267 } \
268 })
269
270#define CONVERT_RADIX_10_SIGN(val, fmt_buf, p, signchar, type) \
271 do { \
272 if (val) { \
273 unsigned type v; \
274 \
275 if (val < 0) { \
276 v = (typeof (v))-(val + 1) + 1; \
277 signchar = '-'; \
278 } \
279 else { \
280 v = val; \
281 } \
282 \
283 do { \
284 *--p = (v % 10) + '0'; \
285 v /= 10; \
286 } while (v); \
287 } \
288 \
289 if (signchar) { \
290 p[-1] = signchar; \
291 fmt_buf->length = 1; \
292 break; \
293 } \
294 \
295 fmt_buf->length = 0; \
296 } while (0)
297
298#define CONVERT_RADIX_8(val, fmt_buf, p) \
299 do { \
300 if (val) { \
301 typeof (val) v = val; \
302 \
303 do { \
304 *--p = (v % 010) + '0'; \
305 v /= 010; \
306 } while (v); \
307 } \
308 \
309 if (fmt_buf->length) { \
310 *--p = '0'; \
311 fmt_buf->length = 0; \
312 } \
313 } while (0)
314
315#define CONVERT_RADIX_10(val, fmt_buf, p) \
316 do { \
317 if (val) { \
318 typeof (val) v = val; \
319 \
320 do { \
321 *--p = (v % 10) + '0'; \
322 v /= 10; \
323 } while (v); \
324 } \
325 \
326 fmt_buf->length = 0; \
327 } while (0)
328
329#define CONVERT_RADIX_16(val, fmt_buf, p, x) \
330 do { \
331 if (val) { \
332 const int h = x - 'X' - 0xA \
333 + 'A' - '0'; \
334 typeof (val) v = val; \
335 \
336 do { \
337 unsigned int d = v % 0x10; \
338 if (d >= 0xA) { \
339 d += h; \
340 } \
341 *--p = d + '0'; \
342 v /= 0x10; \
343 } while (v); \
344 \
345 if (fmt_buf->length) { \
346 p[-1] = x; \
347 p[-2] = '0'; \
348 fmt_buf->length = 2; \
349 break; \
350 } \
351 } \
352 \
353 fmt_buf->length = 0; \
354 } while (0)
355
356#define CONVERT_RADIX_NOSIGN(val, fmt_buf, p, x) \
357 switch (x) \
358 { \
359 IF_FMT_RADIX_o( case 'o': \
360 CONVERT_RADIX_8(val, fmt_buf, p); \
361 break; ) \
362 case 'u': \
363 CONVERT_RADIX_10(val, fmt_buf, p); \
364 break; \
365 IF_FMT_RADIX_x( default: \
366 CONVERT_RADIX_16(val, fmt_buf, p, x); \
367 break; ) \
368 }
369
370struct fmt_buf {
371 const char *fmt_start; /* second character of formatter after '%' */
372 size_t length; /* length of formatted text (non-numeric)
373 or prefix (numeric) */
374 char buf[24]; /* work buffer */
375 char bufend[1]; /* buffer end marker and guard '0' */
376};
377
378/* %d %i */
379static inline const char * format_d(int val,
380 struct fmt_buf *fmt_buf,
381 int signchar)
382{
383 char *p = fmt_buf->bufend;
384 CONVERT_RADIX_10_SIGN(val, fmt_buf, p, signchar, int);
385 return p;
386}
387
388/* %o %u %x %X */
389static inline const char * format_u(unsigned int val,
390 struct fmt_buf *fmt_buf,
391 int radixchar)
392{
393 char *p = fmt_buf->bufend;
394 CONVERT_RADIX_NOSIGN(val, fmt_buf, p, radixchar);
395 return p;
396}
397
398#if (FMT_LENMOD & FMT_LENMOD_l)
399#ifndef format_ld
400/* %ld %li */
401static inline const char * format_ld(long val,
402 struct fmt_buf *fmt_buf,
403 int signchar)
404{
405 char *p = fmt_buf->bufend;
406 CONVERT_RADIX_10_SIGN(val, fmt_buf, p, signchar, long);
407 return p;
408}
409#endif /* format_ld */
410
411#ifndef format_lu
412/* %lo %lu %lx %lX */
413static inline const char * format_lu(unsigned long val,
414 struct fmt_buf *fmt_buf,
415 int radixchar)
416{
417 char *p = fmt_buf->bufend;
418 CONVERT_RADIX_NOSIGN(val, fmt_buf, p, radixchar);
419 return p;
420}
421#endif /* format_lu */
422#endif /* FMT_LENMOD_l */
423
424#if (FMT_LENMOD & FMT_LENMOD_ll)
425#ifndef format_lld
426/* %lld %lli */
427static inline const char * format_lld(long long val,
428 struct fmt_buf *fmt_buf,
429 int signchar)
430{
431 char *p = fmt_buf->bufend;
432 CONVERT_RADIX_10_SIGN(val, fmt_buf, p, signchar, long long);
433 return p;
434}
435#endif /* format_lld */
436
437#ifndef format_llu
438/* %llo %llu %llx %llX */
439static inline const char * format_llu(unsigned long long val,
440 struct fmt_buf *fmt_buf,
441 int radixchar)
442{
443 char *p = fmt_buf->bufend;
444 CONVERT_RADIX_NOSIGN(val, fmt_buf, p, radixchar);
445 return p;
446}
447#endif /* format_llu */
448#endif /* FMT_LENMOD_ll */
449
450/* %c */
451static inline const char * format_c(int c,
452 struct fmt_buf *fmt_buf,
453 int lenmod)
454{
455 if (lenmod != LENMOD_NONE) {
456 return NULL; /* wchar_t support for now */
457 }
458
459 char *p = fmt_buf->bufend;
460 fmt_buf->length = 1;
461 *--p = (unsigned char)c;
462 return p;
463}
464
465/* %s */
466static inline const char * format_s(const void *str,
467 struct fmt_buf *fmt_buf,
468 int precision,
469 int lenmod)
470{
471 if (lenmod != LENMOD_NONE) {
472 return NULL; /* wchar_t support for now */
473 }
474
475 /* string length may be specified by precision instead of \0-
476 terminated; however, don't go past a \0 if one is there */
477 const char *s = str;
478 size_t len = precision >= 0 ? precision : -1;
479
480 const char *nil = memchr(s, '\0', len);
481 if (nil) {
482 len = nil - s;
483 }
484
485 fmt_buf->length = len;
486 return s;
487}
488
489#if (FMT_RADIX & FMT_RADIX_n)
490/* %n */
491static inline bool format_n(void *np,
492 int count,
493 int lenmod)
494{
495 if (lenmod != LENMOD_NONE) {
496 return false; /* int only for now */
497 }
498
499 *(int *)np = count;
500 return true;
501}
502#endif /* FMT_RADIX_n */
503
504#if (FMT_RADIX & FMT_RADIX_p)
505/* %p %P */
506static inline const char * format_p(const void *p,
507 struct fmt_buf *fmt_buf,
508 int radixchar,
509 bool *numericp)
510{
511 if (p) {
512 /* format as %#x or %#X */
513 *numericp = true;
514 radixchar -= 'P' - 'X';
515 fmt_buf->length = 2;
516 return LENMOD_INTCOMPAT_CALL(LENMOD_INTCOMPAT_SEL(uintptr_t, false),
517 (uintptr_t)p, fmt_buf, radixchar, false);
518 }
519 else {
520 /* format as %s */
521 fmt_buf->length = 5;
522 return "(nil)";
523 }
524}
525#endif /* FMT_RADIX_p */
526
527/* parse fixed width or precision field */
528static const char * parse_number_spec(const char *fmt,
529 int ch,
530 int *out)
531{
532 int i = ch - '0';
533
534 while (1) {
535 ch = *fmt - '0';
536
537 if (ch < 0 || ch > 9 || i > INT_MAX / 10 ||
538 (i == INT_MAX / 10 && ch > INT_MAX % 10)) {
539 break;
540 }
541
542 i = i * 10 + ch;
543 fmt++;
544 }
545
546 *out = i;
547 return fmt;
548}
549
550int vuprintf(vuprintf_push_cb push, /* call 'push()' for each output letter */
551 void *userp,
552 const char *fmt,
553 va_list ap)
554{
555 #define PUSHCHAR(ch) \
556 do { \
557 int __ch = (ch); \
558 int __rc = push(userp, __ch); \
559 count += __rc >= 0; \
560 if (__rc <= 0) { \
561 goto done; \
562 } \
563 } while (0)
564
565 int count = 0;
566 int ch;
567
568 /* macrofied identifiers share a variable with another */
569 unsigned int val_d;
570 unsigned int val_u;
571 #ifndef val_ld
572 unsigned long val_ld;
573 #endif
574 #ifndef val_lu
575 unsigned long val_lu;
576 #endif
577 #ifndef val_lld
578 unsigned long long val_lld;
579 #endif
580 #ifndef val_llu
581 unsigned long long val_llu;
582 #endif
583
584 struct fmt_buf fmt_buf;
585 fmt_buf.bufend[0] = '0';
586
587 while (1) {
588 while (1) {
589 if ((ch = *fmt++) == '\0') {
590 goto done;
591 }
592
593 if (ch == '%' && (ch = *fmt++) != '%') {
594 break;
595 }
596
597 PUSHCHAR(ch);
598 }
599
600 /* set to defaults */
601 fmt_buf.fmt_start = fmt;
602
603 int signchar = 0;
604 unsigned int width = 0;
605 int lenmod = LENMOD_NONE;
606 size_t length = 0;
607 size_t pfxlen = 0;
608 bool numeric = false;
609 int alignchar = '0' + 1;
610 int precision = -1;
611 const char *buf = NULL;
612
613 /*** flags ***/
614 while (1) {
615 switch (ch)
616 {
617 case ' ': /* <space> before non-negative value (signed conversion) */
618 case '+': /* '+' before non-negative value (signed conversion) */
619 /* '+' overrides ' ' */
620 if (ch > signchar) {
621 signchar = ch;
622 }
623 break;
624 case '-': /* left-justify in field */
625 case '0': /* zero-pad to fill field */
626 /* '-' overrides '0' */
627 if (ch < alignchar) {
628 alignchar = ch;
629 }
630 break;
631 case '#': /* number prefix (nonzero %o:'0' %x/%X:'0x') */
632 /* indicate; formatter updates with actual length */
633 pfxlen = 1;
634 break;
635 #if 0
636 case '\'': /* digit grouping (non-monetary) */
637 break;
638 #endif
639 default:
640 goto flags_done;
641 }
642
643 ch = *fmt++;
644 }
645 flags_done:
646
647 /*** width ***/
648 if (ch == '*') {
649 /* variable width */
650 int w = va_arg(ap, int);
651 if (w < 0) {
652 /* negative width is width with implied '-' */
653 width = (unsigned int)-(w + 1) + 1;
654 alignchar = '-';
655 }
656 else {
657 width = w;
658 }
659
660 ch = *fmt++;
661 }
662 else if (ch >= '1' && ch <= '9') {
663 /* fixed width */
664 fmt = parse_number_spec(fmt, ch, &width);
665 ch = *fmt++;
666 }
667
668 /*** precision ***/
669 if (ch == '.') {
670 ch = *fmt++;
671
672 if (ch == '*') {
673 /* variable precision; negative precision is ignored */
674 precision = va_arg (ap, int);
675 ch = *fmt++;
676 }
677 else if (ch >= '0' && ch <= '9') {
678 /* fixed precision */
679 fmt = parse_number_spec(fmt, ch, &precision);
680 ch = *fmt++;
681 }
682 }
683
684 /*** length modifier ***/
685 #if FMT_LENMOD
686 switch (ch)
687 {
688 #if (FMT_LENMOD & (FMT_LENMOD_h | FMT_LENMOD_hh))
689 case 'h':
690 #endif
691 #if (FMT_LENMOD & FMT_LENMOD_j)
692 case 'j':
693 #endif
694 #if (FMT_LENMOD & (FMT_LENMOD_l | FMT_LENMOD_ll))
695 case 'l':
696 #endif
697 #if (FMT_LENMOD & FMT_LENMOD_t)
698 case 't':
699 #endif
700 #if (FMT_LENMOD & FMT_LENMOD_z)
701 case 'z':
702 #endif
703 lenmod = ch;
704 ch = *fmt++;
705 #if (FMT_LENMOD & (FMT_LENMOD_hh | FMT_LENMOD_ll))
706 /* doesn't matter if jj, tt or zz happen; they will be rejected
707 by the radix handler */
708 if (ch == lenmod) {
709 lenmod = LENMOD2(lenmod, ch);
710 ch = *fmt++;
711 }
712 #endif
713 }
714 #endif /* FMT_LENMOD */
715
716 /*** radix ***/
717 switch (ch)
718 {
719 /** non-numeric **/
720 case 'c':
721 buf = format_c(va_arg(ap, int), &fmt_buf, lenmod);
722 break;
723 #if (FMT_RADIX & FMT_RADIX_n)
724 case 'n':
725 if (format_n(va_arg(ap, void *), count, lenmod)) {
726 continue; /* no output */
727 }
728 break;
729 #endif
730 case 's':
731 buf = format_s(va_arg(ap, const void *), &fmt_buf,
732 precision, lenmod);
733 break;
734
735 /** non-integer **/
736 #if (FMT_RADIX & FMT_RADIX_p)
737 case 'p':
738 case 'P':
739 buf = format_p(va_arg(ap, void *), &fmt_buf, ch,
740 &numeric);
741 break;
742 #endif
743
744 /** signed integer **/
745 case 'd':
746 case 'i':
747 fmt_buf.length = pfxlen;
748
749 switch (lenmod)
750 {
751 case LENMOD_NONE:
752 val_d = va_arg(ap, signed int);
753 goto branch_fmt_d;
754 #if (FMT_LENMOD & FMT_LENMOD_h)
755 case LENMOD_h:
756 val_d = (signed short)va_arg(ap, SSHRT_INT_ARG);
757 goto branch_fmt_d;
758 #endif
759 #if (FMT_LENMOD & FMT_LENMOD_hh)
760 case LENMOD_hh:
761 val_d = (signed char)va_arg(ap, SCHAR_INT_ARG);
762 goto branch_fmt_d;
763 #endif
764 #if (FMT_LENMOD & FMT_LENMOD_j)
765 case LENMOD_j:
766 LENMOD_INTCOMPAT_BRANCH(LENMOD_INTCOMPAT_SEL(intmax_t, true),
767 va_arg(ap, intmax_t), true);
768 #endif
769 #if (FMT_LENMOD & FMT_LENMOD_l)
770 case LENMOD_l:
771 val_ld = va_arg(ap, signed long);
772 goto branch_fmt_ld;
773 #endif
774 #if (FMT_LENMOD & FMT_LENMOD_ll)
775 case LENMOD_ll:
776 val_lld = va_arg(ap, signed long long);
777 goto branch_fmt_lld;
778 #endif
779 #if (FMT_LENMOD & FMT_LENMOD_t)
780 case LENMOD_t:
781 LENMOD_INTCOMPAT_BRANCH(LENMOD_INTCOMPAT_SEL(ptrdiff_t, true),
782 va_arg(ap, ptrdiff_t), true);
783 #endif
784 #if (FMT_LENMOD & FMT_LENMOD_z)
785 case LENMOD_z:
786 LENMOD_INTCOMPAT_BRANCH(LENMOD_INTCOMPAT_SEL(ssize_t, true),
787 va_arg(ap, ssize_t), true);
788 #endif
789 }
790
791 /* macrofied labels share a formatter with another */
792 if (0) {
793 branch_fmt_d:
794 buf = format_d(val_d, &fmt_buf, signchar);
795 } else if (0) {
796 #ifndef val_ld
797 branch_fmt_ld:
798 buf = format_ld(val_ld, &fmt_buf, signchar);
799 #endif
800 } else if (0) {
801 #ifndef val_lld
802 branch_fmt_lld:
803 buf = format_lld(val_lld, &fmt_buf, signchar);
804 #endif
805 }
806
807 numeric = true;
808 break;
809
810 /** unsigned integer **/
811 #if (FMT_RADIX & FMT_RADIX_o)
812 case 'o':
813 #endif
814 case 'u':
815 #if (FMT_RADIX & FMT_RADIX_x)
816 case 'x':
817 case 'X':
818 #endif
819 fmt_buf.length = pfxlen;
820
821 switch (lenmod)
822 {
823 case LENMOD_NONE:
824 val_u = va_arg(ap, unsigned int);
825 goto branch_fmt_u;
826 #if (FMT_LENMOD & FMT_LENMOD_h)
827 case LENMOD_h:
828 val_u = (unsigned short)va_arg(ap, USHRT_INT_ARG);
829 goto branch_fmt_u;
830 #endif
831 #if (FMT_LENMOD & FMT_LENMOD_hh)
832 case LENMOD_hh:
833 val_u = (unsigned char)va_arg(ap, UCHAR_INT_ARG);
834 goto branch_fmt_u;
835 #endif
836 #if (FMT_LENMOD & FMT_LENMOD_j)
837 case LENMOD_j:
838 LENMOD_INTCOMPAT_BRANCH(LENMOD_INTCOMPAT_SEL(uintmax_t, false),
839 va_arg(ap, uintmax_t), false);
840 #endif
841 #if (FMT_LENMOD & FMT_LENMOD_l)
842 case LENMOD_l:
843 val_lu = va_arg(ap, unsigned long);
844 goto branch_fmt_lu;
845 #endif
846 #if (FMT_LENMOD & FMT_LENMOD_ll)
847 case LENMOD_ll:
848 val_llu = va_arg(ap, unsigned long long);
849 goto branch_fmt_llu;
850 #endif
851 #if (FMT_LENMOD & (FMT_LENMOD_t | FMT_LENMOD_z))
852 /* format "uptrdiff_t" as size_t (unless it becomes standard) */
853 #if (FMT_LENMOD & FMT_LENMOD_t)
854 case LENMOD_t:
855 #endif
856 #if (FMT_LENMOD & FMT_LENMOD_z)
857 case LENMOD_z:
858 #endif
859 LENMOD_INTCOMPAT_BRANCH(LENMOD_INTCOMPAT_SEL(size_t, false),
860 va_arg(ap, size_t), false);
861 #endif
862 }
863
864 /* macrofied labels share a formatter with another */
865 if (0) {
866 branch_fmt_u:
867 buf = format_u(val_u, &fmt_buf, ch);
868 } else if (0) {
869 #ifndef val_lu
870 branch_fmt_lu:
871 buf = format_lu(val_lu, &fmt_buf, ch);
872 #endif
873 } else if (0) {
874 #ifndef val_llu
875 branch_fmt_llu:
876 buf = format_llu(val_llu, &fmt_buf, ch);
877 #endif
878 }
879
880 numeric = true;
881 break;
882 }
883
884 if (buf) {
885 /** padding **/
886 if (numeric) {
887 /* numeric formats into fmt_buf.buf */
888 pfxlen = fmt_buf.length;
889 length = fmt_buf.bufend - buf;
890
891 size_t size = pfxlen + length;
892
893 if (precision >= 0) {
894 /* explicit precision */
895 precision -= (int)length;
896
897 if (precision > 0) {
898 size += precision;
899 }
900
901 width -= MIN(width, size);
902 }
903 else {
904 /* default precision */
905 if (!length) {
906 length = 1;
907 size++;
908 }
909
910 width -= MIN(width, size);
911
912 if (alignchar == '0') {
913 /* width zero-fill */
914 precision = width;
915 width = 0;
916 }
917 }
918 }
919 else {
920 /* non-numeric: supress prefix and precision; keep length and
921 width */
922 pfxlen = 0;
923 precision = 0;
924 length = fmt_buf.length;
925 width -= MIN(width, length);
926 }
927 }
928 else {
929 /* format not accepted; print it literally */
930 buf = fmt_buf.fmt_start - 2;
931 length = fmt - buf;
932 width = 0;
933 pfxlen = 0;
934 precision = 0;
935 }
936
937 /** push all the stuff **/
938
939 if (alignchar != '-') {
940 /* left padding */
941 while (width > 0) {
942 PUSHCHAR(' ');
943 width--;
944 }
945 }
946
947 /* prefix */
948 while (pfxlen > 0) {
949 PUSHCHAR(buf[-pfxlen]);
950 pfxlen--;
951 }
952
953 /* 0-padding */
954 while (precision > 0) {
955 PUSHCHAR('0');
956 precision--;
957 }
958
959 /* field */
960 while (length > 0) {
961 PUSHCHAR(*buf++);
962 length--;
963 }
964
965 /* right padding */
966 while (width > 0) {
967 PUSHCHAR(' ');
968 width--;
969 }
970 }
971
972done:
973 return count;
974}
diff --git a/firmware/include/format.h b/firmware/include/vuprintf.h
index 30a072aca8..3876482fb2 100644
--- a/firmware/include/format.h
+++ b/firmware/include/vuprintf.h
@@ -19,19 +19,27 @@
19 * 19 *
20 ****************************************************************************/ 20 ****************************************************************************/
21 21
22#ifndef __FORMAT_H__ 22#ifndef __VUPRINTF_H__
23#define __FORMAT_H__ 23#define __VUPRINTF_H__
24 24
25void format( 25#include <stdarg.h>
26 /* call 'push()' for each output letter */
27 int (*push)(void *userp, unsigned char data),
28 void *userp,
29 const char *fmt,
30 va_list ap);
31 26
32/* callback function is called for every output character (byte) with userp and 27/* callback function is called for every output character (byte) in the
33 * should return 0 when ch is a char other than '\0' that should stop printing */ 28 * output with userp
34void vuprintf(int (*push)(void *userp, unsigned char data), 29 *
35 void *userp, const char *fmt, va_list ap); 30 * it must return > 0 to continue (increments counter)
31 * it may return 0 to stop (increments counter)
32 * it may return < 0 to stop (does not increment counter)
33 * a zero in the format string stops (does not increment counter)
34 *
35 * caller is reponsible for stopping formatting in order to keep the return
36 * value from overflowing (assuming they have a reason to care)
37 */
38typedef int (* vuprintf_push_cb)(void *userp, int c);
39
40/*
41 * returns the number of times push() was called and returned >= 0
42 */
43int vuprintf(vuprintf_push_cb push, void *userp, const char *fmt, va_list ap);
36 44
37#endif /* __FORMAT_H__ */ 45#endif /* __VUPRINTF_H__ */
diff --git a/firmware/libc/sprintf.c b/firmware/libc/sprintf.c
index 18e2ce6fd2..a56f454c34 100644
--- a/firmware/libc/sprintf.c
+++ b/firmware/libc/sprintf.c
@@ -18,74 +18,94 @@
18 * KIND, either express or implied. 18 * KIND, either express or implied.
19 * 19 *
20 ****************************************************************************/ 20 ****************************************************************************/
21
22/*
23 * Minimal printf and snprintf formatting functions
24 *
25 * These support %c %s %d and %x
26 * Field width and zero-padding flag only
27 */
28
29#include <stdio.h> 21#include <stdio.h>
30#include <stdarg.h>
31#include <stdbool.h>
32#include <limits.h> 22#include <limits.h>
33#include "format.h" 23#include <errno.h>
24#include "vuprintf.h"
34 25
35/* ALSA library requires a more advanced snprintf, so let's not 26/* ALSA library requires a more advanced snprintf, so let's not
36 override it in simulator for Linux. Note that Cygwin requires 27 override it in simulator for Linux. Note that Cygwin requires
37 our snprintf or it produces garbled output after a while. */ 28 our snprintf or it produces garbled output after a while. */
38 29
39struct for_snprintf { 30struct for_snprintf {
40 unsigned char *ptr; /* where to store it */ 31 char *ptr; /* where to store it */
41 size_t bytes; /* amount already stored */ 32 int rem; /* unwritten buffer remaining */
42 size_t max; /* max amount to store */
43}; 33};
44 34
45static int sprfunc(void *ptr, unsigned char letter) 35static int sprfunc(void *ptr, int letter)
46{ 36{
47 struct for_snprintf *pr = (struct for_snprintf *)ptr; 37 struct for_snprintf *pr = (struct for_snprintf *)ptr;
48 if(pr->bytes < pr->max) { 38
49 *pr->ptr = letter; 39 if (pr->rem > 0) {
50 pr->ptr++; 40 if (--pr->rem == 0) {
51 pr->bytes++; 41 return 0;
52 return true; 42 }
43
44 *pr->ptr++ = letter;
45 return 1;
53 } 46 }
54 return false; /* filled buffer */ 47 else {
55} 48 if (pr->rem == -INT_MAX) {
49 pr->rem = 1;
50 return -1;
51 }
56 52
53 --pr->rem;
54 return 1;
55 }
56}
57 57
58int snprintf(char *buf, size_t size, const char *fmt, ...) 58int vsnprintf(char *buf, size_t size, const char *fmt, va_list ap)
59{ 59{
60 va_list ap; 60 if (size <= INT_MAX) {
61 struct for_snprintf pr; 61 int bytes;
62 struct for_snprintf pr;
63
64 pr.ptr = buf;
65 pr.rem = size;
62 66
63 pr.ptr = (unsigned char *)buf; 67 bytes = vuprintf(sprfunc, &pr, fmt, ap);
64 pr.bytes = 0;
65 pr.max = size;
66 68
67 va_start(ap, fmt); 69 if (size) {
68 format(sprfunc, &pr, fmt, ap); 70 *pr.ptr = '\0';
69 va_end(ap); 71 }
72 else if (pr.rem > 0) {
73 goto overflow;
74 }
70 75
71 /* make sure it ends with a trailing zero */ 76 return bytes;
72 pr.ptr[(pr.bytes < pr.max) ? 0 : -1] = '\0'; 77 }
73 78
74 return pr.bytes; 79overflow:
80 errno = EOVERFLOW;
81 return -1;
75} 82}
76 83
77int vsnprintf(char *buf, size_t size, const char *fmt, va_list ap) 84int snprintf(char *buf, size_t size, const char *fmt, ...)
78{ 85{
79 struct for_snprintf pr; 86 if (size <= INT_MAX) {
87 int bytes;
88 struct for_snprintf pr;
89 va_list ap;
90
91 pr.ptr = buf;
92 pr.rem = size;
80 93
81 pr.ptr = (unsigned char *)buf; 94 va_start(ap, fmt);
82 pr.bytes = 0; 95 bytes = vuprintf(sprfunc, &pr, fmt, ap);
83 pr.max = size; 96 va_end(ap);
84 97
85 format(sprfunc, &pr, fmt, ap); 98 if (size) {
99 *pr.ptr = '\0';
100 }
101 else if (pr.rem > 0) {
102 goto overflow;
103 }
104
105 return bytes;
106 }
86 107
87 /* make sure it ends with a trailing zero */ 108overflow:
88 pr.ptr[(pr.bytes < pr.max) ? 0 : -1] = '\0'; 109 errno = EOVERFLOW;
89 110 return -1;
90 return pr.bytes;
91} 111}
diff --git a/firmware/logf.c b/firmware/logf.c
index bdc5ad9cc0..3f9bd36112 100644
--- a/firmware/logf.c
+++ b/firmware/logf.c
@@ -38,7 +38,7 @@
38#endif 38#endif
39#include "logf.h" 39#include "logf.h"
40#include "serial.h" 40#include "serial.h"
41#include "format.h" 41#include "vuprintf.h"
42 42
43#ifdef HAVE_USBSTACK 43#ifdef HAVE_USBSTACK
44#include "usb_core.h" 44#include "usb_core.h"
@@ -193,7 +193,7 @@ static void check_logfindex(void)
193 } 193 }
194} 194}
195 195
196static int logf_push(void *userp, unsigned char c) 196static int logf_push(void *userp, int c)
197{ 197{
198 (void)userp; 198 (void)userp;
199 199
@@ -210,7 +210,7 @@ static int logf_push(void *userp, unsigned char c)
210 } 210 }
211#endif 211#endif
212 212
213 return true; 213 return 1;
214} 214}
215 215
216void _logf(const char *fmt, ...) 216void _logf(const char *fmt, ...)
@@ -310,7 +310,7 @@ void logf_panic_dump(int *y)
310#endif 310#endif
311 311
312#ifdef ROCKBOX_HAS_LOGDISKF 312#ifdef ROCKBOX_HAS_LOGDISKF
313static int logdiskf_push(void *userp, unsigned char c) 313static int logdiskf_push(void *userp, int c)
314{ 314{
315 (void)userp; 315 (void)userp;
316 316
@@ -319,11 +319,11 @@ static int logdiskf_push(void *userp, unsigned char c)
319 { 319 {
320 strcpy(&logdiskfbuffer[logdiskfindex-8], "LOGFULL"); 320 strcpy(&logdiskfbuffer[logdiskfindex-8], "LOGFULL");
321 logdiskfindex=MAX_LOGDISKF_SIZE; 321 logdiskfindex=MAX_LOGDISKF_SIZE;
322 return false; 322 return 0;
323 } 323 }
324 logdiskfbuffer[logdiskfindex++] = c; 324 logdiskfbuffer[logdiskfindex++] = c;
325 325
326 return true; 326 return 1;
327} 327}
328 328
329static void flush_buffer(void); 329static void flush_buffer(void);
diff --git a/firmware/target/arm/s3c2440/uart-s3c2440.c b/firmware/target/arm/s3c2440/uart-s3c2440.c
index e9c9345103..47f11a92b6 100644
--- a/firmware/target/arm/s3c2440/uart-s3c2440.c
+++ b/firmware/target/arm/s3c2440/uart-s3c2440.c
@@ -60,7 +60,7 @@ void tx_writec(unsigned char c)
60} 60}
61 61
62 62
63static int uart_push(void *user_data, unsigned char ch) 63static int uart_push(void *user_data, int ch)
64{ 64{
65 (void)user_data; 65 (void)user_data;
66 66