Usermode/libc - Fix strchr and strrchr behavior
[tpg/acess2.git] / KernelLand / Kernel / libc.c
index c6df2cd..572184d 100644 (file)
@@ -7,6 +7,7 @@
  */
 #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);
@@ -67,15 +72,11 @@ EXPORT(CheckString);
 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_
+#define _SysDebug(f,v...)      Log_Debug("libc", f ,## v)
+#include "../../Usermode/Libraries/libc.so_src/strtoi.c"
+
 int ParseInt(const char *string, int *Val)
 {
         int    ret = 0;
@@ -156,18 +157,21 @@ void itoa(char *buf, Uint64 num, int base, int minLength, char pad)
         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++;
        }
@@ -185,8 +189,8 @@ void itoa(char *buf, Uint64 num, int base, int minLength, char pad)
  * \brief Append a character the the vsnprintf output
  */
 #define PUTCH(ch)      do { \
-               if(pos < __maxlen) { \
-                       if(__s) __s[pos] = ch; \
+               if(pos < __maxlen && __s) { \
+                       __s[pos] = ch; \
                } else { \
                        (void)ch;\
                } \
@@ -199,13 +203,13 @@ void itoa(char *buf, Uint64 num, int base, int minLength, char pad)
 /**
  * \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
@@ -228,11 +232,18 @@ int vsnprintf(char *__s, size_t __maxlen, const char *__format, va_list args)
                        PUTCH('*');     PUTCH('0');     PUTCH('x');
                        for( len = BITS/4; len -- && ((ptr>>(len*4))&15) == 0; )
                                ;
-                       for( len ++; len --; )
-                               PUTCH( cUCDIGITS[ (ptr>>(len*4))&15 ] );
+                       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;
@@ -290,6 +301,7 @@ int vsnprintf(char *__s, size_t __maxlen, const char *__format, va_list args)
                isLongLong = 0;
                if(c == 'l')    // Long is actually the default on x86
                {
+                       isLong = 1;
                        c = *__format++;
                        if(c == 'l') {
                                c = *__format++;
@@ -306,11 +318,14 @@ int vsnprintf(char *__s, size_t __maxlen, const char *__format, va_list args)
                        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;
@@ -353,21 +368,63 @@ int vsnprintf(char *__s, size_t __maxlen, const char *__format, va_list args)
                
                // 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  
+                       if( p && !CheckString(p) )      goto invalString;       // 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;
+               invalString:    
+                       PUTCH('(');PUTCH('i');PUTCH('n');PUTCH('v');PUTCH('a'); PUTCH('l');PUTCH(':');
+                       PUTCH('*');PUTCH('0');PUTCH('x');
+                       val = (tVAddr)p;
+                       for( len = BITS/4; len -- && ((val>>(len*4))&15) == 0; )
+                               ;
+                       len ++;
+                       if( len == 0 )
+                               PUTCH( '0' );
+                       else
+                               while( len -- )
+                                       PUTCH( cUCDIGITS[ (val>>(len*4))&15 ] );
+                       PUTCH(')');
+                       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
@@ -379,7 +436,7 @@ int vsnprintf(char *__s, size_t __maxlen, const char *__format, va_list args)
                }
        }
        
-       if(__s && pos != __maxlen)
+       if(__s && pos < __maxlen)
                __s[pos] = '\0';
        
        return pos;
@@ -483,7 +540,7 @@ int isspace(int c)
 }
 int isupper(int c)
 {
-       return ('a' <= c && c <= 'z');
+       return ('A' <= c && c <= 'Z');
 }
 int isxdigit(int c)
 {

UCC git Repository :: git.ucc.asn.au