/*\r
-AcessOS Basic C Library\r
-\r
-stdlib.c\r
-*/\r
+ * AcessOS Basic C Library\r
+ * stdlib.c\r
+ */\r
#include <acess/sys.h>\r
#include <stdlib.h>\r
+#include <stdio.h>\r
#include "lib.h"\r
\r
-int _stdout = 1;\r
-int _stdin = 2;\r
+extern void *_crt0_exit_handler;\r
\r
-EXPORT int puts(const char *str);\r
-EXPORT void itoa(char *buf, unsigned long num, int base, int minLength, char pad);\r
+// === PROTOTYPES ===\r
EXPORT int atoi(const char *str);\r
-EXPORT int puts(const char *str);\r
-EXPORT int ssprintfv(char *format, va_list args);\r
-EXPORT void sprintfv(char *buf, char *format, va_list args);\r
-EXPORT int printf(const char *format, ...);\r
-EXPORT int strlen(const char *str);\r
-EXPORT int strcmp(char *str1, char *str2);\r
-EXPORT int strncmp(char *str1, char *str2, size_t len);\r
-EXPORT char *strcpy(char *dst, const char *src);\r
-\r
-// === CODE ===\r
-EXPORT int putchar(int ch)\r
-{\r
- return write(_stdout, 1, (char*)&ch);\r
-}\r
-\r
-EXPORT int puts(const char *str)\r
-{\r
- int len;\r
- \r
- if(!str) return 0;\r
- len = strlen(str);\r
- \r
- len = write(_stdout, len, (char*)str);\r
- write(_stdout, 1, "\n");\r
- return len;\r
-}\r
+EXPORT void exit(int status);\r
\r
-//sprintfv\r
-/**\r
- \fn EXPORT void sprintfv(char *buf, char *format, va_list args)\r
- \brief Prints a formatted string to a buffer\r
- \param buf Pointer - Destination Buffer\r
- \param format String - Format String\r
- \param args VarArgs List - Arguments\r
-*/\r
-EXPORT void sprintfv(char *buf, char *format, va_list args)\r
-{\r
- char tmp[33];\r
- int c, arg, minSize;\r
- int pos = 0;\r
- char *p;\r
- char pad;\r
+// === GLOBALS ===\r
+void (*g_stdlib_exithandler)(void);\r
\r
- tmp[32] = '\0';\r
- \r
- while((c = *format++) != 0)\r
- {\r
- //SysDebug("c = '%c'\n", c);\r
- if (c != '%') {\r
- buf[pos++] = c;\r
- continue;\r
- }\r
- \r
- c = *format++;\r
- if(c == '%') {\r
- buf[pos++] = '%';\r
- continue;\r
- }\r
- \r
- // Padding\r
- if(c == '0') {\r
- pad = '0';\r
- c = *format++;\r
- } else\r
- pad = ' ';\r
- minSize = 0;\r
- if('1' <= c && c <= '9')\r
- {\r
- while('0' <= c && c <= '9')\r
- {\r
- minSize *= 10;\r
- minSize += c - '0';\r
- c = *format++;\r
- }\r
- }\r
- \r
- p = tmp;\r
- \r
- // Get Argument\r
- arg = va_arg(args, int);\r
- // Get Type\r
- switch (c) {\r
- case 'd':\r
- case 'i':\r
- if(arg < 0) {\r
- buf[pos++] = '-';\r
- arg = -arg;\r
- }\r
- itoa(tmp, arg, 10, minSize, pad);\r
- goto sprintf_puts;\r
- // break;\r
- case 'u':\r
- itoa(tmp, arg, 10, minSize, pad);\r
- goto sprintf_puts;\r
- // break;\r
- case 'x':\r
- itoa(tmp, arg, 16, minSize, pad);\r
- goto sprintf_puts;\r
- // break;\r
- case 'o':\r
- itoa(tmp, arg, 8, minSize, pad);\r
- goto sprintf_puts;\r
- // break;\r
- case 'b':\r
- itoa(tmp, arg, 2, minSize, pad);\r
- goto sprintf_puts;\r
- // break;\r
-\r
- case 's':\r
- p = (void*)arg;\r
- sprintf_puts:\r
- if(!p) p = "(null)";\r
- while(*p) buf[pos++] = *p++;\r
- break;\r
-\r
- default:\r
- buf[pos++] = arg;\r
- break;\r
- }\r
- }\r
- buf[pos++] = '\0';\r
-}\r
-/*\r
-ssprintfv\r
-- Size, Stream, Print Formated, Variable Argument List\r
-*/\r
-/**\r
- \fn EXPORT int ssprintfv(char *format, va_list args)\r
- \brief Gets the total character count from a formatted string\r
- \param format String - Format String\r
- \param args VarArgs - Argument List\r
-*/\r
-EXPORT int ssprintfv(char *format, va_list args)\r
+// === CODE ===\r
+void atexit(void (*__func)(void))\r
{\r
- char tmp[33];\r
- int c, arg, minSize;\r
- int len = 0;\r
- char *p;\r
- char pad;\r
-\r
- tmp[32] = '\0';\r
- \r
- while((c = *format++) != 0)\r
- {\r
- if (c != '%') {\r
- len++;\r
- continue;\r
- }\r
- \r
- c = *format++;\r
- \r
- // Literal '%'\r
- if(c == '%') {\r
- len++;\r
- continue;\r
- }\r
- \r
- // Padding\r
- if(c == '0') {\r
- pad = '0';\r
- c = *format++;\r
- } else\r
- pad = ' ';\r
- minSize = 0;\r
- if('1' <= c && c <= '9')\r
- {\r
- while('0' <= c && c <= '9')\r
- {\r
- minSize *= 10;\r
- minSize += c - '0';\r
- c = *format++;\r
- }\r
- }\r
- \r
- p = tmp;\r
- arg = va_arg(args, int);\r
- switch (c) { \r
- case 'd':\r
- case 'i':\r
- if(arg < 0) {\r
- len ++;\r
- arg = -arg;\r
- }\r
- itoa(tmp, arg, 10, minSize, pad);\r
- goto sprintf_puts;\r
- case 'u':\r
- itoa(tmp, arg, 10, minSize, pad);\r
- goto sprintf_puts;\r
- case 'x':\r
- itoa(tmp, arg, 16, minSize, pad);\r
- goto sprintf_puts;\r
- case 'o':\r
- itoa(tmp, arg, 8, minSize, pad);\r
- p = tmp;\r
- goto sprintf_puts;\r
- case 'b':\r
- itoa(tmp, arg, 2, minSize, pad);\r
- goto sprintf_puts;\r
-\r
- case 's':\r
- p = (char*)arg;\r
- sprintf_puts:\r
- if(!p) p = "(null)";\r
- while(*p) len++, p++;\r
- break;\r
-\r
- default:\r
- len ++;\r
- break;\r
- }\r
- }\r
- return len;\r
+ g_stdlib_exithandler = __func;\r
+ // TODO: Replace with meta-function to allow multiple atexit() handlers\r
+ _crt0_exit_handler = __func; \r
}\r
\r
-const char cUCDIGITS[] = "0123456789ABCDEF";\r
/**\r
- * \fn static void itoa(char *buf, unsigned long num, int base, int minLength, char pad)\r
- * \brief Convert an integer into a character string\r
+ * \fn EXPORT void exit(int status)\r
+ * \brief Exit\r
*/\r
-EXPORT void itoa(char *buf, unsigned long num, int base, int minLength, char pad)\r
+EXPORT void exit(int status)\r
{\r
- char tmpBuf[32];\r
- int pos=0, i;\r
-\r
- if(!buf) return;\r
- if(base > 16) {\r
- buf[0] = 0;\r
- return;\r
- }\r
- \r
- while(num > base-1) {\r
- tmpBuf[pos] = cUCDIGITS[ num % base ];\r
- num = (long) num / base; //Shift {number} right 1 digit\r
- pos++;\r
- }\r
-\r
- tmpBuf[pos++] = cUCDIGITS[ num % base ]; //Last digit of {number}\r
- i = 0;\r
- minLength -= pos;\r
- while(minLength-- > 0) buf[i++] = pad;\r
- while(pos-- > 0) buf[i++] = tmpBuf[pos]; //Reverse the order of characters\r
- buf[i] = 0;\r
+ if( g_stdlib_exithandler )\r
+ g_stdlib_exithandler();\r
+ _exit(status);\r
}\r
\r
/**\r
+ * \fn EXPORT void qsort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *))\r
+ * \brief Sort an array\r
+ * \note Uses a selection sort\r
*/\r
-EXPORT int atoi(const char *str)\r
+EXPORT void qsort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *))\r
{\r
- int neg = 0;\r
- int ret = 0;\r
- \r
- // NULL Check\r
- if(!str) return 0;\r
- \r
- while(*str == ' ' || *str == '\t') str++;\r
+ size_t i, j, min;\r
+ // With 0 items, there's nothing to do and with 1 its already sorted\r
+ if(nmemb == 0 || nmemb == 1) return;\r
\r
- // Check for negative\r
- if(*str == '-') {\r
- neg = 1;\r
- str++;\r
- }\r
- \r
- if(*str == '0') {\r
- str ++;\r
- if(*str == 'x') {\r
- str++;\r
- // Hex\r
- while( ('0' <= *str && *str <= '9')\r
- || ('A' <= *str && *str <= 'F' )\r
- || ('a' <= *str && *str <= 'f' )\r
- )\r
- {\r
- ret *= 16;\r
- if(*str <= '9') {\r
- ret += *str - '0';\r
- } else if (*str <= 'F') {\r
- ret += *str - 'A' + 10;\r
- } else {\r
- ret += *str - 'a' + 10;\r
- }\r
- str++;\r
- }\r
- } else {\r
- // Octal\r
- while( '0' <= *str && *str <= '7' )\r
- {\r
- ret *= 8;\r
- ret += *str - '0';\r
- str++;\r
+ // SORT!\r
+ for( i = 0; i < (nmemb-1); i++ )\r
+ {\r
+ min = i;\r
+ for( j = i+1; j < nmemb; j++ )\r
+ {\r
+ if(compar(base+size*j, base + size*min) < 0) {\r
+ min = j;\r
}\r
}\r
- } else {\r
- // Decimal\r
- while( '0' <= *str && *str <= '9' )\r
- {\r
- ret *= 10;\r
- ret += *str - '0';\r
- str++;\r
+ if (i != min) {\r
+ char swap[size];\r
+ memcpy(swap, base+size*i, size);\r
+ memcpy(base+size*i, base+size*min, size);\r
+ memcpy(base+size*i, swap, size);\r
}\r
}\r
- \r
- // Negate if needed\r
- if(neg) ret = -ret;\r
- return ret;\r
-}\r
-\r
-//printf\r
-EXPORT int printf(const char *format, ...)\r
-{\r
- int size;\r
- char *buf;\r
- va_list args;\r
- \r
- va_start(args, format);\r
- size = ssprintfv((char*)format, args);\r
- va_end(args);\r
- \r
- buf = (char*)malloc(size+1);\r
- buf[size] = '\0';\r
- \r
- va_start(args, format);\r
- sprintfv(buf, (char*)format, args);\r
- va_end(args);\r
- \r
- \r
- write(_stdout, size+1, buf);\r
- \r
- free(buf);\r
- return size;\r
-}\r
-\r
-EXPORT int sprintf(const char *buf, char *format, ...)\r
-{\r
- va_list args;\r
- va_start(args, format);\r
- sprintfv((char*)buf, (char*)format, args);\r
- va_end(args);\r
- return 1;\r
-}\r
-\r
-\r
-//MEMORY\r
-EXPORT int strcmp(char *s1, char *s2)\r
-{\r
- while(*s1 == *s2 && *s1 != '\0' && *s2 != '\0') {\r
- s1++; s2++;\r
- }\r
- return (int)*s1 - (int)*s2;\r
-}\r
-EXPORT char *strcpy(char *dst, const char *src)\r
-{\r
- char *_dst = dst;\r
- while(*src) {\r
- *dst = *src;\r
- src++; dst++;\r
- }\r
- *dst = '\0';\r
- return _dst;\r
-}\r
-EXPORT int strlen(const char *str)\r
-{\r
- int retval;\r
- for(retval = 0; *str != '\0'; str++)\r
- retval++;\r
- return retval;\r
}\r
\r
-EXPORT int strncmp(char *s1, char *s2, size_t len)\r
-{\r
- while(--len && *s1 == *s2 && *s1 != '\0' && *s2 != '\0') {\r
- s1++; s2++;\r
- }\r
- return (int)*s1 - (int)*s2;\r
-}\r
\r
-EXPORT void *memcpy(void *dest, void *src, unsigned int count)\r
-{\r
- char *sp = (char *)src;\r
- char *dp = (char *)dest;\r
- for(;count--;) *dp++ = *sp++;\r
- return dest;\r
-}\r
+int abs(int j) { return j < 0 ? -j : j; }\r
+long int labs(long int j) { return j < 0 ? -j : j; }\r
\r
-EXPORT void *memmove(void *dest, void *src, unsigned int count)\r
-{\r
- char *sp = (char *)src;\r
- char *dp = (char *)dest;\r
- // Check if corruption will happen\r
- if( (unsigned int)dest > (unsigned int)src && (unsigned int)dest < (unsigned int)src+count )\r
- for(;count--;) dp[count] = sp[count];\r
- else\r
- for(;count--;) *dp++ = *sp++;\r
- return dest;\r
-}\r