+ * \brief Append a character the the vsnprintf output
+ */
+#define PUTCH(c) do{\
+ char ch=(c);\
+ if(pos==__maxlen){return pos;}\
+ if(__s){__s[pos++]=ch;}else{pos++;}\
+ }while(0)
+#define GETVAL() do {\
+ if(isLongLong) val = va_arg(args, Uint64);\
+ else val = va_arg(args, unsigned int);\
+ }while(0)
+/**
+ * \brief VArg String Number Print Formatted
+ */
+int vsnprintf(char *__s, size_t __maxlen, const char *__format, va_list args)
+{
+ char c, pad = ' ';
+ int minSize = 0, precision = -1, len;
+ char tmpBuf[34]; // For Integers
+ const char *p = NULL;
+ int isLongLong = 0;
+ Uint64 val;
+ size_t pos = 0;
+ // Flags
+ int bPadLeft = 0;
+
+ //Log("vsnprintf: (__s=%p, __maxlen=%i, __format='%s', ...)", __s, __maxlen, __format);
+
+ while((c = *__format++) != 0)
+ {
+ // Non control character
+ if(c != '%') { PUTCH(c); continue; }
+
+ c = *__format++;
+ //Log("pos = %i", pos);
+
+ // Literal %
+ if(c == '%') { PUTCH('%'); continue; }
+
+ // Pointer - Done first for debugging
+ if(c == 'p') {
+ Uint ptr = va_arg(args, Uint);
+ PUTCH('*'); PUTCH('0'); PUTCH('x');
+ itoa(tmpBuf, ptr, 16, BITS/4, '0');
+ p = tmpBuf;
+ goto printString;
+ }
+
+ // - Padding Side Flag
+ if(c == '-') {
+ bPadLeft = 1;
+ c = *__format++;
+ }
+
+ // - Padding
+ if(c == '0') {
+ pad = '0';
+ c = *__format++;
+ }
+ else
+ pad = ' ';
+
+ // - Minimum length
+ if(c == '*') { // Dynamic length
+ minSize = va_arg(args, unsigned int);
+ c = *__format++;
+ }
+ else if('1' <= c && c <= '9')
+ {
+ minSize = 0;
+ while('0' <= c && c <= '9')
+ {
+ minSize *= 10;
+ minSize += c - '0';
+ c = *__format++;
+ }
+ }
+ else
+ minSize = 0;
+
+ // - Precision
+ precision = -1;
+ if( c == '.' ) {
+ c = *__format++;
+
+ if(c == '*') { // Dynamic length
+ precision = va_arg(args, unsigned int);
+ c = *__format++;
+ }
+ else if('1' <= c && c <= '9')
+ {
+ precision = 0;
+ while('0' <= c && c <= '9')
+ {
+ precision *= 10;
+ precision += c - '0';
+ c = *__format++;
+ }
+ }
+ }
+
+ // - Default, Long or LongLong?
+ isLongLong = 0;
+ if(c == 'l') // Long is actually the default on x86
+ {
+ c = *__format++;
+ if(c == 'l') {
+ c = *__format++;
+ isLongLong = 1;
+ }
+ }
+
+ // - Now get the format code
+ p = tmpBuf;
+ switch(c)
+ {
+ case 'd':
+ case 'i':
+ GETVAL();
+ if( isLongLong && val >> 63 ) {
+ PUTCH('-');
+ val = -val;
+ }
+ else if( !isLongLong && val >> 31 ) {
+ PUTCH('-');
+ val = -(Sint32)val;
+ }
+ itoa(tmpBuf, val, 10, minSize, pad);
+ goto printString;
+ case 'u': // Unsigned
+ GETVAL();
+ itoa(tmpBuf, val, 10, minSize, pad);
+ goto printString;
+ case 'P': // Physical Address
+ PUTCH('0');
+ PUTCH('x');
+ if(sizeof(tPAddr) > 4) isLongLong = 1;
+ GETVAL();
+ itoa(tmpBuf, val, 16, minSize, pad);
+ goto printString;
+ case 'X': // Hex
+ if(BITS == 64)
+ isLongLong = 1; // TODO: Handle non-x86 64-bit archs
+ GETVAL();
+ itoa(tmpBuf, val, 16, minSize, pad);
+ goto printString;
+
+ case 'x': // Lower case hex
+ GETVAL();
+ itoa(tmpBuf, val, 16, minSize, pad);
+ goto printString;
+ case 'o': // Octal
+ GETVAL();
+ itoa(tmpBuf, val, 8, minSize, pad);
+ goto printString;
+ case 'b':
+ GETVAL();
+ itoa(tmpBuf, val, 2, minSize, pad);
+ goto printString;
+
+ case 'B': //Boolean
+ val = va_arg(args, unsigned int);
+ if(val) p = "True";
+ else p = "False";
+ goto printString;
+
+ // String - Null Terminated Array
+ case 's':
+ p = va_arg(args, char*); // Get Argument
+ if( !CheckString(p) ) p = "(inval)"; // Avoid #PFs
+ printString:
+ if(!p) p = "(null)";
+ len = strlen(p);
+ if( !bPadLeft ) while(len++ < minSize) PUTCH(pad);
+ while(*p && precision--) PUTCH(*p++);
+ if( bPadLeft ) while(len++ < minSize) PUTCH(pad);
+ break;
+
+ case 'C': // Non-Null Terminated Character Array
+ p = va_arg(args, char*);
+ if( !CheckMem(p, minSize) ) continue; // No #PFs please
+ if(!p) goto printString;
+ while(minSize--) PUTCH(*p++);
+ break;
+
+ // Single Character
+ case 'c':
+ default:
+ GETVAL();
+ PUTCH( (Uint8)val );
+ break;
+ }
+ }
+
+ if(__s && pos != __maxlen)
+ __s[pos] = '\0';
+
+ return pos;
+}
+#undef PUTCH
+
+/**
+ */
+int sprintf(char *__s, const char *__format, ...)
+{
+ va_list args;
+ int ret;
+
+ va_start(args, __format);
+ ret = vsnprintf(__s, -1, __format, args);
+ va_end(args);
+
+ return ret;
+}
+
+/**
+ * \fn int tolower(int c)