view cos/kernel/snprintf.c @ 16:ddefe6d97cd7

Merged
author windel-eee
date Fri, 18 Nov 2011 14:41:53 +0100
parents d07d4701a103
children f3e3e0e9c4bc
line wrap: on
line source

/*
 * snprintf.c
 */
#include "kernel.h"

/*
 * NOTE! This ctype does not handle EOF like the standard C
 * library is required to.
 */

#define _U	0x01	/* upper */
#define _L	0x02	/* lower */
#define _D	0x04	/* digit */
#define _C	0x08	/* cntrl */
#define _P	0x10	/* punct */
#define _S	0x20	/* white space (space/lf/tab) */
#define _X	0x40	/* hex digit */
#define _SP	0x80	/* hard space (0x20) */


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 __ismask(x) (_ctype[(int)(unsigned char)(x)])

#define isalnum(c)	((__ismask(c)&(_U|_L|_D)) != 0)
#define isalpha(c)	((__ismask(c)&(_U|_L)) != 0)
#define iscntrl(c)	((__ismask(c)&(_C)) != 0)
#define isdigit(c)	((__ismask(c)&(_D)) != 0)
#define isgraph(c)	((__ismask(c)&(_P|_U|_L|_D)) != 0)
#define islower(c)	((__ismask(c)&(_L)) != 0)
#define isprint(c)	((__ismask(c)&(_P|_U|_L|_D|_SP)) != 0)
#define ispunct(c)	((__ismask(c)&(_P)) != 0)
#define isspace(c)	((__ismask(c)&(_S)) != 0)
#define isupper(c)	((__ismask(c)&(_U)) != 0)
#define isxdigit(c)	((__ismask(c)&(_D|_X)) != 0)

#define isascii(c) (((unsigned char)(c))<=0x7f)
#define toascii(c) (((unsigned char)(c))&0x7f)

static inline unsigned char tolower(unsigned char c)
{
	if (isupper(c))
		c -= 'A'-'a';
	return c;
}

static inline unsigned char toupper(unsigned char c)
{
	if (islower(c))
		c -= 'a'-'A';
	return c;
}

#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++ = 'x'; // TODO: 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);
}