X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Kernel%2Flib.c;h=8612638c639afe3d40d6c398c3734c0746de561c;hb=7536e8afcc3018c4ca2a4aa8f8422cf86a6c188c;hp=5f277b8b7365fbda5fa4f8927b33c000f0f376f8;hpb=22621d0f86a4b3ca5038e470f105d941fbbd7c62;p=tpg%2Facess2.git diff --git a/Kernel/lib.c b/Kernel/lib.c index 5f277b8b..8612638c 100644 --- a/Kernel/lib.c +++ b/Kernel/lib.c @@ -3,6 +3,7 @@ * Common Library Functions */ #include +#include // === CONSTANTS === #define RANDOM_SEED 0xACE55052 @@ -38,6 +39,9 @@ char **str_split(const char *__str, char __ch); int WriteUTF8(Uint8 *str, Uint32 Val); int DivUp(int num, int dem); Sint64 timestamp(int sec, int mins, int hrs, int day, int month, int year); +#endif +void format_date(tTime TS, int *year, int *month, int *day, int *hrs, int *mins, int *sec, int *ms); +#if 0 int rand(void); int CheckString(char *String); @@ -46,6 +50,7 @@ Sint64 timestamp(int sec, int mins, int hrs, int day, int month, int year); int ModUtil_LookupString(char **Array, char *Needle); int ModUtil_SetIdent(char *Dest, char *Value); + int Hex(char *Dest, size_t Size, const Uint8 *SourceData); int UnHex(Uint8 *Dest, size_t DestSize, const char *SourceString); #endif @@ -62,6 +67,8 @@ EXPORT(ByteSum); EXPORT(strlen); EXPORT(strcpy); EXPORT(strncpy); +EXPORT(strcat); +EXPORT(strncat); EXPORT(strcmp); EXPORT(strncmp); //EXPORT(strdup); @@ -77,15 +84,25 @@ EXPORT(CheckMem); EXPORT(ModUtil_LookupString); EXPORT(ModUtil_SetIdent); EXPORT(UnHex); +EXPORT(SwapEndian16); +EXPORT(SwapEndian32); +EXPORT(memmove); // === CODE === /** * \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); @@ -137,13 +154,17 @@ int atoi(const char *string) ret *= 10; ret += *string - '0'; } + // Error check + if( ret == 0 ) return 0; } if(bNeg) ret = -ret; //Log("atoi: RETURN %i", ret); - return ret; + if(Val) *Val = ret; + + return string - orig_string; } static const char cUCDIGITS[] = "0123456789ABCDEF"; @@ -155,6 +176,7 @@ 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; @@ -167,11 +189,11 @@ void itoa(char *buf, Uint64 num, int base, int minLength, char pad) // Convert while(num > base-1) { - tmpBuf[pos] = cUCDIGITS[ num % base ]; - num /= (Uint)base; // Shift `num` right 1 digit + num = DivMod64U(num, base, &rem); // Shift `num` and get remainder + tmpBuf[pos] = cUCDIGITS[ rem ]; pos++; } - tmpBuf[pos++] = cUCDIGITS[ num % base ]; // Last digit of `num` + tmpBuf[pos++] = cUCDIGITS[ num ]; // Last digit of `num` // Put in reverse i = 0; @@ -184,11 +206,7 @@ void itoa(char *buf, Uint64 num, int base, int minLength, char pad) /** * \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 PUTCH(c) _putch(c) #define GETVAL() do {\ if(isLongLong) val = va_arg(args, Uint64);\ else val = va_arg(args, unsigned int);\ @@ -208,15 +226,24 @@ int vsnprintf(char *__s, size_t __maxlen, const char *__format, va_list args) // Flags int bPadLeft = 0; - //Log("vsnprintf: (__s=%p, __maxlen=%i, __format='%s', ...)", __s, __maxlen, __format); - + 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++; - //Log("pos = %i", pos); + if(c == '\0') break; // Literal % if(c == '%') { PUTCH('%'); continue; } @@ -225,9 +252,9 @@ int vsnprintf(char *__s, size_t __maxlen, const char *__format, va_list args) 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; + for( len = BITS/4; len --; ) + PUTCH( cUCDIGITS[ (ptr>>(len*4))&15 ] ); + continue ; } // - Padding Side Flag @@ -260,7 +287,7 @@ int vsnprintf(char *__s, size_t __maxlen, const char *__format, va_list args) } } else - minSize = 1; + minSize = 0; // - Precision precision = -1; @@ -311,22 +338,29 @@ int vsnprintf(char *__s, size_t __maxlen, const char *__format, va_list args) } itoa(tmpBuf, val, 10, minSize, pad); goto printString; - case 'u': + case 'u': // Unsigned GETVAL(); itoa(tmpBuf, val, 10, minSize, pad); goto printString; - case 'X': + 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': + case 'x': // Lower case hex GETVAL(); itoa(tmpBuf, val, 16, minSize, pad); goto printString; - case 'o': + case 'o': // Octal GETVAL(); itoa(tmpBuf, val, 8, minSize, pad); goto printString; @@ -344,7 +378,7 @@ int vsnprintf(char *__s, size_t __maxlen, const char *__format, va_list args) // String - Null Terminated Array case 's': p = va_arg(args, char*); // Get Argument - if( !CheckString(p) ) p = "(inval)"; // Avoid #PFs + if( !p || !CheckString(p) ) p = "(inval)"; // Avoid #PFs printString: if(!p) p = "(null)"; len = strlen(p); @@ -462,7 +496,6 @@ size_t strlen(const char *__str) } /** - * \fn char *strcpy(char *__str1, const char *__str2) * \brief Copy a string to a new location */ char *strcpy(char *__str1, const char *__str2) @@ -474,18 +507,44 @@ char *strcpy(char *__str1, const char *__str2) } /** - * \fn char *strncpy(char *__str1, const char *__str2, size_t max) * \brief Copy a string to a new location + * \note Copies at most `max` chars */ -char *strncpy(char *__str1, const char *__str2, size_t max) +char *strncpy(char *__str1, const char *__str2, size_t __max) { - while(*__str2 && max-- >= 1) + while(*__str2 && __max-- >= 1) *__str1++ = *__str2++; - if(max) + if(__max) *__str1 = '\0'; // Terminate String return __str1; } +/** + * \brief Append a string to another + */ +char *strcat(char *__dest, const char *__src) +{ + while(*__dest++); + __dest--; + while(*__src) + *__dest++ = *__src++; + *__dest = '\0'; + return __dest; +} + +/** + * \brief Append at most \a n chars to a string from another + * \note At most n+1 chars are written (the dest is always zero terminated) + */ +char *strncat(char *__dest, const char *__src, size_t n) +{ + while(*__dest++); + while(*__src && n-- >= 1) + *__dest++ = *__src++; + *__dest = '\0'; + return __dest; +} + /** * \fn int strcmp(const char *str1, const char *str2) * \brief Compare two strings return the difference between @@ -681,37 +740,39 @@ int WriteUTF8(Uint8 *str, Uint32 Val) { // ASCII if( Val < 128 ) { - *str = Val; + if( str ) { + *str = Val; + } return 1; } // Two Byte if( Val < 0x8000 ) { - *str = 0xC0 | (Val >> 6); - str ++; - *str = 0x80 | (Val & 0x3F); + if( str ) { + *str++ = 0xC0 | (Val >> 6); + *str++ = 0x80 | (Val & 0x3F); + } return 2; } // Three Byte if( Val < 0x10000 ) { - *str = 0xE0 | (Val >> 12); - str ++; - *str = 0x80 | ((Val >> 6) & 0x3F); - str ++; - *str = 0x80 | (Val & 0x3F); + if( str ) { + *str++ = 0xE0 | (Val >> 12); + *str++ = 0x80 | ((Val >> 6) & 0x3F); + *str++ = 0x80 | (Val & 0x3F); + } return 3; } // Four Byte if( Val < 0x110000 ) { - *str = 0xF0 | (Val >> 18); - str ++; - *str = 0x80 | ((Val >> 12) & 0x3F); - str ++; - *str = 0x80 | ((Val >> 6) & 0x3F); - str ++; - *str = 0x80 | (Val & 0x3F); + if( str ) { + *str++ = 0xF0 | (Val >> 18); + *str++ = 0x80 | ((Val >> 12) & 0x3F); + *str++ = 0x80 | ((Val >> 6) & 0x3F); + *str++ = 0x80 | (Val & 0x3F); + } return 4; } @@ -723,28 +784,118 @@ int WriteUTF8(Uint8 *str, Uint32 Val) * \fn Uint64 timestamp(int sec, int mins, int hrs, int day, int month, int year) * \brief Converts a date into an Acess Timestamp */ -Sint64 timestamp(int sec, int mins, int hrs, int day, int month, int year) +Sint64 timestamp(int sec, int min, int hrs, int day, int month, int year) { + int is_leap; Sint64 stamp; - stamp = sec; - stamp += mins*60; - stamp += hrs*3600; - - stamp += day*3600*24; - stamp += month*DAYS_BEFORE[month]*3600*24; - if( ( - ((year&3) == 0 || year%100 != 0) - || (year%100 == 0 && ((year/100)&3) == 0) - ) && month > 1) // Leap year and after feb - stamp += 3600*24; + + if( !(0 <= sec && sec < 60) ) return 0; + if( !(0 <= min && min < 60) ) return 0; + if( !(0 <= hrs && hrs < 24) ) return 0; + if( !(0 <= day && day < 31) ) return 0; + if( !(0 <= month && month < 12) ) return 0; + + stamp = DAYS_BEFORE[month] + day; + + // Every 4 years + // - every 100 years + // + every 400 years + is_leap = (year % 4 == 0) - (year % 100 == 0) + (year % 400 == 0); + ASSERT(is_leap == 0 || is_leap == 1); + + if( is_leap && month > 1 ) // Leap year and after feb + stamp += 1; + + // Get seconds before the first of specified year + year -= 2000; // Base off Y2K + // base year days + total leap year days + stamp += year*365 + (year/400) - (year/100) + (year/4); - stamp += ((365*4+1) * ((year-2000)&~3)) * 3600*24; // Four Year Segments - stamp += ((year-2000)&3) * 365*3600*24; // Inside four year segment + stamp *= 3600*24; stamp += UNIX_TO_2K; + stamp += sec; + stamp += min*60; + stamp += hrs*3600; return stamp * 1000; } +void format_date(tTime TS, int *year, int *month, int *day, int *hrs, int *mins, int *sec, int *ms) +{ + int is_leap = 0, i; + + auto Sint64 DivMod64(Sint64 N, Sint64 D, Sint64 *R); + + Sint64 DivMod64(Sint64 N, Sint64 D, Sint64 *R) + { + int sign = (N < 0) != (D < 0); + if(N < 0) N = -N; + if(D < 0) D = -D; + if(sign) + return -DivMod64U(N, D, (Uint64*)R); + else + return DivMod64U(N, D, (Uint64*)R); + } + + // Get time + // TODO: Leap-seconds? + { + Sint64 rem; + TS = DivMod64( TS, 1000, &rem ); + *ms = rem; + TS = DivMod64( TS, 60, &rem ); + *sec = rem; + TS = DivMod64( TS, 60, &rem ); + *mins = rem; + TS = DivMod64( TS, 24, &rem ); + *hrs = rem; + } + + // Adjust to Y2K + TS -= UNIX_TO_2K/(3600*24); + + // Year (400 yr blocks) - (400/4-3) leap years + *year = 400 * DivMod64( TS, 365*400 + (400/4-3), &TS ); + if( TS < 366 ) // First year in 400 is a leap + is_leap = 1; + else + { + // 100 yr blocks - 100/4-1 leap years + *year += 100 * DivMod64( TS, 365*100 + (100/4-1), &TS ); + if( TS < 366 ) // First year in 100 isn't a leap + is_leap = 0; + else + { + *year += 4 * DivMod64( TS, 365*4 + 1, &TS ); + if( TS < 366 ) // First year in 4 is a leap + is_leap = 1; + else + { + *year += DivMod64( TS, 356, &TS ); + } + } + } + *year += 2000; + + ASSERT(TS >= 0); + + *day = 0; + // Month (if after the first of march, which is 29 Feb in a leap year) + if( is_leap && TS > DAYS_BEFORE[2] ) { + TS -= 1; // Shifts 29 Feb to 28 Feb + *day = 1; + } + // Get what month it is + for( i = 0; i < 12; i ++ ) { + if( TS < DAYS_BEFORE[i] ) + break; + } + *month = i - 1; + // Get day + TS -= DAYS_BEFORE[i-1]; + *day += TS; // Plus offset from leap handling above +} + /** * \fn int rand() * \brief Pseudo random number generator @@ -783,65 +934,38 @@ int rand(void) */ int CheckString(const char *String) { - if( !MM_GetPhysAddr( (tVAddr)String ) ) + tVAddr addr; + int bUser; + + addr = (tVAddr)String; + + if( !MM_GetPhysAddr( addr ) ) return 0; // Check 1st page - if( MM_IsUser( (tVAddr)String ) ) + bUser = MM_IsUser( addr ); + + while( *(char*)addr ) { - // Traverse String - while( *String ) + if( (addr & (PAGE_SIZE-1)) == 0 ) { - if( !MM_IsUser( (tVAddr)String ) ) + if(bUser && !MM_IsUser(addr) ) return 0; - // Increment string pointer - String ++; - } - return 1; - } - else if( MM_GetPhysAddr( (tVAddr)String ) ) - { - // Traverse String - while( *String ) - { - if( !MM_GetPhysAddr( (tVAddr)String ) ) + if(!bUser && !MM_GetPhysAddr(addr) ) return 0; - // Increment string pointer - String ++; } - return 1; + addr ++; } - return 0; + return 1; } /** * \brief Check if a sized memory region is valid memory + * \return Boolean success */ int CheckMem(const void *Mem, int NumBytes) { - tVAddr addr = (tVAddr)Mem; - - if( MM_IsUser( addr ) ) - { - while( NumBytes-- ) - { - if( !MM_IsUser( addr ) ) - return 0; - addr ++; - } - return 1; - } - else if( MM_GetPhysAddr( addr ) ) - { - while( NumBytes-- ) - { - if( !MM_GetPhysAddr( addr ) ) - return 0; - addr ++; - } - return 1; - } - return 0; + return MM_IsValidBuffer( (tVAddr)Mem, NumBytes ); } /* * * \} @@ -869,10 +993,20 @@ int ModUtil_SetIdent(char *Dest, const char *Value) return 1; } +int Hex(char *Dest, size_t Size, const Uint8 *SourceData) +{ + int i; + for( i = 0; i < Size; i ++ ) + { + sprintf(Dest + i*2, "%02x", SourceData[i]); + } + return i*2; +} + /** * \brief Convert a string of hexadecimal digits into a byte stream */ -int UnHex(Uint8 *Dest, size_t DestSize, const char *SourceString) +int UnHex(Uint8 *Dest, size_t DestSize, const char *SourceString) { int i; @@ -902,3 +1036,51 @@ int UnHex(Uint8 *Dest, size_t DestSize, const char *SourceString) } return i/2; } + +Uint16 SwapEndian16(Uint16 Val) +{ + return ((Val&0xFF)<<8) | ((Val>>8)&0xFF); +} +Uint32 SwapEndian32(Uint32 Val) +{ + return ((Val&0xFF)<<24) | ((Val&0xFF00)<<8) | ((Val>>8)&0xFF00) | ((Val>>24)&0xFF); +} + +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( len == 0 || dest == src ) + return dest; + + if( (tVAddr)dest > (tVAddr)src + len ) + return memcpy(dest, src, len); + if( (tVAddr)dest + len < (tVAddr)src ) + return memcpy(dest, src, len); + + // NOTE: Assumes memcpy works forward + if( (tVAddr)dest < (tVAddr)src ) + return memcpy(dest, src, len); + + if( (tVAddr)dest < (tVAddr)src ) + block_size = (tVAddr)src - (tVAddr)dest; + else + block_size = (tVAddr)dest - (tVAddr)src; + + block_size &= ~0xF; + + while(len >= block_size) + { + memcpy(dest, src, block_size); + len -= block_size; + dest += block_size; + src += block_size; + } + memcpy(dest, src, len); + return ret; + +} +