OSDN Git Service

チケット #30493 , チケット #30494 , チケット #30502
[uzume/uzume_bfin.git] / uzumeapp / kernel / uzume / ntshell / xprintf.c
1 /*------------------------------------------------------------------------/\r
2   /  Universal string handler for user console interface\r
3   /-------------------------------------------------------------------------/\r
4   /\r
5   /  Copyright (C) 2011, ChaN, all right reserved.\r
6   /\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
11   /\r
12   /-------------------------------------------------------------------------*/\r
13 \r
14 #include "xprintf.h"\r
15 \r
16 \r
17 #if _USE_XFUNC_OUT\r
18 #include <stdarg.h>\r
19 void (*xfunc_out)(unsigned char); /* Pointer to the output stream */\r
20 static char *outptr;\r
21 \r
22 /*----------------------------------------------*/\r
23 /* Put a character                              */\r
24 /*----------------------------------------------*/\r
25 \r
26 void xputc (char c)\r
27 {\r
28     if (_CR_CRLF && c == '\n') xputc('\r');  /* CR -> CRLF */\r
29 \r
30     if (outptr) {\r
31         *outptr++ = (unsigned char)c;\r
32         return;\r
33     }\r
34 \r
35     if (xfunc_out) xfunc_out((unsigned char)c);\r
36 }\r
37 \r
38 \r
39 \r
40 /*----------------------------------------------*/\r
41 /* Put a null-terminated string                 */\r
42 /*----------------------------------------------*/\r
43 \r
44 void xputs (     /* Put a string to the default device */\r
45         const char* str    /* Pointer to the string */\r
46         )\r
47 {\r
48     while (*str)\r
49         xputc(*str++);\r
50 }\r
51 \r
52 \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
56             )\r
57 {\r
58     void (*pf)(unsigned char);\r
59 \r
60 \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
64         xputc(*str++);\r
65     xfunc_out = pf;  /* Restore output device */\r
66 }\r
67 \r
68 \r
69 \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
85     */\r
86 \r
87     static\r
88 void xvprintf (\r
89         const char* fmt, /* Pointer to the format string */\r
90         va_list arp   /* Pointer to arguments */\r
91         )\r
92 {\r
93     unsigned int r, i, j, w, f;\r
94     unsigned long v;\r
95     char s[16], c, d, *p;\r
96 \r
97 \r
98     for (;;) {\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
103         }\r
104         f = 0;\r
105         c = *fmt++;     /* Get first char of the sequense */\r
106         if (c == '0') {    /* Flag: '0' padded */\r
107             f = 1; c = *fmt++;\r
108         } else {\r
109             if (c == '-') {   /* Flag: left justified */\r
110                 f = 2; c = *fmt++;\r
111             }\r
112         }\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
117         }\r
118         if (!c) break;    /* End of format? */\r
119         d = c;\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
126                 xputs(p);\r
127                 while (j++ < w) xputc(' ');\r
128                 continue;\r
129             case 'C' :     /* Character */\r
130                 xputc((char)va_arg(arp, int)); continue;\r
131             case 'B' :     /* Binary */\r
132                 r = 2; break;\r
133             case 'O' :     /* Octal */\r
134                 r = 8; break;\r
135             case 'D' :     /* Signed decimal */\r
136             case 'U' :     /* Unsigned decimal */\r
137                 r = 10; break;\r
138             case 'X' :     /* Hexdecimal */\r
139                 r = 16; break;\r
140             default:     /* Unknown type (passthrough) */\r
141                 xputc(c); continue;\r
142         }\r
143 \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
147             v = 0 - v;\r
148             f |= 8;\r
149         }\r
150         i = 0;\r
151         do {\r
152             d = (char)(v % r); v /= r;\r
153             if (d > 9) d += (c == 'x') ? 0x27 : 0x07;\r
154             s[i++] = d + '0';\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
161     }\r
162 }\r
163 \r
164 \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
168         )\r
169 {\r
170     va_list arp;\r
171 \r
172 \r
173     va_start(arp, fmt);\r
174     xvprintf(fmt, arp);\r
175     va_end(arp);\r
176 }\r
177 \r
178 \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
183         )\r
184 {\r
185     va_list arp;\r
186 \r
187 \r
188     outptr = buff;  /* Switch destination for memory */\r
189 \r
190     va_start(arp, fmt);\r
191     xvprintf(fmt, arp);\r
192     va_end(arp);\r
193 \r
194     *outptr = 0;  /* Terminate output string with a \0 */\r
195     outptr = 0;   /* Switch destination for device */\r
196 }\r
197 \r
198 \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
203             )\r
204 {\r
205     va_list arp;\r
206     void (*pf)(unsigned char);\r
207 \r
208 \r
209     pf = xfunc_out;  /* Save current output device */\r
210     xfunc_out = func; /* Switch output to specified device */\r
211 \r
212     va_start(arp, fmt);\r
213     xvprintf(fmt, arp);\r
214     va_end(arp);\r
215 \r
216     xfunc_out = pf;  /* Restore output device */\r
217 }\r
218 \r
219 \r
220 \r
221 /*----------------------------------------------*/\r
222 /* Dump a line of binary dump                   */\r
223 /*----------------------------------------------*/\r
224 \r
225 void put_dump (\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
230         )\r
231 {\r
232     int i;\r
233     const unsigned char *bp;\r
234     const unsigned short *sp;\r
235     const unsigned long *lp;\r
236 \r
237 \r
238     xprintf("%08lX ", addr);  /* address */\r
239 \r
240     switch (width) {\r
241         case DW_CHAR:\r
242             bp = buff;\r
243             for (i = 0; i < len; i++)  /* Hexdecimal dump */\r
244                 xprintf(" %02X", bp[i]);\r
245             xputc(' ');\r
246             for (i = 0; i < len; i++)  /* ASCII dump */\r
247                 xputc((bp[i] >= ' ' && bp[i] <= '~') ? bp[i] : '.');\r
248             break;\r
249         case DW_SHORT:\r
250             sp = buff;\r
251             do        /* Hexdecimal dump */\r
252                 xprintf(" %04X", *sp++);\r
253             while (--len);\r
254             break;\r
255         case DW_LONG:\r
256             lp = buff;\r
257             do        /* Hexdecimal dump */\r
258                 xprintf(" %08LX", *lp++);\r
259             while (--len);\r
260             break;\r
261     }\r
262 \r
263     xputc('\n');\r
264 }\r
265 \r
266 #endif /* _USE_XFUNC_OUT */\r
267 \r
268 \r
269 \r
270 #if _USE_XFUNC_IN\r
271 unsigned char (*xfunc_in)(void); /* Pointer to the input stream */\r
272 \r
273 /*----------------------------------------------*/\r
274 /* Get a line from the input                    */\r
275 /*----------------------------------------------*/\r
276 \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
280         )\r
281 {\r
282     int c, i;\r
283 \r
284 \r
285     if (!xfunc_in) return 0;  /* No input function specified */\r
286 \r
287     i = 0;\r
288     for (;;) {\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
293             i--;\r
294             if (_LINE_ECHO) xputc(c);\r
295             continue;\r
296         }\r
297         if (c >= ' ' && i < len - 1) { /* Visible chars */\r
298             buff[i++] = c;\r
299             if (_LINE_ECHO) xputc(c);\r
300         }\r
301     }\r
302     buff[i] = 0; /* Terminate with a \0 */\r
303     if (_LINE_ECHO) xputc('\n');\r
304     return 1;\r
305 }\r
306 \r
307 \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
312             )\r
313 {\r
314     unsigned char (*pf)(void);\r
315     int n;\r
316 \r
317 \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
322 \r
323     return n;\r
324 }\r
325 \r
326 \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
337    */\r
338 \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
342         )\r
343 {\r
344     unsigned long val;\r
345     unsigned char c, r, s = 0;\r
346 \r
347 \r
348     *res = 0;\r
349 \r
350     while ((c = **str) == ' ') (*str)++; /* Skip leading spaces */\r
351 \r
352     if (c == '-') {  /* negative? */\r
353         s = 1;\r
354         c = *(++(*str));\r
355     }\r
356 \r
357     if (c == '0') {\r
358         c = *(++(*str));\r
359         switch (c) {\r
360             case 'x':  /* hexdecimal */\r
361                 r = 16; c = *(++(*str));\r
362                 break;\r
363             case 'b':  /* binary */\r
364                 r = 2; c = *(++(*str));\r
365                 break;\r
366             default:\r
367                 if (c <= ' ') return 1; /* single zero */\r
368                 if (c < '0' || c > '9') return 0; /* invalid char */\r
369                 r = 8;  /* octal */\r
370         }\r
371     } else {\r
372         if (c < '0' || c > '9') return 0; /* EOL or invalid char */\r
373         r = 10;   /* decimal */\r
374     }\r
375 \r
376     val = 0;\r
377     while (c > ' ') {\r
378         if (c >= 'a') c -= 0x20;\r
379         c -= '0';\r
380         if (c >= 17) {\r
381             c -= 7;\r
382             if (c <= 9) return 0; /* invalid char */\r
383         }\r
384         if (c >= r) return 0;  /* invalid char for current radix */\r
385         val = val * r + c;\r
386         c = *(++(*str));\r
387     }\r
388     if (s) val = 0 - val;   /* apply sign if needed */\r
389 \r
390     *res = val;\r
391     return 1;\r
392 }\r
393 \r
394 #endif /* _USE_XFUNC_IN */\r
395 \r