+ * \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)
+int vsnprintf(char *__s, size_t __maxlen, const char *__format, va_list args)
+{
+ char c, pad = ' ';
+ int minSize = 0, len;
+ char tmpBuf[34]; // For Integers
+ 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');
+ p = tmpBuf;
+ itoa(p, ptr, 16, BITS/4, '0');
+ goto printString;
+ }
+
+ // Get Argument
+ val = va_arg(args, Uint);
+
+ // - Padding Side Flag
+ if(c == '+') {
+ bPadLeft = 1;
+ c = *__format++;
+ }
+
+ // - Padding
+ if(c == '0') {
+ pad = '0';
+ c = *__format++;
+ }
+ else
+ pad = ' ';
+
+ // - Minimum length
+ if(c == '*') {
+ minSize = val;
+ val = va_arg(args, Uint);
+ c = *__format++;
+ }
+ else if('1' <= c && c <= '9')
+ {
+ minSize = 0;
+ while('0' <= c && c <= '9')
+ {
+ minSize *= 10;
+ minSize += c - '0';
+ c = *__format++;
+ }
+ }
+ else
+ minSize = 1;
+
+ // - Default, Long or LongLong?
+ isLongLong = 0;
+ if(c == 'l') // Long is actually the default on x86
+ {
+ c = *__format++;
+ if(c == 'l') {
+ #if BITS == 32
+ val |= (Uint64)va_arg(args, Uint) << 32;
+ #endif
+ c = *__format++;
+ isLongLong = 1;
+ }
+ }
+
+ // - Now get the format code
+ p = tmpBuf;
+ switch(c)
+ {
+ case 'd':
+ case 'i':
+ #if BITS == 32
+ if( (isLongLong && val >> 63) || (!isLongLong && val >> 31) ) {
+ #else
+ if( (Sint)val < 0 ) {
+ #endif
+ PUTCH('-');
+ val = -val;
+ }
+ itoa(p, val, 10, minSize, pad);
+ goto printString;
+ case 'u':
+ itoa(p, val, 10, minSize, pad);
+ goto printString;
+ case 'x':
+ itoa(p, val, 16, minSize, pad);
+ goto printString;
+ case 'o':
+ itoa(p, val, 8, minSize, pad);
+ goto printString;
+ case 'b':
+ itoa(p, val, 2, minSize, pad);
+ goto printString;
+
+ case 'B': //Boolean
+ if(val) p = "True";
+ else p = "False";
+ goto printString;
+
+ // String - Null Terminated Array
+ case 's':
+ p = (char*)(Uint)val;
+ printString:
+ if(!p) p = "(null)";
+ len = strlen(p);
+ if( !bPadLeft ) while(len++ < minSize) PUTCH(pad);
+ while(*p) PUTCH(*p++);
+ if( bPadLeft ) while(len++ < minSize) PUTCH(pad);
+ break;
+
+ case 'C': // Non-Null Terminated Character Array
+ p = (char*)(Uint)val;
+ if(!p) goto printString;
+ while(minSize--) PUTCH(*p++);
+ break;
+
+ // Single Character
+ case 'c':
+ default:
+ 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)