1 /*------------------------------------------------------------------------/
\r
2 / Universal string handler for user console interface
\r
3 /-------------------------------------------------------------------------/
\r
5 / Copyright (C) 2011, ChaN, all right reserved.
\r
7 / * This software is a free software and there is NO WARRANTY.
\r
8 / * No restriction on use. You can use, modify and redistribute it for
\r
9 / personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY.
\r
10 / * Redistributions of source code must retain the above copyright notice.
\r
12 /-------------------------------------------------------------------------*/
\r
14 #include "xprintf.h"
\r
19 void (*xfunc_out)(unsigned char); /* Pointer to the output stream */
\r
20 static char *outptr;
\r
22 /*----------------------------------------------*/
\r
23 /* Put a character */
\r
24 /*----------------------------------------------*/
\r
28 if (_CR_CRLF && c == '\n') xputc('\r'); /* CR -> CRLF */
\r
31 *outptr++ = (unsigned char)c;
\r
35 if (xfunc_out) xfunc_out((unsigned char)c);
\r
40 /*----------------------------------------------*/
\r
41 /* Put a null-terminated string */
\r
42 /*----------------------------------------------*/
\r
44 void xputs ( /* Put a string to the default device */
\r
45 const char* str /* Pointer to the string */
\r
53 void xfputs ( /* Put a string to the specified device */
\r
54 void(*func)(unsigned char), /* Pointer to the output function */
\r
55 const char* str /* Pointer to the string */
\r
58 void (*pf)(unsigned char);
\r
61 pf = xfunc_out; /* Save current output device */
\r
62 xfunc_out = func; /* Switch output to specified device */
\r
63 while (*str) /* Put the string */
\r
65 xfunc_out = pf; /* Restore output device */
\r
70 /*----------------------------------------------*/
\r
71 /* Formatted string output */
\r
72 /*----------------------------------------------*/
\r
73 /* xprintf("%d", 1234); "1234"
\r
74 xprintf("%6d,%3d%%", -200, 5); " -200, 5%"
\r
75 xprintf("%-6u", 100); "100 "
\r
76 xprintf("%ld", 12345678L); "12345678"
\r
77 xprintf("%04x", 0xA3); "00a3"
\r
78 xprintf("%08LX", 0x123ABC); "00123ABC"
\r
79 xprintf("%016b", 0x550F); "0101010100001111"
\r
80 xprintf("%s", "String"); "String"
\r
81 xprintf("%-4s", "abc"); "abc "
\r
82 xprintf("%4s", "abc"); " abc"
\r
83 xprintf("%c", 'a'); "a"
\r
84 xprintf("%f", 10.0); <xprintf lacks floating point support>
\r
89 const char* fmt, /* Pointer to the format string */
\r
90 va_list arp /* Pointer to arguments */
\r
93 unsigned int r, i, j, w, f;
\r
95 char s[16], c, d, *p;
\r
99 c = *fmt++; /* Get a char */
\r
100 if (!c) break; /* End of format? */
\r
101 if (c != '%') { /* Pass through it if not a % sequense */
\r
102 xputc(c); continue;
\r
105 c = *fmt++; /* Get first char of the sequense */
\r
106 if (c == '0') { /* Flag: '0' padded */
\r
109 if (c == '-') { /* Flag: left justified */
\r
113 for (w = 0; c >= '0' && c <= '9'; c = *fmt++) /* Minimum width */
\r
114 w = w * 10 + c - '0';
\r
115 if (c == 'l' || c == 'L') { /* Prefix: Size is long int */
\r
116 f |= 4; c = *fmt++;
\r
118 if (!c) break; /* End of format? */
\r
120 if (d >= 'a') d -= 0x20;
\r
121 switch (d) { /* Type is... */
\r
122 case 'S' : /* String */
\r
123 p = va_arg(arp, char*);
\r
124 for (j = 0; p[j]; j++) ;
\r
125 while (!(f & 2) && j++ < w) xputc(' ');
\r
127 while (j++ < w) xputc(' ');
\r
129 case 'C' : /* Character */
\r
130 xputc((char)va_arg(arp, int)); continue;
\r
131 case 'B' : /* Binary */
\r
133 case 'O' : /* Octal */
\r
135 case 'D' : /* Signed decimal */
\r
136 case 'U' : /* Unsigned decimal */
\r
138 case 'X' : /* Hexdecimal */
\r
140 default: /* Unknown type (passthrough) */
\r
141 xputc(c); continue;
\r
144 /* Get an argument and put it in numeral */
\r
145 v = (f & 4) ? va_arg(arp, long) : ((d == 'D') ? (long)va_arg(arp, int) : (long)va_arg(arp, unsigned int));
\r
146 if (d == 'D' && (v & 0x80000000)) {
\r
152 d = (char)(v % r); v /= r;
\r
153 if (d > 9) d += (c == 'x') ? 0x27 : 0x07;
\r
155 } while (v && i < sizeof(s));
\r
156 if (f & 8) s[i++] = '-';
\r
157 j = i; d = (f & 1) ? '0' : ' ';
\r
158 while (!(f & 2) && j++ < w) xputc(d);
\r
159 do xputc(s[--i]); while(i);
\r
160 while (j++ < w) xputc(' ');
\r
165 void xprintf ( /* Put a formatted string to the default device */
\r
166 const char* fmt, /* Pointer to the format string */
\r
167 ... /* Optional arguments */
\r
173 va_start(arp, fmt);
\r
174 xvprintf(fmt, arp);
\r
179 void xsprintf ( /* Put a formatted string to the memory */
\r
180 char* buff, /* Pointer to the output buffer */
\r
181 const char* fmt, /* Pointer to the format string */
\r
182 ... /* Optional arguments */
\r
188 outptr = buff; /* Switch destination for memory */
\r
190 va_start(arp, fmt);
\r
191 xvprintf(fmt, arp);
\r
194 *outptr = 0; /* Terminate output string with a \0 */
\r
195 outptr = 0; /* Switch destination for device */
\r
199 void xfprintf ( /* Put a formatted string to the specified device */
\r
200 void(*func)(unsigned char), /* Pointer to the output function */
\r
201 const char* fmt, /* Pointer to the format string */
\r
202 ... /* Optional arguments */
\r
206 void (*pf)(unsigned char);
\r
209 pf = xfunc_out; /* Save current output device */
\r
210 xfunc_out = func; /* Switch output to specified device */
\r
212 va_start(arp, fmt);
\r
213 xvprintf(fmt, arp);
\r
216 xfunc_out = pf; /* Restore output device */
\r
221 /*----------------------------------------------*/
\r
222 /* Dump a line of binary dump */
\r
223 /*----------------------------------------------*/
\r
226 const void* buff, /* Pointer to the array to be dumped */
\r
227 unsigned long addr, /* Heading address value */
\r
228 int len, /* Number of items to be dumped */
\r
229 int width /* Size of the items (DF_CHAR, DF_SHORT, DF_LONG) */
\r
233 const unsigned char *bp;
\r
234 const unsigned short *sp;
\r
235 const unsigned long *lp;
\r
238 xprintf("%08lX ", addr); /* address */
\r
243 for (i = 0; i < len; i++) /* Hexdecimal dump */
\r
244 xprintf(" %02X", bp[i]);
\r
246 for (i = 0; i < len; i++) /* ASCII dump */
\r
247 xputc((bp[i] >= ' ' && bp[i] <= '~') ? bp[i] : '.');
\r
251 do /* Hexdecimal dump */
\r
252 xprintf(" %04X", *sp++);
\r
257 do /* Hexdecimal dump */
\r
258 xprintf(" %08LX", *lp++);
\r
266 #endif /* _USE_XFUNC_OUT */
\r
271 unsigned char (*xfunc_in)(void); /* Pointer to the input stream */
\r
273 /*----------------------------------------------*/
\r
274 /* Get a line from the input */
\r
275 /*----------------------------------------------*/
\r
277 int xgets ( /* 0:End of stream, 1:A line arrived */
\r
278 char* buff, /* Pointer to the buffer */
\r
279 int len /* Buffer length */
\r
285 if (!xfunc_in) return 0; /* No input function specified */
\r
289 c = xfunc_in(); /* Get a char from the incoming stream */
\r
290 if (!c) return 0; /* End of stream? */
\r
291 if (c == '\r') break; /* End of line? */
\r
292 if (c == '\b' && i) { /* Back space? */
\r
294 if (_LINE_ECHO) xputc(c);
\r
297 if (c >= ' ' && i < len - 1) { /* Visible chars */
\r
299 if (_LINE_ECHO) xputc(c);
\r
302 buff[i] = 0; /* Terminate with a \0 */
\r
303 if (_LINE_ECHO) xputc('\n');
\r
308 int xfgets ( /* 0:End of stream, 1:A line arrived */
\r
309 unsigned char (*func)(void), /* Pointer to the input stream function */
\r
310 char* buff, /* Pointer to the buffer */
\r
311 int len /* Buffer length */
\r
314 unsigned char (*pf)(void);
\r
318 pf = xfunc_in; /* Save current input device */
\r
319 xfunc_in = func; /* Switch input to specified device */
\r
320 n = xgets(buff, len); /* Get a line */
\r
321 xfunc_in = pf; /* Restore input device */
\r
327 /*----------------------------------------------*/
\r
328 /* Get a value of the string */
\r
329 /*----------------------------------------------*/
\r
330 /* "123 -5 0x3ff 0b1111 0377 w "
\r
331 ^ 1st call returns 123 and next ptr
\r
332 ^ 2nd call returns -5 and next ptr
\r
333 ^ 3rd call returns 1023 and next ptr
\r
334 ^ 4th call returns 15 and next ptr
\r
335 ^ 5th call returns 255 and next ptr
\r
336 ^ 6th call fails and returns 0
\r
339 int xatoi ( /* 0:Failed, 1:Successful */
\r
340 char **str, /* Pointer to pointer to the string */
\r
341 long *res /* Pointer to the valiable to store the value */
\r
345 unsigned char c, r, s = 0;
\r
350 while ((c = **str) == ' ') (*str)++; /* Skip leading spaces */
\r
352 if (c == '-') { /* negative? */
\r
360 case 'x': /* hexdecimal */
\r
361 r = 16; c = *(++(*str));
\r
363 case 'b': /* binary */
\r
364 r = 2; c = *(++(*str));
\r
367 if (c <= ' ') return 1; /* single zero */
\r
368 if (c < '0' || c > '9') return 0; /* invalid char */
\r
372 if (c < '0' || c > '9') return 0; /* EOL or invalid char */
\r
373 r = 10; /* decimal */
\r
378 if (c >= 'a') c -= 0x20;
\r
382 if (c <= 9) return 0; /* invalid char */
\r
384 if (c >= r) return 0; /* invalid char for current radix */
\r
388 if (s) val = 0 - val; /* apply sign if needed */
\r
394 #endif /* _USE_XFUNC_IN */
\r