f74caa349e4e146b9e84a570a5747dc0abb94845
[mes.git] / libc / mlibc.c
1 /* -*-comment-start: "//";comment-end:""-*-
2  * Mes --- Maxwell Equations of Software
3  * Copyright © 2016,2017 Jan Nieuwenhuizen <janneke@gnu.org>
4  *
5  * This file is part of Mes.
6  *
7  * Mes is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or (at
10  * your option) any later version.
11  *
12  * Mes is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with Mes.  If not, see <http://www.gnu.org/licenses/>.
19  */
20
21 int g_stdin = 0;
22
23 #define EOF -1
24 #define STDIN 0
25 #define STDOUT 1
26 #define STDERR 2
27
28 #if __GNUC__ && !POSIX
29
30 #define O_RDONLY 0
31 #define INT_MIN -2147483648
32 #define INT_MAX 2147483647
33
34 typedef long size_t;
35 void *malloc (size_t i);
36 int open (char const *s, int mode);
37 int read (int fd, void* buf, size_t n);
38 int write (int fd, char const* s, int n);
39
40 void
41 exit (int code)
42 {
43   asm (
44        "movl %0,%%ebx\n\t"
45        "movl $1,%%eax\n\t"
46        "int  $0x80"
47        : // no outputs "=" (r)
48        : "" (code)
49        );
50   // not reached
51   exit (0);
52 }
53
54 char const*
55 getenv (char const* p)
56 {
57   return 0;
58 }
59
60 int
61 read (int fd, void* buf, size_t n)
62 {
63   int r;
64   //syscall (SYS_write, fd, s, n));
65   asm (
66        "movl %1,%%ebx\n\t"
67        "movl %2,%%ecx\n\t"
68        "movl %3,%%edx\n\t"
69
70        "movl $0x3,%%eax\n\t"
71        "int  $0x80\n\t"
72
73        "mov %%eax,%0\n\t"
74        : "=r" (r)
75        : "" (fd), "" (buf), "" (n)
76        : "eax", "ebx", "ecx", "edx"
77        );
78   return r;
79 }
80
81 int
82 open (char const *s, int mode)
83 {
84   int r;
85   //syscall (SYS_open, mode));
86   asm (
87        "mov %1,%%ebx\n\t"
88        "mov %2,%%ecx\n\t"
89        "mov $0x5,%%eax\n\t"
90        "int $0x80\n\t"
91        "mov %%eax,%0\n\t"
92        : "=r" (r)
93        : "" (s), "" (mode)
94        : "eax", "ebx", "ecx"
95        );
96   return r;
97 }
98
99 int puts (char const*);
100 char const* itoa (int);
101
102 int
103 write (int fd, char const* s, int n)
104 {
105   int r;
106   //syscall (SYS_write, fd, s, n));
107   asm (
108        "mov %1,%%ebx\n\t"
109        "mov %2,%%ecx\n\t"
110        "mov %3,%%edx\n\t"
111
112        "mov $0x4, %%eax\n\t"
113        "int $0x80\n\t"
114        "mov %%eax,%0\n\t"
115        : "=r" (r)
116        : "" (fd), "" (s), "" (n)
117        : "eax", "ebx", "ecx", "edx"
118        );
119   return r;
120 }
121
122 int
123 fsync (int fd)
124 {
125   int r;
126   //syscall (SYS_fsync, fd));
127   asm (
128        "mov %1,%%ebx\n\t"
129
130        "mov $0x76, %%eax\n\t"
131        "int $0x80\n\t"
132        "mov %%eax,%0\n\t"
133        : "=r" (r)
134        : "" (fd)
135        : "eax", "ebx"
136        );
137   return r;
138 }
139
140 void *
141 brk (void *p)
142 {
143   void *r;
144   asm (
145        "mov %1,%%ebx\n\t"
146
147        "mov $0x2d,%%eax\n\t"
148        "int $0x80\n\t"
149
150        "mov %%eax,%0\n\t"
151        : "=r" (r)
152        : "" (p)
153        : "eax", "ebx"
154        );
155   return r;
156 }
157
158 int
159 fputc (int c, int fd)
160 {
161   write (fd, (char*)&c, 1);
162   return 0;
163 }
164
165 int
166 putchar (int c)
167 {
168   write (STDOUT, (char*)&c, 1);
169   return 0;
170 }
171
172 void *g_malloc_base = 0;
173
174 void *
175 malloc (size_t size)
176 {
177   void *p = brk (0);
178   if (!g_malloc_base) g_malloc_base = p;
179   brk (p+size);
180   return p;
181 }
182
183 void *
184 realloc (void *p, size_t size)
185 {
186   (void)p;
187   brk (g_malloc_base + size);
188   return g_malloc_base;
189 }
190
191 void
192 free (void *p)
193 {
194   int *n = (int*)p-1;
195   //munmap ((void*)p, *n);
196 }
197
198 size_t
199 strlen (char const* s)
200 {
201   int i = 0;
202   while (s[i]) i++;
203   return i;
204 }
205
206 int
207 strcmp (char const* a, char const* b)
208 {
209   while (*a && *b && *a == *b) {a++;b++;}
210   return *a - *b;
211 }
212
213 int
214 eputs (char const* s)
215 {
216   int i = strlen (s);
217   write (STDERR, s, i);
218   return 0;
219 }
220
221 int
222 fputs (char const* s, int fd)
223 {
224   int i = strlen (s);
225   write (fd, s, i);
226   return 0;
227 }
228
229 int
230 puts (char const* s)
231 {
232   int i = strlen (s);
233   write (STDOUT, s, i);
234   return 0;
235 }
236
237 void
238 assert_fail (char* s)
239 {
240   eputs ("assert fail: ");
241   eputs (s);
242   eputs ("\n");
243   *((int*)0) = 0;
244 }
245
246 #define assert(x) ((x) ? (void)0 : assert_fail (#x))
247
248 int ungetc_char = -1;
249 char ungetc_buf[2];
250
251 int
252 getchar ()
253 {
254   char c;
255   int i;
256   if (ungetc_char == -1)
257     {
258       int r = read (g_stdin, &c, 1);
259       if (r < 1) return -1;
260       i = c;
261     }
262   else
263     i = ungetc_buf[ungetc_char--];
264
265   if (i < 0) i += 256;
266
267   return i;
268 }
269
270 int
271 ungetc (int c, int fd)
272 {
273   assert (ungetc_char < 2);
274   ungetc_buf[++ungetc_char] = c;
275   return c;
276 }
277
278 int
279 isdigit (int c)
280 {
281   return (c>='0') && (c<='9');
282 }
283 #endif
284
285 char itoa_buf[10];
286
287 char const*
288 itoa (int x)
289 {
290   //static char itoa_buf[10];
291   //char *p = buf+9;
292   char *p = itoa_buf;
293   p += 9;
294   *p-- = 0;
295
296   //int sign = x < 0;
297   int sign;
298   sign = x < 0;
299   if (sign)
300     x = -x;
301
302   do
303     {
304       *p-- = '0' + (x % 10);
305       x = x / 10;
306     } while (x);
307
308   if (sign)
309     *p-- = '-';
310
311   return p+1;
312 }
313
314 #if POSIX
315
316 #define _GNU_SOURCE
317 #include <assert.h>
318 #include <ctype.h>
319 #include <errno.h>
320 #include <fcntl.h>
321 #include <limits.h>
322 #include <stdio.h>
323 #include <stdlib.h>
324 #include <string.h>
325 #include <unistd.h>
326
327 #undef puts
328 #define puts(x) fdputs(x, STDOUT)
329 #define eputs(x) fdputs(x, STDERR)
330 #define fputs fdputs
331 int
332 fdputs (char const* s, int fd)
333 {
334   int i = strlen (s);
335   write (fd, s, i);
336   return 0;
337 }
338
339 #ifdef putc
340 #undef putc
341 #endif
342 #define fputc fdputc
343 int
344 fdputc (int c, int fd)
345 {
346   write (fd, (char*)&c, 1);
347   return 0;
348 }
349
350 int
351 putchar (int c)
352 {
353   write (STDOUT, (char*)&c, 1);
354   return 0;
355 }
356
357 int ungetc_char = -1;
358 char ungetc_buf[2];
359
360 int
361 getchar ()
362 {
363   char c;
364   int i;
365   if (ungetc_char == -1)
366     {
367       int r = read (g_stdin, &c, 1);
368       if (r < 1) return -1;
369       i = c;
370     }
371   else
372     i = ungetc_buf[ungetc_char--];
373
374   if (i < 0) i += 256;
375
376   return i;
377 }
378
379 #define ungetc fdungetc
380 int
381 fdungetc (int c, int fd)
382 {
383   assert (ungetc_char < 2);
384   ungetc_buf[++ungetc_char] = c;
385   return c;
386 }
387 #else
388
389 #define fputs fdputs
390 int
391 fdputs (char const* s, int fd)
392 {
393   int i = strlen (s);
394   write (fd, s, i);
395   return 0;
396 }
397
398 #endif