#include <acess/sys.h>\r
#include <stdlib.h>\r
#include <stdio.h>\r
-#include <errno.h>\r
-#include <ctype.h>\r
-#include <limits.h>\r
#include "lib.h"\r
\r
-#define _stdout 1\r
-#define _stdin 0\r
+extern void _stdio_cleanup(void);\r
\r
-extern void *_crt0_exit_handler;\r
+#define MAX_ATEXIT_HANDLERS 64 // Standard defines >=32\r
\r
// === PROTOTYPES ===\r
EXPORT int atoi(const char *str);\r
EXPORT void exit(int status);\r
\r
// === GLOBALS ===\r
-void (*g_stdlib_exithandler)(void);\r
+typedef void (*stdlib_exithandler_t)(void);\r
+stdlib_exithandler_t g_stdlib_exithandlers[MAX_ATEXIT_HANDLERS];\r
+ int g_stdlib_num_exithandlers;\r
\r
// === CODE ===\r
-void atexit(void (*__func)(void))\r
+void _call_atexit_handlers(void)\r
{\r
- g_stdlib_exithandler = __func;\r
- // TODO: Replace with meta-function to allow multiple atexit() handlers\r
- _crt0_exit_handler = __func; \r
+ int i;\r
+ for( i = g_stdlib_num_exithandlers; i --; )\r
+ g_stdlib_exithandlers[i]();\r
+ _stdio_cleanup();\r
+}\r
+\r
+EXPORT void atexit(void (*__func)(void))\r
+{\r
+ if( g_stdlib_num_exithandlers < MAX_ATEXIT_HANDLERS )\r
+ {\r
+ g_stdlib_exithandlers[g_stdlib_num_exithandlers++] = __func;\r
+ }\r
}\r
\r
/**\r
*/\r
EXPORT void exit(int status)\r
{\r
- if( g_stdlib_exithandler )\r
- g_stdlib_exithandler();\r
+ _call_atexit_handlers();\r
_exit(status);\r
}\r
\r
*/\r
EXPORT void qsort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *))\r
{\r
- int i, j, min;\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
}\r
}\r
\r
-EXPORT long long strtoll(const char *str, char **end, int base)\r
-{\r
- int neg = 0;\r
- long long ret = 0;\r
- \r
- if( !str || base < 0 || base > 36 || base == 1 ) {\r
- if(end)\r
- *end = (char*)str;\r
- errno = EINVAL;\r
- return 0;\r
- }\r
-\r
- while( isspace(*str) )\r
- str++;\r
- \r
- // Check for negative (or positive) sign\r
- if(*str == '-' || *str == '+') {\r
- neg = (*str == '-');\r
- str++;\r
- }\r
- \r
- if( base == 0 || base == 16 ) {\r
- if( *str == '0' && str[1] == 'x' ) {\r
- str += 2;\r
- base = 16;\r
- }\r
- }\r
- \r
- if( base == 0 && *str == '0' ) {\r
- str ++;\r
- base = 8;\r
- }\r
-\r
- if( base == 0 )\r
- base = 10;\r
-\r
- while( *str )\r
- {\r
- int next = -1;\r
- if( base <= 10 ) {\r
- if( '0' <= *str && *str <= '0'+base-1 )\r
- next = *str - '0';\r
- }\r
- else {\r
- if( '0' <= *str && *str <= '9' )\r
- next = *str - '0';\r
- if( 'A' <= *str && *str <= 'A'+base-10-1 )\r
- next = *str - 'A';\r
- if( 'a' <= *str && *str <= 'a'+base-10-1 )\r
- next = *str - 'a';\r
- }\r
- if( next < 0 )\r
- break;\r
- ret *= base;\r
- ret += next;\r
- str ++;\r
- }\r
-\r
- if( neg )\r
- ret = -ret; \r
-\r
- if(end)\r
- *end = (char*)str;\r
- return ret;\r
-}\r
-\r
-EXPORT long strtol(const char *str, char **end, int base)\r
-{\r
- long long tmp = strtoll(str, end, base);\r
- if( tmp > LONG_MAX || tmp < LONG_MIN ) {\r
- errno = ERANGE;\r
- return (tmp > LONG_MAX) ? LONG_MAX : LONG_MIN;\r
- }\r
- return tmp;\r
-}\r
-\r
-/**\r
- * \fn EXPORT int atoi(const char *str)\r
- * \brief Convert a string to an integer\r
- */\r
-EXPORT int atoi(const char *str)\r
-{\r
- long long tmp = strtoll(str, NULL, 0);\r
- if( tmp > INT_MAX || tmp < INT_MIN ) {\r
- errno = ERANGE;\r
- return (tmp > INT_MAX) ? INT_MAX : INT_MIN;\r
- }\r
- return tmp;\r
-}\r
\r
int abs(int j) { return j < 0 ? -j : j; }\r
long int labs(long int j) { return j < 0 ? -j : j; }\r