Usermode/libc - scanf() and many other cleanups
[tpg/acess2.git] / Usermode / Libraries / libc.so_src / stdlib.c
1 /*\r
2  * AcessOS Basic C Library\r
3  * stdlib.c\r
4  */\r
5 #include <acess/sys.h>\r
6 #include <stdlib.h>\r
7 #include <stdio.h>\r
8 #include <errno.h>\r
9 #include <ctype.h>\r
10 #include <limits.h>\r
11 #include "lib.h"\r
12 \r
13 #define _stdout 1\r
14 #define _stdin  0\r
15 \r
16 extern void     *_crt0_exit_handler;\r
17 \r
18 // === PROTOTYPES ===\r
19 EXPORT int      atoi(const char *str);\r
20 EXPORT void     exit(int status);\r
21 \r
22 // === GLOBALS ===\r
23 void    (*g_stdlib_exithandler)(void);\r
24 \r
25 // === CODE ===\r
26 void atexit(void (*__func)(void))\r
27 {\r
28         g_stdlib_exithandler = __func;\r
29         // TODO: Replace with meta-function to allow multiple atexit() handlers\r
30         _crt0_exit_handler = __func;    \r
31 }\r
32 \r
33 /**\r
34  * \fn EXPORT void exit(int status)\r
35  * \brief Exit\r
36  */\r
37 EXPORT void exit(int status)\r
38 {\r
39         if( g_stdlib_exithandler )\r
40                 g_stdlib_exithandler();\r
41         _exit(status);\r
42 }\r
43 \r
44 /**\r
45  * \fn EXPORT void qsort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *))\r
46  * \brief Sort an array\r
47  * \note Uses a selection sort\r
48  */\r
49 EXPORT void qsort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *))\r
50 {\r
51         size_t  i, j, min;\r
52         // With 0 items, there's nothing to do and with 1 its already sorted\r
53         if(nmemb == 0 || nmemb == 1)    return;\r
54         \r
55         // SORT!\r
56         for( i = 0; i < (nmemb-1); i++ )\r
57         {\r
58                 min = i;\r
59                 for( j = i+1; j < nmemb; j++ )\r
60                 {\r
61                         if(compar(base+size*j, base + size*min) < 0) {\r
62                                 min = j;\r
63                         }\r
64                 }\r
65                 if (i != min) {\r
66                         char    swap[size];\r
67                         memcpy(swap, base+size*i, size);\r
68                         memcpy(base+size*i, base+size*min, size);\r
69                         memcpy(base+size*i, swap, size);\r
70                 }\r
71         }\r
72 }\r
73 \r
74 EXPORT long long strtoll(const char *str, char **end, int base)\r
75 {\r
76          int    neg = 0;\r
77         long long       ret = 0;\r
78         \r
79         if( !str || base < 0 || base > 36 || base == 1 ) {\r
80                 if(end)\r
81                         *end = (char*)str;\r
82                 errno = EINVAL;\r
83                 return 0;\r
84         }\r
85 \r
86         while( isspace(*str) )\r
87                 str++;\r
88         \r
89         // Check for negative (or positive) sign\r
90         if(*str == '-' || *str == '+') {\r
91                 neg = (*str == '-');\r
92                 str++;\r
93         }\r
94         \r
95         if( base == 0 || base == 16 ) {\r
96                 if( *str == '0' && str[1] == 'x' ) {\r
97                         str += 2;\r
98                         base = 16;\r
99                 }\r
100         }\r
101         \r
102         if( base == 0 && *str == '0' ) {\r
103                 str ++;\r
104                 base = 8;\r
105         }\r
106 \r
107         if( base == 0 )\r
108                 base = 10;\r
109 \r
110         while( *str )\r
111         {\r
112                  int    next = -1;\r
113                 if( base <= 10 ) {\r
114                         if( '0' <= *str && *str <= '0'+base-1 )\r
115                                 next = *str - '0';\r
116                 }\r
117                 else {\r
118                         if( '0' <= *str && *str <= '9' )\r
119                                 next = *str - '0';\r
120                         if( 'A' <= *str && *str <= 'A'+base-10-1 )\r
121                                 next = *str - 'A';\r
122                         if( 'a' <= *str && *str <= 'a'+base-10-1 )\r
123                                 next = *str - 'a';\r
124                 }\r
125                 if( next < 0 )\r
126                         break;\r
127                 ret *= base;\r
128                 ret += next;\r
129                 str ++;\r
130         }\r
131 \r
132         if( neg )\r
133                 ret = -ret;     \r
134 \r
135         if(end)\r
136                 *end = (char*)str;\r
137         return ret;\r
138 }\r
139 \r
140 EXPORT long strtol(const char *str, char **end, int base)\r
141 {\r
142         long long tmp = strtoll(str, end, base);\r
143         if( tmp > LONG_MAX || tmp < LONG_MIN ) {\r
144                 errno = ERANGE;\r
145                 return (tmp > LONG_MAX) ? LONG_MAX : LONG_MIN;\r
146         }\r
147         return tmp;\r
148 }\r
149 \r
150 /**\r
151  * \fn EXPORT int atoi(const char *str)\r
152  * \brief Convert a string to an integer\r
153  */\r
154 EXPORT int atoi(const char *str)\r
155 {\r
156         long long       tmp = strtoll(str, NULL, 0);\r
157         if( tmp > INT_MAX || tmp < INT_MIN ) {\r
158                 errno = ERANGE;\r
159                 return (tmp > INT_MAX) ? INT_MAX : INT_MIN;\r
160         }\r
161         return tmp;\r
162 }\r
163 \r
164 int abs(int j) { return j < 0 ? -j : j; }\r
165 long int labs(long int j) { return j < 0 ? -j : j; }\r
166 \r

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