Kernel/armv7 - Fixed for threading changes
[tpg/acess2.git] / Kernel / lib.c
index 369b7b0..ca37433 100644 (file)
@@ -39,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);
@@ -191,11 +194,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);\
@@ -215,15 +214,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; }
@@ -232,9 +240,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
@@ -490,11 +498,11 @@ char *strcpy(char *__str1, const char *__str2)
  * \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;
 }
@@ -720,37 +728,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;
        }
        
@@ -762,28 +772,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

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