X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Usermode%2FLibraries%2Flibc.so_src%2Fstdlib.c;h=e05ddc2d4ed07316e1958507402cd992f91df514;hb=7d1c355c2843a140d5c474567c690402793aaa36;hp=44dc55fa7308f881b1eb62d99a59d668cb13c0c1;hpb=17e16b3110b4c5124b0707435e0427993d696545;p=tpg%2Facess2.git diff --git a/Usermode/Libraries/libc.so_src/stdlib.c b/Usermode/Libraries/libc.so_src/stdlib.c index 44dc55fa..e05ddc2d 100644 --- a/Usermode/Libraries/libc.so_src/stdlib.c +++ b/Usermode/Libraries/libc.so_src/stdlib.c @@ -1,409 +1,83 @@ /* -AcessOS Basic C Library - -stdlib.c -*/ + * AcessOS Basic C Library + * stdlib.c + */ #include #include +#include #include "lib.h" -int _stdout = 1; -int _stdin = 2; +extern void _stdio_cleanup(void); + +#define MAX_ATEXIT_HANDLERS 64 // Standard defines >=32 -EXPORT int puts(const char *str); -EXPORT void itoa(char *buf, unsigned long num, int base, int minLength, char pad); +// === PROTOTYPES === EXPORT int atoi(const char *str); -EXPORT int puts(const char *str); -EXPORT int ssprintfv(char *format, va_list args); -EXPORT void sprintfv(char *buf, char *format, va_list args); -EXPORT int printf(const char *format, ...); -EXPORT int strlen(const char *str); -EXPORT int strcmp(char *str1, char *str2); -EXPORT int strncmp(char *str1, char *str2, size_t len); -EXPORT char *strcpy(char *dst, const char *src); +EXPORT void exit(int status); -// === CODE === -EXPORT int putchar(int ch) -{ - return write(_stdout, 1, (char*)&ch); -} +// === GLOBALS === +typedef void (*stdlib_exithandler_t)(void); +stdlib_exithandler_t g_stdlib_exithandlers[MAX_ATEXIT_HANDLERS]; + int g_stdlib_num_exithandlers; -EXPORT int puts(const char *str) +// === CODE === +void _call_atexit_handlers(void) { - int len; - - if(!str) return 0; - len = strlen(str); - - len = write(_stdout, len, (char*)str); - write(_stdout, 1, "\n"); - return len; + int i; + for( i = g_stdlib_num_exithandlers; i --; ) + g_stdlib_exithandlers[i](); + _stdio_cleanup(); } -//sprintfv -/** - \fn EXPORT void sprintfv(char *buf, char *format, va_list args) - \brief Prints a formatted string to a buffer - \param buf Pointer - Destination Buffer - \param format String - Format String - \param args VarArgs List - Arguments -*/ -EXPORT void sprintfv(char *buf, char *format, va_list args) -{ - char tmp[33]; - int c, arg, minSize; - int pos = 0; - char *p; - char pad; - - tmp[32] = '\0'; - - while((c = *format++) != 0) - { - //SysDebug("c = '%c'\n", c); - if (c != '%') { - buf[pos++] = c; - continue; - } - - c = *format++; - if(c == '%') { - buf[pos++] = '%'; - continue; - } - - // Padding - if(c == '0') { - pad = '0'; - c = *format++; - } else - pad = ' '; - minSize = 0; - if('1' <= c && c <= '9') - { - while('0' <= c && c <= '9') - { - minSize *= 10; - minSize += c - '0'; - c = *format++; - } - } - - p = tmp; - - // Get Argument - arg = va_arg(args, int); - // Get Type - switch (c) { - case 'd': - case 'i': - if(arg < 0) { - buf[pos++] = '-'; - arg = -arg; - } - itoa(tmp, arg, 10, minSize, pad); - goto sprintf_puts; - // break; - case 'u': - itoa(tmp, arg, 10, minSize, pad); - goto sprintf_puts; - // break; - case 'x': - itoa(tmp, arg, 16, minSize, pad); - goto sprintf_puts; - // break; - case 'o': - itoa(tmp, arg, 8, minSize, pad); - goto sprintf_puts; - // break; - case 'b': - itoa(tmp, arg, 2, minSize, pad); - goto sprintf_puts; - // break; - - case 's': - p = (void*)arg; - sprintf_puts: - if(!p) p = "(null)"; - while(*p) buf[pos++] = *p++; - break; - - default: - buf[pos++] = arg; - break; - } - } - buf[pos++] = '\0'; -} -/* -ssprintfv -- Size, Stream, Print Formated, Variable Argument List -*/ -/** - \fn EXPORT int ssprintfv(char *format, va_list args) - \brief Gets the total character count from a formatted string - \param format String - Format String - \param args VarArgs - Argument List -*/ -EXPORT int ssprintfv(char *format, va_list args) +EXPORT void atexit(void (*__func)(void)) { - char tmp[33]; - int c, arg, minSize; - int len = 0; - char *p; - char pad; - - tmp[32] = '\0'; - - while((c = *format++) != 0) + if( g_stdlib_num_exithandlers < MAX_ATEXIT_HANDLERS ) { - if (c != '%') { - len++; - continue; - } - - c = *format++; - - // Literal '%' - if(c == '%') { - len++; - continue; - } - - // Padding - if(c == '0') { - pad = '0'; - c = *format++; - } else - pad = ' '; - minSize = 0; - if('1' <= c && c <= '9') - { - while('0' <= c && c <= '9') - { - minSize *= 10; - minSize += c - '0'; - c = *format++; - } - } - - p = tmp; - arg = va_arg(args, int); - switch (c) { - case 'd': - case 'i': - if(arg < 0) { - len ++; - arg = -arg; - } - itoa(tmp, arg, 10, minSize, pad); - goto sprintf_puts; - case 'u': - itoa(tmp, arg, 10, minSize, pad); - goto sprintf_puts; - case 'x': - itoa(tmp, arg, 16, minSize, pad); - goto sprintf_puts; - case 'o': - itoa(tmp, arg, 8, minSize, pad); - p = tmp; - goto sprintf_puts; - case 'b': - itoa(tmp, arg, 2, minSize, pad); - goto sprintf_puts; - - case 's': - p = (char*)arg; - sprintf_puts: - if(!p) p = "(null)"; - while(*p) len++, p++; - break; - - default: - len ++; - break; - } - } - return len; + g_stdlib_exithandlers[g_stdlib_num_exithandlers++] = __func; + } } -const char cUCDIGITS[] = "0123456789ABCDEF"; /** - * \fn static void itoa(char *buf, unsigned long num, int base, int minLength, char pad) - * \brief Convert an integer into a character string + * \fn EXPORT void exit(int status) + * \brief Exit */ -EXPORT void itoa(char *buf, unsigned long num, int base, int minLength, char pad) +EXPORT void exit(int status) { - char tmpBuf[32]; - int pos=0, i; - - if(!buf) return; - if(base > 16) { - buf[0] = 0; - return; - } - - while(num > base-1) { - tmpBuf[pos] = cUCDIGITS[ num % base ]; - num = (long) num / base; //Shift {number} right 1 digit - pos++; - } - - tmpBuf[pos++] = cUCDIGITS[ num % base ]; //Last digit of {number} - 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; + _call_atexit_handlers(); + _exit(status); } /** + * \fn EXPORT void qsort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *)) + * \brief Sort an array + * \note Uses a selection sort */ -EXPORT int atoi(const char *str) +EXPORT void qsort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *)) { - int neg = 0; - int ret = 0; + size_t i, j, min; + // With 0 items, there's nothing to do and with 1 its already sorted + if(nmemb == 0 || nmemb == 1) return; - // NULL Check - if(!str) return 0; - - while(*str == ' ' || *str == '\t') str++; - - // Check for negative - if(*str == '-') { - neg = 1; - str++; - } - - if(*str == '0') { - str ++; - if(*str == 'x') { - str++; - // Hex - while( ('0' <= *str && *str <= '9') - || ('A' <= *str && *str <= 'F' ) - || ('a' <= *str && *str <= 'f' ) - ) - { - ret *= 16; - if(*str <= '9') { - ret += *str - '0'; - } else if (*str <= 'F') { - ret += *str - 'A' + 10; - } else { - ret += *str - 'a' + 10; - } - str++; - } - } else { - // Octal - while( '0' <= *str && *str <= '7' ) - { - ret *= 8; - ret += *str - '0'; - str++; + // SORT! + for( i = 0; i < (nmemb-1); i++ ) + { + min = i; + for( j = i+1; j < nmemb; j++ ) + { + if(compar(base+size*j, base + size*min) < 0) { + min = j; } } - } else { - // Decimal - while( '0' <= *str && *str <= '9' ) - { - ret *= 10; - ret += *str - '0'; - str++; + if (i != min) { + char swap[size]; + memcpy(swap, base+size*i, size); + memcpy(base+size*i, base+size*min, size); + memcpy(base+size*i, swap, size); } } - - // Negate if needed - if(neg) ret = -ret; - return ret; } -//printf -EXPORT int printf(const char *format, ...) -{ - int size; - char *buf; - va_list args; - - va_start(args, format); - size = ssprintfv((char*)format, args); - va_end(args); - - buf = (char*)malloc(size+1); - buf[size] = '\0'; - - va_start(args, format); - sprintfv(buf, (char*)format, args); - va_end(args); - - - write(_stdout, size+1, buf); - - free(buf); - return size; -} -EXPORT int sprintf(const char *buf, char *format, ...) -{ - va_list args; - va_start(args, format); - sprintfv((char*)buf, (char*)format, args); - va_end(args); - return 1; -} - - -//MEMORY -EXPORT int strcmp(char *s1, char *s2) -{ - while(*s1 == *s2 && *s1 != '\0' && *s2 != '\0') { - s1++; s2++; - } - return (int)*s1 - (int)*s2; -} -EXPORT char *strcpy(char *dst, const char *src) -{ - char *_dst = dst; - while(*src) { - *dst = *src; - src++; dst++; - } - *dst = '\0'; - return _dst; -} -EXPORT int strlen(const char *str) -{ - int retval; - for(retval = 0; *str != '\0'; str++) - retval++; - return retval; -} - -EXPORT int strncmp(char *s1, char *s2, size_t len) -{ - while(--len && *s1 == *s2 && *s1 != '\0' && *s2 != '\0') { - s1++; s2++; - } - return (int)*s1 - (int)*s2; -} +int abs(int j) { return j < 0 ? -j : j; } +long int labs(long int j) { return j < 0 ? -j : j; } -EXPORT void *memcpy(void *dest, void *src, unsigned int count) -{ - char *sp = (char *)src; - char *dp = (char *)dest; - for(;count--;) *dp++ = *sp++; - return dest; -} - -EXPORT void *memmove(void *dest, void *src, unsigned int count) -{ - char *sp = (char *)src; - char *dp = (char *)dest; - // Check if corruption will happen - if( (unsigned int)dest > (unsigned int)src && (unsigned int)dest < (unsigned int)src+count ) - for(;count--;) dp[count] = sp[count]; - else - for(;count--;) *dp++ = *sp++; - return dest; -}