OSDN Git Service

チケット #30491 Natural Tiny Shell (NT-Shell)の追加を実施。
[uzume/uzume_bfin.git] / uzumeapp / kernel / uzume / ntshell / xprintf.c
diff --git a/uzumeapp/kernel/uzume/ntshell/xprintf.c b/uzumeapp/kernel/uzume/ntshell/xprintf.c
new file mode 100644 (file)
index 0000000..fde70b2
--- /dev/null
@@ -0,0 +1,395 @@
+/*------------------------------------------------------------------------/\r
+  /  Universal string handler for user console interface\r
+  /-------------------------------------------------------------------------/\r
+  /\r
+  /  Copyright (C) 2011, ChaN, all right reserved.\r
+  /\r
+  / * This software is a free software and there is NO WARRANTY.\r
+  / * No restriction on use. You can use, modify and redistribute it for\r
+  /   personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY.\r
+  / * Redistributions of source code must retain the above copyright notice.\r
+  /\r
+  /-------------------------------------------------------------------------*/\r
+\r
+#include "xprintf.h"\r
+\r
+\r
+#if _USE_XFUNC_OUT\r
+#include <stdarg.h>\r
+void (*xfunc_out)(unsigned char); /* Pointer to the output stream */\r
+static char *outptr;\r
+\r
+/*----------------------------------------------*/\r
+/* Put a character                              */\r
+/*----------------------------------------------*/\r
+\r
+void xputc (char c)\r
+{\r
+    if (_CR_CRLF && c == '\n') xputc('\r');  /* CR -> CRLF */\r
+\r
+    if (outptr) {\r
+        *outptr++ = (unsigned char)c;\r
+        return;\r
+    }\r
+\r
+    if (xfunc_out) xfunc_out((unsigned char)c);\r
+}\r
+\r
+\r
+\r
+/*----------------------------------------------*/\r
+/* Put a null-terminated string                 */\r
+/*----------------------------------------------*/\r
+\r
+void xputs (     /* Put a string to the default device */\r
+        const char* str    /* Pointer to the string */\r
+        )\r
+{\r
+    while (*str)\r
+        xputc(*str++);\r
+}\r
+\r
+\r
+    void xfputs (     /* Put a string to the specified device */\r
+            void(*func)(unsigned char), /* Pointer to the output function */\r
+            const char* str    /* Pointer to the string */\r
+            )\r
+{\r
+    void (*pf)(unsigned char);\r
+\r
+\r
+    pf = xfunc_out;  /* Save current output device */\r
+    xfunc_out = func; /* Switch output to specified device */\r
+    while (*str)  /* Put the string */\r
+        xputc(*str++);\r
+    xfunc_out = pf;  /* Restore output device */\r
+}\r
+\r
+\r
+\r
+/*----------------------------------------------*/\r
+/* Formatted string output                      */\r
+/*----------------------------------------------*/\r
+/*  xprintf("%d", 1234);   "1234"\r
+    xprintf("%6d,%3d%%", -200, 5); "  -200,  5%"\r
+    xprintf("%-6u", 100);   "100   "\r
+    xprintf("%ld", 12345678L);  "12345678"\r
+    xprintf("%04x", 0xA3);   "00a3"\r
+    xprintf("%08LX", 0x123ABC);  "00123ABC"\r
+    xprintf("%016b", 0x550F);  "0101010100001111"\r
+    xprintf("%s", "String");  "String"\r
+    xprintf("%-4s", "abc");   "abc "\r
+    xprintf("%4s", "abc");   " abc"\r
+    xprintf("%c", 'a');    "a"\r
+    xprintf("%f", 10.0);            <xprintf lacks floating point support>\r
+    */\r
+\r
+    static\r
+void xvprintf (\r
+        const char* fmt, /* Pointer to the format string */\r
+        va_list arp   /* Pointer to arguments */\r
+        )\r
+{\r
+    unsigned int r, i, j, w, f;\r
+    unsigned long v;\r
+    char s[16], c, d, *p;\r
+\r
+\r
+    for (;;) {\r
+        c = *fmt++;     /* Get a char */\r
+        if (!c) break;    /* End of format? */\r
+        if (c != '%') {    /* Pass through it if not a % sequense */\r
+            xputc(c); continue;\r
+        }\r
+        f = 0;\r
+        c = *fmt++;     /* Get first char of the sequense */\r
+        if (c == '0') {    /* Flag: '0' padded */\r
+            f = 1; c = *fmt++;\r
+        } else {\r
+            if (c == '-') {   /* Flag: left justified */\r
+                f = 2; c = *fmt++;\r
+            }\r
+        }\r
+        for (w = 0; c >= '0' && c <= '9'; c = *fmt++) /* Minimum width */\r
+            w = w * 10 + c - '0';\r
+        if (c == 'l' || c == 'L') { /* Prefix: Size is long int */\r
+            f |= 4; c = *fmt++;\r
+        }\r
+        if (!c) break;    /* End of format? */\r
+        d = c;\r
+        if (d >= 'a') d -= 0x20;\r
+        switch (d) {    /* Type is... */\r
+            case 'S' :     /* String */\r
+                p = va_arg(arp, char*);\r
+                for (j = 0; p[j]; j++) ;\r
+                while (!(f & 2) && j++ < w) xputc(' ');\r
+                xputs(p);\r
+                while (j++ < w) xputc(' ');\r
+                continue;\r
+            case 'C' :     /* Character */\r
+                xputc((char)va_arg(arp, int)); continue;\r
+            case 'B' :     /* Binary */\r
+                r = 2; break;\r
+            case 'O' :     /* Octal */\r
+                r = 8; break;\r
+            case 'D' :     /* Signed decimal */\r
+            case 'U' :     /* Unsigned decimal */\r
+                r = 10; break;\r
+            case 'X' :     /* Hexdecimal */\r
+                r = 16; break;\r
+            default:     /* Unknown type (passthrough) */\r
+                xputc(c); continue;\r
+        }\r
+\r
+        /* Get an argument and put it in numeral */\r
+        v = (f & 4) ? va_arg(arp, long) : ((d == 'D') ? (long)va_arg(arp, int) : (long)va_arg(arp, unsigned int));\r
+        if (d == 'D' && (v & 0x80000000)) {\r
+            v = 0 - v;\r
+            f |= 8;\r
+        }\r
+        i = 0;\r
+        do {\r
+            d = (char)(v % r); v /= r;\r
+            if (d > 9) d += (c == 'x') ? 0x27 : 0x07;\r
+            s[i++] = d + '0';\r
+        } while (v && i < sizeof(s));\r
+        if (f & 8) s[i++] = '-';\r
+        j = i; d = (f & 1) ? '0' : ' ';\r
+        while (!(f & 2) && j++ < w) xputc(d);\r
+        do xputc(s[--i]); while(i);\r
+        while (j++ < w) xputc(' ');\r
+    }\r
+}\r
+\r
+\r
+void xprintf (   /* Put a formatted string to the default device */\r
+        const char* fmt, /* Pointer to the format string */\r
+        ...     /* Optional arguments */\r
+        )\r
+{\r
+    va_list arp;\r
+\r
+\r
+    va_start(arp, fmt);\r
+    xvprintf(fmt, arp);\r
+    va_end(arp);\r
+}\r
+\r
+\r
+void xsprintf (   /* Put a formatted string to the memory */\r
+        char* buff,   /* Pointer to the output buffer */\r
+        const char* fmt, /* Pointer to the format string */\r
+        ...     /* Optional arguments */\r
+        )\r
+{\r
+    va_list arp;\r
+\r
+\r
+    outptr = buff;  /* Switch destination for memory */\r
+\r
+    va_start(arp, fmt);\r
+    xvprintf(fmt, arp);\r
+    va_end(arp);\r
+\r
+    *outptr = 0;  /* Terminate output string with a \0 */\r
+    outptr = 0;   /* Switch destination for device */\r
+}\r
+\r
+\r
+    void xfprintf (     /* Put a formatted string to the specified device */\r
+            void(*func)(unsigned char), /* Pointer to the output function */\r
+            const char* fmt,   /* Pointer to the format string */\r
+            ...       /* Optional arguments */\r
+            )\r
+{\r
+    va_list arp;\r
+    void (*pf)(unsigned char);\r
+\r
+\r
+    pf = xfunc_out;  /* Save current output device */\r
+    xfunc_out = func; /* Switch output to specified device */\r
+\r
+    va_start(arp, fmt);\r
+    xvprintf(fmt, arp);\r
+    va_end(arp);\r
+\r
+    xfunc_out = pf;  /* Restore output device */\r
+}\r
+\r
+\r
+\r
+/*----------------------------------------------*/\r
+/* Dump a line of binary dump                   */\r
+/*----------------------------------------------*/\r
+\r
+void put_dump (\r
+        const void* buff,  /* Pointer to the array to be dumped */\r
+        unsigned long addr,  /* Heading address value */\r
+        int len,    /* Number of items to be dumped */\r
+        int width    /* Size of the items (DF_CHAR, DF_SHORT, DF_LONG) */\r
+        )\r
+{\r
+    int i;\r
+    const unsigned char *bp;\r
+    const unsigned short *sp;\r
+    const unsigned long *lp;\r
+\r
+\r
+    xprintf("%08lX ", addr);  /* address */\r
+\r
+    switch (width) {\r
+        case DW_CHAR:\r
+            bp = buff;\r
+            for (i = 0; i < len; i++)  /* Hexdecimal dump */\r
+                xprintf(" %02X", bp[i]);\r
+            xputc(' ');\r
+            for (i = 0; i < len; i++)  /* ASCII dump */\r
+                xputc((bp[i] >= ' ' && bp[i] <= '~') ? bp[i] : '.');\r
+            break;\r
+        case DW_SHORT:\r
+            sp = buff;\r
+            do        /* Hexdecimal dump */\r
+                xprintf(" %04X", *sp++);\r
+            while (--len);\r
+            break;\r
+        case DW_LONG:\r
+            lp = buff;\r
+            do        /* Hexdecimal dump */\r
+                xprintf(" %08LX", *lp++);\r
+            while (--len);\r
+            break;\r
+    }\r
+\r
+    xputc('\n');\r
+}\r
+\r
+#endif /* _USE_XFUNC_OUT */\r
+\r
+\r
+\r
+#if _USE_XFUNC_IN\r
+unsigned char (*xfunc_in)(void); /* Pointer to the input stream */\r
+\r
+/*----------------------------------------------*/\r
+/* Get a line from the input                    */\r
+/*----------------------------------------------*/\r
+\r
+int xgets (  /* 0:End of stream, 1:A line arrived */\r
+        char* buff, /* Pointer to the buffer */\r
+        int len  /* Buffer length */\r
+        )\r
+{\r
+    int c, i;\r
+\r
+\r
+    if (!xfunc_in) return 0;  /* No input function specified */\r
+\r
+    i = 0;\r
+    for (;;) {\r
+        c = xfunc_in();    /* Get a char from the incoming stream */\r
+        if (!c) return 0;   /* End of stream? */\r
+        if (c == '\r') break;  /* End of line? */\r
+        if (c == '\b' && i) {  /* Back space? */\r
+            i--;\r
+            if (_LINE_ECHO) xputc(c);\r
+            continue;\r
+        }\r
+        if (c >= ' ' && i < len - 1) { /* Visible chars */\r
+            buff[i++] = c;\r
+            if (_LINE_ECHO) xputc(c);\r
+        }\r
+    }\r
+    buff[i] = 0; /* Terminate with a \0 */\r
+    if (_LINE_ECHO) xputc('\n');\r
+    return 1;\r
+}\r
+\r
+\r
+    int xfgets ( /* 0:End of stream, 1:A line arrived */\r
+            unsigned char (*func)(void), /* Pointer to the input stream function */\r
+            char* buff, /* Pointer to the buffer */\r
+            int len  /* Buffer length */\r
+            )\r
+{\r
+    unsigned char (*pf)(void);\r
+    int n;\r
+\r
+\r
+    pf = xfunc_in;   /* Save current input device */\r
+    xfunc_in = func;  /* Switch input to specified device */\r
+    n = xgets(buff, len); /* Get a line */\r
+    xfunc_in = pf;   /* Restore input device */\r
+\r
+    return n;\r
+}\r
+\r
+\r
+/*----------------------------------------------*/\r
+/* Get a value of the string                    */\r
+/*----------------------------------------------*/\r
+/* "123 -5   0x3ff 0b1111 0377  w "\r
+   ^                           1st call returns 123 and next ptr\r
+   ^                        2nd call returns -5 and next ptr\r
+   ^                3rd call returns 1023 and next ptr\r
+   ^         4th call returns 15 and next ptr\r
+   ^    5th call returns 255 and next ptr\r
+   ^ 6th call fails and returns 0\r
+   */\r
+\r
+int xatoi (   /* 0:Failed, 1:Successful */\r
+        char **str,  /* Pointer to pointer to the string */\r
+        long *res  /* Pointer to the valiable to store the value */\r
+        )\r
+{\r
+    unsigned long val;\r
+    unsigned char c, r, s = 0;\r
+\r
+\r
+    *res = 0;\r
+\r
+    while ((c = **str) == ' ') (*str)++; /* Skip leading spaces */\r
+\r
+    if (c == '-') {  /* negative? */\r
+        s = 1;\r
+        c = *(++(*str));\r
+    }\r
+\r
+    if (c == '0') {\r
+        c = *(++(*str));\r
+        switch (c) {\r
+            case 'x':  /* hexdecimal */\r
+                r = 16; c = *(++(*str));\r
+                break;\r
+            case 'b':  /* binary */\r
+                r = 2; c = *(++(*str));\r
+                break;\r
+            default:\r
+                if (c <= ' ') return 1; /* single zero */\r
+                if (c < '0' || c > '9') return 0; /* invalid char */\r
+                r = 8;  /* octal */\r
+        }\r
+    } else {\r
+        if (c < '0' || c > '9') return 0; /* EOL or invalid char */\r
+        r = 10;   /* decimal */\r
+    }\r
+\r
+    val = 0;\r
+    while (c > ' ') {\r
+        if (c >= 'a') c -= 0x20;\r
+        c -= '0';\r
+        if (c >= 17) {\r
+            c -= 7;\r
+            if (c <= 9) return 0; /* invalid char */\r
+        }\r
+        if (c >= r) return 0;  /* invalid char for current radix */\r
+        val = val * r + c;\r
+        c = *(++(*str));\r
+    }\r
+    if (s) val = 0 - val;   /* apply sign if needed */\r
+\r
+    *res = val;\r
+    return 1;\r
+}\r
+\r
+#endif /* _USE_XFUNC_IN */\r
+\r