stdlibc: small changes
[meinos.git] / apps / lib / stdlibc / stdlib.c
blob803f3f18c3f020527566ed812c2a329f22213b86
1 /*
2 meinOS - A unix-like x86 microkernel operating system
3 Copyright (C) 2008 Janosch Gräf <janosch.graef@gmx.net>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include <sys/types.h>
20 #include <string.h>
21 #include <errno.h>
22 #include <stdlib.h>
23 #include <limits.h>
24 #include <ctype.h>
25 #include <llist.h>
26 #include <syscall.h>
27 #include <time.h>
28 #include <stdint.h>
30 // some variables/functions needed
31 void stdio_init(); ///< @see stdio.h
32 void env_init(); ///< @see env.c
33 llist_t atexit_list; ///< @see stdlib.c
34 void _close_all_filehandles(); ///< @see files.c
35 void _signal_init(); ///< @see signal.c
36 void _fs_init(char *_stdin,char *_stdout,char *_stderr); ///< @see apps/lib/stdlibc/files.c
38 void _stdlib_init_pre() {
39 rand_seed = rand_seed%RAND_MAX;
40 errno = 0;
41 atexit_list = llist_create();
42 _signal_init();
44 #include <stdio.h>
45 void _stdlib_init_post(char *_stdin,char *_stdout,char *_stderr) {
46 env_init();
47 _fs_init(_stdin,_stdout,_stderr);
48 stdio_init();
51 /**
52 * Exits process
53 * @param result Program result value
54 * @see also used by crt0.asm
56 void exit(int result) {
57 void (*func)(void);
58 while ((func = llist_pop(atexit_list))!=NULL) func();
59 _Exit(result);
62 /**
63 * Closes all filehandles and exits
64 * @param result Program result
66 void _Exit(int result) {
67 _close_all_filehandles();
68 syscall_call(SYSCALL_PROC_EXIT,1,result);
71 /**
72 * Registers a function to run at process termination
73 * @param func Function
74 * @return 0=successful; -1=failed
76 int atexit(void (*func)(void)) {
77 return llist_push(atexit_list,func)!=NULL?0:-1;
80 /**
81 * Converts a string to a number
82 * @param str String representing a number
83 * @return Represented number from string
85 int atoi(const char *str) {
86 size_t len,i;
87 int num = 0;
88 int sign = 0;
90 len = strlen(str);
91 for (i=0;i<len;i++) {
92 if (str[i]=='+') sign = 0;
93 else if (str[i]=='-') sign = 1;
94 else num = num*10+str[i]-'0';
96 if (sign) num *= -1;
97 return num;
101 * Returns absolute number
102 * @param num Number to get absolute number of
103 * @return Absolute number
105 int abs(int num) {
106 if (num<0) num = -num;
107 return num;
111 * Devides a number
112 * @param numer Numer
113 * @param denom Denom
114 * @return Devision result
116 div_t div(int numer, int denom) {
117 div_t res;
118 res.quot = numer/denom;
119 res.rem = numer%denom;
120 return res;
124 * Binary search a sorted table
125 * @param vdkey Key
126 * @param vdbase Base
127 * @param nel Num elements
128 * @param width Size of an element
129 * @param compar Function called when match found
131 void *bsearch(const void *vdkey,const void *vdbase,size_t nel,size_t width,int (*compar)(const void *, const void *)) {
132 char *key = (char*)vdkey;
133 char *cpkey = memcpy(malloc(width),key,width);
134 char *base = (char*)vdbase;
135 void *last = NULL;
136 size_t found = 0;
137 size_t i;
139 for (i=0;i<nel;i++) {
140 if (*(base+nel*width)==*key) found++;
141 if (found==width) {
142 char *cpbase = memcpy(malloc(width),base,width);
143 if (compar!=NULL) compar(key,base);
144 *key = *cpkey;
145 *base = *cpbase;
146 free(cpbase);
147 found = 0;
148 last = (void*)(vdbase+nel*width);
152 free(cpkey);
153 return last;
157 * Gets a new page from kernel
158 * @param size How many bytes (should be devidable by PAGESIZE)
159 * @return Pointer to new page
161 void *sbrk(intptr_t size) {
162 return (void*)syscall_call(SYSCALL_MEM_MALLOC,1,size);
165 /// @todo FIXME
166 int rand() {
167 return 0xD00FC0DE;
168 const int N = 624;
169 const int M = 397;
170 const unsigned A[2] = { 0, 0x9908b0df };
171 const unsigned HI = 0x80000000;
172 const unsigned LO = 0x7fffffff;
174 static unsigned *y;
175 static int init = 0;
176 static int index;
177 if (!init) {
178 index = N;
179 init = 1;
182 if (index >= N) {
183 if (index > N) {
184 // initialisiere y mit Pseudozufallszahlen:
185 y = calloc(N,sizeof(unsigned int));
186 unsigned r = 9, s = 3402;
187 int i;
188 for (i=0 ; i<N ; ++i) {
189 r = 509845221 * r + 3;
190 s *= s + 1;
191 y[i] = s + (r >> 10);
194 unsigned h;
195 int k;
196 for (k=0 ; k<N-M ; ++k) {
197 h = (y[k] & HI) | (y[k+1] & LO);
198 y[k] = y[k+M] ^ (h >> 1) ^ A[h & 1];
200 for (k=N-M ; k<N-1 ; ++k) {
201 h = (y[k] & HI) | (y[k+1] & LO);
202 y[k] = y[k+(M-N)] ^ (h >> 1) ^ A[h & 1];
204 h = (y[N-1] & HI) | (y[0] & LO);
205 y[N-1] = y[M-1] ^ (h >> 1) ^ A[h & 1];
206 index = 0;
209 unsigned e = y[index++];
210 // tempering:
211 e ^= (e >> 11);
212 e ^= (e << 7) & 0x9d2c5680;
213 e ^= (e << 15) & 0xefc60000;
214 e ^= (e >> 18);
215 return e%RAND_MAX;