Mercurial > lcfOS
diff cos/kernel/snprintf.c @ 9:92ace1ca50a8
64 bits kernel without interrupts but with printf in C
author | windel |
---|---|
date | Sun, 13 Nov 2011 12:47:47 +0100 |
parents | |
children | fcdae30b2782 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cos/kernel/snprintf.c Sun Nov 13 12:47:47 2011 +0100 @@ -0,0 +1,234 @@ +/* + * snprintf.c + */ +#include "kernel.h" + +#include "stdarg.h" +#include "ctype.h" + +unsigned char _ctype[] = { +_C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */ +_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */ +_C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */ +_C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */ +_S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */ +_P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */ +_D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */ +_D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */ +_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */ +_U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */ +_U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */ +_U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */ +_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */ +_L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */ +_L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */ +_L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */ +_S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */ +_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */ +_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */ +_U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */ +_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */ +_L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */ + + +#define MORE_THAN_YOU_WANT 1<<30 +#define MAX_STDOUT_CHARS 255 + +static char hexmap[] = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' +}; + +void va_snprintf(char *b, int l, const char *fmt, va_list pvar) +{ + int n, i; + uint_t u; + ulonglong_t ull; + char *t; + char d[10]; + char mod_l; + char mod_ll; + + if (!fmt || !b || (l < 1)) + return; + + mod_l = 0; + mod_ll = 0; + + while (l && *fmt) { + if (*fmt == '%') { + if (!(--l)) + break; + again: + fmt++; + + switch (*fmt) { + case '.': /* precision modifier */ + while(isdigit(fmt[1])) + fmt++; + goto again; + + case 'l': /* long modifier */ + if (!mod_l) { + mod_l = 1; + } else if (!mod_ll) { + mod_l = 0; + mod_ll = 1; + } + goto again; + + case 's': /* string */ + t = va_arg(pvar, char *); + while (l && *t) + *b++ = *t++, l--; + break; + + case 'c': /* single character */ + *b++ = va_arg(pvar, char); + l--; + break; + + case 'S': /* uint32 as a short ... */ + if (l < 4) { + l = 0; + break; + } + u = va_arg(pvar, unsigned int); + for (i = 3; i >= 0; i--) { + b[i] = hexmap[u & 0x0F]; + u >>= 4; + } + b += 4; + l -= 4; + break; + + case 'x': + case 'p': + if (!mod_ll) { /* 8 digit, unsigned 32-bit hex integer */ + if (l < 8) { + l = 0; + break; + } + u = va_arg(pvar, unsigned int); + for (i = 7; i >= 0; i--) { + b[i] = hexmap[u & 0x0F]; + u >>= 4; + } + b += 8; + l -= 8; + } else if (mod_ll) { /* 16 digit, unsigned 64-bit hex integer */ + if (l < 16) { + l = 0; + break; + } + ull = va_arg(pvar, unsigned long long); + for (i = 15; i >= 0; i--) { + b[i] = hexmap[ull & 0x0f]; + ull >>= 4; + } + b += 16; + l -= 16; + } + mod_l = mod_ll = 0; + break; + + case 'd': /* signed integer */ + n = va_arg(pvar, int); + if (n < 0) { + u = -n; + *b++ = '-'; + if (!(--l)) + break; + } else { + u = n; + } + goto u2; + + case 'u': /* unsigned integer */ + u = va_arg(pvar, unsigned int); + u2: + i = 9; + do { + d[i] = (u % 10) + '0'; + u /= 10; + i--; + } + while (u && i >= 0); + while (++i < 10) { + *b++ = d[i]; + if (!(--l)) + break; + } + break; + + case 'U': + u = va_arg(pvar, unsigned int); + i = 9; + d[8] = d[7] = d[6] = ' '; + do { + d[i] = (u % 10) + '0'; + u /= 10; + i--; + } + while (u && i >= 0); + i = 5; + while (++i < 10) { + *b++ = d[i]; + if (!(--l)) + break; + } + break; + + case 'X': /* 2 digit, unsigned 8bit hex int */ + if (l < 2) { + l = 0; + break; + } + n = va_arg(pvar, int); + *b++ = hexmap[(n & 0xF0) >> 4]; + *b++ = hexmap[n & 0x0F]; + l -= 2; + break; + default: + *b++ = *fmt; + } + } else { + *b++ = *fmt; + l--; + } + fmt++; + } + *b = 0; +} + +void snprintf(char *str, int len, char *fmt, ...) +{ + va_list pvar; + va_start(pvar, fmt); + va_snprintf(str, len, fmt, pvar); + va_end(pvar); +} + +void +sprintf(char *dst, const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + va_snprintf(dst, MORE_THAN_YOU_WANT, fmt, args); + va_end(args); +} + +void +printf(const char* fmt, ...) +{ + static char buf[MAX_STDOUT_CHARS]; + + va_list args; + va_start(args, fmt); + va_snprintf(buf, MAX_STDOUT_CHARS, fmt, args); + va_end(args); + + print_string(buf); +}