-/**
- * \brief Convert a string into an integer
- */
-int atoi(const char *string)
-{
- int ret = 0;
- ParseInt(string, &ret);
- return ret;
-}
-int ParseInt(const char *string, int *Val)
-{
- int ret = 0;
- int bNeg = 0;
- const char *orig_string = string;
-
- //Log("atoi: (string='%s')", string);
-
- // Clear non-numeric characters
- while( !('0' <= *string && *string <= '9') && *string != '-' ) string++;
- if( *string == '-' ) {
- bNeg = 1;
- while( !('0' <= *string && *string <= '9') ) string++;
- }
-
- if(*string == '0')
- {
- string ++;
- if(*string == 'x')
- {
- // Hex
- string ++;
- for( ;; string ++ )
- {
- if('0' <= *string && *string <= '9') {
- ret *= 16;
- ret += *string - '0';
- }
- else if('A' <= *string && *string <= 'F') {
- ret *= 16;
- ret += *string - 'A' + 10;
- }
- else if('a' <= *string && *string <= 'f') {
- ret *= 16;
- ret += *string - 'a' + 10;
- }
- else
- break;
- }
- }
- else // Octal
- {
- for( ; '0' <= *string && *string <= '7'; string ++ )
- {
- ret *= 8;
- ret += *string - '0';
- }
- }
- }
- else // Decimal
- {
- for( ; '0' <= *string && *string <= '9'; string++)
- {
- ret *= 10;
- ret += *string - '0';
- }
- // Error check
- if( ret == 0 ) return 0;
- }
-
- if(bNeg) ret = -ret;
-
- //Log("atoi: RETURN %i", ret);
-
- if(Val) *Val = ret;
-
- return string - orig_string;
-}
-
-static const char cUCDIGITS[] = "0123456789ABCDEF";
-/**
- * \fn void itoa(char *buf, Uint64 num, int base, int minLength, char pad)
- * \brief Convert an integer into a character string
- */
-void itoa(char *buf, Uint64 num, int base, int minLength, char pad)
-{
- char tmpBuf[64+1];
- int pos=0, i;
- Uint64 rem;
-
- // Sanity check
- if(!buf) return;
-
- // Sanity Check
- if(base > 16 || base < 2) {
- buf[0] = 0;
- return;
- }
-
- // Convert
- while(num > base-1) {
- num = DivMod64U(num, base, &rem); // Shift `num` and get remainder
- tmpBuf[pos] = cUCDIGITS[ rem ];
- pos++;
- }
- tmpBuf[pos++] = cUCDIGITS[ num ]; // Last digit of `num`
-
- // Put in reverse
- i = 0;
- minLength -= pos;
- while(minLength-- > 0) buf[i++] = pad;
- while(pos-- > 0) buf[i++] = tmpBuf[pos]; // Reverse the order of characters
- buf[i] = 0;
-}
-
-/**
- * \brief Append a character the the vsnprintf output
- */
-#define PUTCH(c) _putch(c)
-#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;
-
- auto void _putch(char ch);
-
- void _putch(char ch)
- {
- if(pos < __maxlen)
- {
- if(__s) __s[pos] = ch;
- pos ++;
- }
- }
-
- while((c = *__format++) != 0)
- {
- // Non control character
- if(c != '%') { PUTCH(c); continue; }
-
- c = *__format++;
- if(c == '\0') break;
-
- // Literal %
- if(c == '%') { PUTCH('%'); continue; }
-
- // Pointer - Done first for debugging
- if(c == 'p') {
- Uint ptr = va_arg(args, Uint);
- PUTCH('*'); PUTCH('0'); PUTCH('x');
- for( len = BITS/4; len --; )
- PUTCH( cUCDIGITS[ (ptr>>(len*4))&15 ] );
- continue ;
- }
-
- // - 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( !p || !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
-
-/**
- */
-size_t snprintf(char *__s, size_t __n, const char *__format, ...)
-{
- va_list args;
- int ret;
-
- va_start(args, __format);
- ret = vsnprintf(__s, __n, __format, args);
- va_end(args);
-
- return ret;
-}
-
-/**
- */
-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)
- * \brief Converts a character to lower case
- */
-int tolower(int c)
-{
- if('A' <= c && c <= 'Z')
- return c - 'A' + 'a';
- return c;
-}
-
-/**
- * \fn int strucmp(const char *Str1, const char *Str2)
- * \brief Compare \a Str1 and \a Str2 case-insensitively
- */
-int strucmp(const char *Str1, const char *Str2)
-{
- while(*Str1 && tolower(*Str1) == tolower(*Str2))
- Str1++, Str2++;
- return tolower(*Str1) - tolower(*Str2);
-}
-
-/**
- * \brief Locate a byte in a string
- */
-char *strchr(const char *__s, int __c)
-{
- for( ; *__s; __s ++ )
- {
- if( *__s == __c ) return (char*)__s;
- }
- return NULL;
-}
-
-/**
- * \fn int strpos(const char *Str, char Ch)
- * \brief Search a string for an ascii character
- */
-int strpos(const char *Str, char Ch)
-{
- int pos;
- for(pos=0;Str[pos];pos++)
- {
- if(Str[pos] == Ch) return pos;
- }
- return -1;
-}
-