*/
#include <acess.h>
#include <hal_proc.h> // For MM_*
+#include <utf16.h>
// === CONSTANTS ===
#define RANDOM_SEED 0xACE55052
// === PROTOTYPES ===
#if 0
+unsigned long long strtoull(const char *str, char **end, int base);
+unsigned long strtoul(const char *str, char **end, int base);
+signed long long strtoll(const char *str, char **end, int base);
+signed long strtol(const char *str, char **end, int base);
int atoi(const char *string);
int ParseInt(const char *string, int *Val);
void itoa(char *buf, Uint64 num, int base, int minLength, char pad);
int vsnprintf(char *__s, size_t __maxlen, const char *__format, va_list args);
int snprintf(char *__s, size_t __n, const char *__format, ...);
int sprintf(char *__s, const char *__format, ...);
-#endif
- int tolower(int c);
-#if 0
int strucmp(const char *Str1, const char *Str2);
char *strchr(const char *__s, int __c);
int strpos(const char *Str, char Ch);
EXPORT(snprintf);
EXPORT(sprintf);
EXPORT(tolower);
+
EXPORT(strucmp);
EXPORT(strchr);
+EXPORT(strrchr);
EXPORT(strpos);
EXPORT(strlen);
EXPORT(strcpy);
EXPORT(CheckMem);
// === CODE ===
-/**
- * \brief Convert a string into an integer
- */
-int atoi(const char *string)
-{
- int ret = 0;
- ParseInt(string, &ret);
- return ret;
-}
+// - Import userland stroi.c file
+#define _LIB_H_
+#include "../../Usermode/Libraries/libc.so_src/strtoi.c"
+
int ParseInt(const char *string, int *Val)
{
int ret = 0;
int pos=0, i;
Uint64 rem;
+ buf[0] = 0;
+ ASSERTR(base >= 2, );
+ ASSERTR(base <= 16, );
+
// 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
+ ASSERT(rem >= 0);
+ if( rem >= base && base != 16 ) {
+ Debug("rem(%llx) >= base(%x), num=%llx", rem, base, num);
+ }
+ ASSERT(rem < base);
tmpBuf[pos] = cUCDIGITS[ rem ];
pos++;
}
/**
* \brief Append a character the the vsnprintf output
*/
-#define PUTCH(c) _putch(c)
+#define PUTCH(ch) do { \
+ if(pos < __maxlen && __s) { \
+ __s[pos] = ch; \
+ } else { \
+ (void)ch;\
+ } \
+ pos ++; \
+ } while(0)
#define GETVAL() do {\
if(isLongLong) val = va_arg(args, Uint64);\
else val = va_arg(args, unsigned int);\
/**
* \brief VArg String Number Print Formatted
*/
-int vsnprintf(char *__s, size_t __maxlen, const char *__format, va_list args)
+int vsnprintf(char *__s, const 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;
+ int isLongLong = 0, isLong;
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)
{
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 ] );
+ for( len = BITS/4; len -- && ((ptr>>(len*4))&15) == 0; )
+ ;
+ len ++;
+ if( len == 0 )
+ PUTCH( '0' );
+ else
+ while( len -- )
+ PUTCH( cUCDIGITS[ (ptr>>(len*4))&15 ] );
continue ;
}
-
+
+ isLongLong = 0;
+ isLong = 0;
+
// - Padding Side Flag
if(c == '-') {
bPadLeft = 1;
isLongLong = 0;
if(c == 'l') // Long is actually the default on x86
{
+ isLong = 1;
c = *__format++;
if(c == 'l') {
c = *__format++;
GETVAL();
if( isLongLong && val >> 63 ) {
PUTCH('-');
- val = -val;
+ if( val == LLONG_MIN )
+ val = LLONG_MAX;
+ else
+ val = -val;
}
- else if( !isLongLong && val >> 31 ) {
+ else if( !isLongLong && (val >> 31) ) {
PUTCH('-');
- val = -(Sint32)val;
+ val = (~val & 0xFFFFFFFF)+1;
}
itoa(tmpBuf, val, 10, minSize, pad);
goto printString;
// String - Null Terminated Array
case 's':
+ if( isLong ) {
+ Uint16 *p16 = va_arg(args, Uint16*);
+ Uint8 tmp[5];
+ while( *p16 && precision-- ) {
+ Uint32 cp;
+ p16 += ReadUTF16(p16, &cp);
+ tmp[WriteUTF8(tmp, cp)] = 0;
+ for(int i = 0; tmp[i] && i<5; i ++)
+ PUTCH(tmp[i]);
+ }
+ break;
+ }
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++);
+ while(*p && precision--) { PUTCH(*p); 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( !CheckMem(p, minSize) ) {
+ p = "(inval)";
+ goto printString;
+ }
if(!p) goto printString;
- while(minSize--) PUTCH(*p++);
+ while(minSize--) {
+ if(*p == '\0') {
+ PUTCH('\\');
+ PUTCH('0');
+ }
+ else if(*p == '\\') {
+ PUTCH('\\');
+ PUTCH('\\');
+ }
+ else {
+ PUTCH(*p);
+ }
+ p ++;
+ }
break;
// Single Character
}
}
- if(__s && pos != __maxlen)
+ if(__s && pos < __maxlen)
__s[pos] = '\0';
return pos;
return ret;
}
-/**
- * \fn int tolower(int c)
- * \brief Converts a character to lower case
+/*
+ * ==================
+ * ctype.h
+ * ==================
*/
+int isalnum(int c)
+{
+ return isalpha(c) || isdigit(c);
+}
+int isalpha(int c)
+{
+ return isupper(c) || islower(c);
+}
+int isascii(int c)
+{
+ return (0 <= c && c < 128);
+}
+int isblank(int c)
+{
+ if(c == '\t') return 1;
+ if(c == ' ') return 1;
+ return 0;
+}
+int iscntrl(int c)
+{
+ // TODO: Check iscntrl
+ if(c < ' ') return 1;
+ return 0;
+}
+int isdigit(int c)
+{
+ return ('0' <= c && c <= '9');
+}
+int isgraph(int c)
+{
+ // TODO: Check isgraph
+ return 0;
+}
+int islower(int c)
+{
+ return ('a' <= c && c <= 'z');
+}
+int isprint(int c)
+{
+ if( ' ' <= c && c <= 0x7F ) return 1;
+ return 0;
+}
+int ispunct(int c)
+{
+ switch(c)
+ {
+ case '.': case ',':
+ case '?': case '!':
+ return 1;
+ default:
+ return 0;
+ }
+}
+int isspace(int c)
+{
+ if(c == ' ') return 1;
+ if(c == '\t') return 1;
+ if(c == '\v') return 1;
+ if(c == '\n') return 1;
+ if(c == '\r') return 1;
+ return 0;
+}
+int isupper(int c)
+{
+ return ('A' <= c && c <= 'Z');
+}
+int isxdigit(int c)
+{
+ return isdigit(c) || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F');
+}
+
+int toupper(int c)
+{
+ if( islower(c) )
+ return c - 0x20;
+ else
+ return c;
+}
int tolower(int c)
{
- if('A' <= c && c <= 'Z')
- return c - 'A' + 'a';
- return c;
+ if( isupper(c) )
+ return c + 0x20;
+ else
+ return c;
}
/**
return NULL;
}
+char *strrchr(const char *__s, int __c)
+{
+ size_t ofs = strlen(__s);
+ while(--ofs && __s[ofs] != __c);
+ if( __s[ofs] == __c )
+ return (char*)__s + ofs;
+ return NULL;
+}
+
/**
* \fn int strpos(const char *Str, char Ch)
* \brief Search a string for an ascii character
void *memmove(void *__dest, const void *__src, size_t len)
{
- size_t block_size;
char *dest = __dest;
const char *src = __src;
void *ret = __dest;
if( (tVAddr)dest < (tVAddr)src )
return memcpy(dest, src, len);
+ #if 0
+ size_t block_size;
if( (tVAddr)dest < (tVAddr)src )
block_size = (tVAddr)src - (tVAddr)dest;
else
}
memcpy(dest, src, len);
return ret;
+ #else
+ for( int i = len; i--; )
+ {
+ dest[i] = src[i];
+ }
+ return ret;
+ #endif
}
-// NOTE: Strictly not libc, but lib.c is used by userland code too
+// NOTE: Strictly not libc, but lib.c is used by userland code too and hence these two
+// can't be in it.
/**
* \name Memory Validation
* \{
addr = (tVAddr)String;
- if( !MM_GetPhysAddr( addr ) )
+ if( !MM_GetPhysAddr( (void*)addr ) )
return 0;
// Check 1st page
{
if(bUser && !MM_IsUser(addr) )
return 0;
- if(!bUser && !MM_GetPhysAddr(addr) )
+ if(!bUser && !MM_GetPhysAddr((void*)addr) )
return 0;
}
addr ++;