3 * @author Shinichiro Nakamura
4 * @brief Natural Tiny Standard I/O Module
6 * The Natural Tiny Standard I/O Module based on xprintf by ChaN.
7 * xprintf is a universal string handler for user console interface.
10 /*------------------------------------------------------------------------/
11 / Universal string handler for user console interface
12 /-------------------------------------------------------------------------/
14 / Copyright (C) 2011, ChaN, all right reserved.
16 / * This software is a free software and there is NO WARRANTY.
17 / * No restriction on use. You can use, modify and redistribute it for
18 / personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY.
19 / * Redistributions of source code must retain the above copyright notice.
21 /-------------------------------------------------------------------------*/
24 * ===============================================================
25 * Natural Tiny Standard I/O Module
26 * ===============================================================
27 * Copyright (c) 2013 Shinichiro Nakamura
29 * Permission is hereby granted, free of charge, to any person
30 * obtaining a copy of this software and associated documentation
31 * files (the "Software"), to deal in the Software without
32 * restriction, including without limitation the rights to use,
33 * copy, modify, merge, publish, distribute, sublicense, and/or
34 * sell copies of the Software, and to permit persons to whom the
35 * Software is furnished to do so, subject to the following
38 * The above copyright notice and this permission notice shall be
39 * included in all copies or substantial portions of the Software.
41 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
42 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
43 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
44 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
45 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
46 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
47 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
48 * OTHER DEALINGS IN THE SOFTWARE.
49 * ===============================================================
55 #define FLAG_ZERO_PADDED (1 << 0)
56 #define FLAG_LEFT_JUSTIFIED (1 << 1)
57 #define FLAG_SIZE_LONG_INT (1 << 2)
58 #define FLAG_SIGNED_DECIMAL (1 << 3)
61 * ntstdio_printf("%d", 1234); "1234"
62 * ntstdio_printf("%6d,%3d%%", -200, 5); " -200, 5%"
63 * ntstdio_printf("%-6u", 100); "100 "
64 * ntstdio_printf("%ld", 12345678L); "12345678"
65 * ntstdio_printf("%04x", 0xA3); "00a3"
66 * ntstdio_printf("%08LX", 0x123ABC); "00123ABC"
67 * ntstdio_printf("%016b", 0x550F); "0101010100001111"
68 * ntstdio_printf("%s", "String"); "String"
69 * ntstdio_printf("%-4s", "abc"); "abc "
70 * ntstdio_printf("%4s", "abc"); " abc"
71 * ntstdio_printf("%c", 'a'); "a"
72 * ntstdio_printf("%f", 10.0); <ntstdio_printf lacks floating point support>
75 static void xvprintf(ntstdio_t *handle, const char *fmt, va_list arp)
78 unsigned int flag, radix, width;
95 * Pass through it if not a % sequense
97 ntstdio_putc(handle, c);
107 * Get the first character of the sequense.
111 flag = FLAG_ZERO_PADDED;
115 flag = FLAG_LEFT_JUSTIFIED;
120 * Calculate the minimum width.
122 for (width = 0; (c >= '0') && (c <= '9'); c = *fmt++) {
123 width = (width * 10) + (c - '0');
125 if ((c == 'l') || (c == 'L')) {
126 flag |= FLAG_SIZE_LONG_INT;
143 p = va_arg(arp, char*);
144 for (j = 0; p[j]; j++) {
146 while (!(flag & FLAG_LEFT_JUSTIFIED) && (j++ < width)) {
147 ntstdio_putc(handle, ' ');
149 ntstdio_puts(handle, p);
150 while (j++ < width) {
151 ntstdio_putc(handle, ' ');
156 ntstdio_putc(handle, (char)va_arg(arp, int));
171 /* Unsigned decimal */
179 /* Unknown type (passthrough) */
180 ntstdio_putc(handle, c);
185 * Get an argument and put it in numeral.
187 value = (flag & FLAG_SIZE_LONG_INT) ? va_arg(arp, long) : ((d == 'D') ? (long)va_arg(arp, int) : (long)va_arg(arp, unsigned int));
188 if ((d == 'D') && (value & 0x80000000)) {
190 flag |= FLAG_SIGNED_DECIMAL;
194 d = (char)(value % radix);
197 d += (c == 'x') ? 0x27 : 0x07;
200 } while (value && (i < sizeof(s)));
201 if (flag & FLAG_SIGNED_DECIMAL) {
205 d = (flag & FLAG_ZERO_PADDED) ? '0' : ' ';
206 while (!(flag & FLAG_LEFT_JUSTIFIED) && (j++ < width)) {
207 ntstdio_putc(handle, d);
210 ntstdio_putc(handle, s[--i]);
212 while (j++ < width) {
213 ntstdio_putc(handle, ' ');
218 void ntstdio_init(ntstdio_t *handle, unsigned int option, NTSTDIO_XI xi, NTSTDIO_XO xo)
223 handle->option = option;
226 void ntstdio_putc(ntstdio_t *handle, char c)
228 if ((handle->option & NTSTDIO_OPTION_CR_CRLF) && (c == '\n')) {
229 ntstdio_putc(handle, '\r');
232 if (handle->outptr) {
233 *(handle->outptr)++ = (unsigned char)c;
238 handle->xo((unsigned char)c);
242 void ntstdio_puts(ntstdio_t *handle, const char *str)
245 ntstdio_putc(handle, *str++);
249 void ntstdio_fputs(ntstdio_t *handle, NTSTDIO_XO xo, const char *str)
251 void (*pf)(unsigned char);
253 /* Save current output device */
255 /* Switch output to specified device */
259 ntstdio_putc(handle, *str++);
262 /* Restore output device */
266 void ntstdio_printf(ntstdio_t *handle, const char *fmt, ...)
270 xvprintf(handle, fmt, arp);
274 void ntstdio_sprintf(ntstdio_t *handle, char *buf, const char *fmt, ...)
277 /* Switch destination for memory */
278 handle->outptr = buf;
280 xvprintf(handle, fmt, arp);
283 /* Terminate output string with a \0 */
284 *(handle->outptr) = 0;
285 /* Switch destination for device */
289 void ntstdio_fprintf(ntstdio_t *handle, NTSTDIO_XO xo, const char *fmt, ...)
292 void (*pf)(unsigned char);
294 /* Save current output device */
296 /* Switch output to specified device */
300 xvprintf(handle, fmt, arp);
303 /* Restore output device */
307 /* 0:End of stream, 1:A line arrived */
308 int ntstdio_gets(ntstdio_t *handle, char *buf, int len)
313 /* No input function specified */
319 /* Get a char from the incoming stream */
329 if ((c == '\b') && i) {
332 if (handle->option & NTSTDIO_OPTION_LINE_ECHO) {
333 ntstdio_putc(handle, c);
337 if ((c >= ' ') && (i < len - 1)) {
340 if (handle->option & NTSTDIO_OPTION_LINE_ECHO) {
341 ntstdio_putc(handle, c);
346 /* Terminate with a \0 */
347 if (handle->option & NTSTDIO_OPTION_LINE_ECHO) {
348 ntstdio_putc(handle, '\n');
353 /* 0:End of stream, 1:A line arrived */
354 int ntstdio_fgets(ntstdio_t *handle, NTSTDIO_XI xi, char *buf, int len)
356 unsigned char (*pf)(void);
359 /* Save current input device */
361 /* Switch input to specified device */
364 n = ntstdio_gets(handle, buf, len);
365 /* Restore input device */