mescc: Support regular C99 compile, headers + mlibc.
[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 char **g_environment = 0;
22 int g_stdin = 0;
23
24 #include <stdio.h>
25 #include <mlibc.h>
26
27 #if __GNUC__ && !POSIX
28
29 #include <stdlib.h>
30
31 void
32 exit (int code)
33 {
34   asm (
35        "movl %0,%%ebx\n\t"
36        "movl $1,%%eax\n\t"
37        "int  $0x80"
38        : // no outputs "=" (r)
39        : "" (code)
40        );
41   // not reached
42   exit (0);
43 }
44
45 int
46 read (int fd, void* buf, size_t n)
47 {
48   int r;
49   //syscall (SYS_write, fd, s, n));
50   asm (
51        "movl %1,%%ebx\n\t"
52        "movl %2,%%ecx\n\t"
53        "movl %3,%%edx\n\t"
54
55        "movl $0x3,%%eax\n\t"
56        "int  $0x80\n\t"
57
58        "mov %%eax,%0\n\t"
59        : "=r" (r)
60        : "" (fd), "" (buf), "" (n)
61        : "eax", "ebx", "ecx", "edx"
62        );
63   return r;
64 }
65
66 int
67 write (int fd, char const* s, int n)
68 {
69   int r;
70   //syscall (SYS_write, fd, s, n));
71   asm (
72        "mov %1,%%ebx\n\t"
73        "mov %2,%%ecx\n\t"
74        "mov %3,%%edx\n\t"
75
76        "mov $0x4, %%eax\n\t"
77        "int $0x80\n\t"
78        "mov %%eax,%0\n\t"
79        : "=r" (r)
80        : "" (fd), "" (s), "" (n)
81        : "eax", "ebx", "ecx", "edx"
82        );
83   return r;
84 }
85
86 int
87 open (char const *s, int mode)
88 {
89   int r;
90   //syscall (SYS_open, mode));
91   asm (
92        "mov %1,%%ebx\n\t"
93        "mov %2,%%ecx\n\t"
94        "mov $0x5,%%eax\n\t"
95        "int $0x80\n\t"
96        "mov %%eax,%0\n\t"
97        : "=r" (r)
98        : "" (s), "" (mode)
99        : "eax", "ebx", "ecx"
100        );
101   return r;
102 }
103
104 int
105 access (char const *s, int mode)
106 {
107   int r;
108   //syscall (SYS_access, mode));
109   asm (
110        "mov %1,%%ebx\n\t"
111        "mov %2,%%ecx\n\t"
112        "mov $0x21,%%eax\n\t"
113        "int $0x80\n\t"
114        "mov %%eax,%0\n\t"
115        : "=r" (r)
116        : "" (s), "" (mode)
117        : "eax", "ebx", "ecx"
118        );
119   return r;
120 }
121
122 void *
123 brk (void *p)
124 {
125   void *r;
126   asm (
127        "mov %1,%%ebx\n\t"
128
129        "mov $0x2d,%%eax\n\t"
130        "int $0x80\n\t"
131
132        "mov %%eax,%0\n\t"
133        : "=r" (r)
134        : "" (p)
135        : "eax", "ebx"
136        );
137   return r;
138 }
139
140 int
141 fsync (int fd)
142 {
143   int r;
144   //syscall (SYS_fsync, fd));
145   asm (
146        "mov %1,%%ebx\n\t"
147
148        "mov $0x76, %%eax\n\t"
149        "int $0x80\n\t"
150        "mov %%eax,%0\n\t"
151        : "=r" (r)
152        : "" (fd)
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 char const* itoa (int);
279
280 int
281 strncmp (char const* a, char const* b, size_t length)
282 {
283   while (*a && *b && *a == *b && --length) {a++;b++;}
284   return *a - *b;
285 }
286
287 char const*
288 getenv (char const* s)
289 {
290   char **p = g_environment;
291   int length = strlen (s);
292   while (*p)
293     {
294       if (!strncmp (s, *p, length) && *(*p + length) == '=') return (*p + length + 1);
295       p++;
296     }
297   return 0;
298 }
299
300 int
301 isdigit (int c)
302 {
303   return (c>='0') && (c<='9');
304 }
305
306 int
307 atoi (char const *s)
308 {
309   int i = 0;
310   int sign = 1;
311   if (*s && *s == '-')
312     {
313       sign = -1;
314       s++;
315     }
316   while (isdigit (*s))
317     {
318       i *= 10;
319       i += (*s - '0');
320       s++;
321     }
322   return i * sign;
323 }
324
325 int
326 printf (char const* format, ...)
327 {
328   int va_arg = 0;
329   int va;
330   char const *p = format;
331   while (*p)
332     if (*p != '%')
333       putchar (*p++);
334     else
335       {
336         p++;
337         char c = *p;
338         switch (c)
339           {
340           case '%': {putchar (*p); break;}
341           case 'c':
342             {
343             asm (
344                  "mov    -0xc(%%ebp),%%eax\n\t"
345                  "shl     $0x2,%%eax\n\t"
346                  "add     %%ebp,%%eax\n\t"
347                  "add     $0xc,%%eax\n\t"
348                  "mov     (%%eax),%%eax\n\t"
349                  //"mov     %%eax,%0\n\t"
350                  : "=va" (va)
351                  : //no inputs ""
352                  );
353             putchar ((char)va);
354             va_arg++;
355             break;
356             }
357           case 'd': {
358             asm (
359                  "mov    -0xc(%%ebp),%%eax\n\t"
360                  "shl     $0x2,%%eax\n\t"
361                  "add     %%ebp,%%eax\n\t"
362                  "add     $0xc,%%eax\n\t"
363                  "mov     (%%eax),%%eax\n\t"
364                  //"mov     %%eax,%0\n\t"
365                  : "=va" (va)
366                  : //no inputs ""
367                  );
368             puts (itoa ((int)va));
369             va_arg++;
370             break;
371           }
372           case 's': {
373             asm (
374                  "mov    -0xc(%%ebp),%%eax\n\t"
375                  "shl     $0x2,%%eax\n\t"
376                  "add     %%ebp,%%eax\n\t"
377                  "add     $0xc,%%eax\n\t"
378                  "mov     (%%eax),%%eax\n\t"
379                  //"mov     %%eax,%0\n\t"
380                  : "=va" (va)
381                  : //no inputs ""
382                  );
383             puts ((char*)va);
384             va_arg++;
385             break;
386           }
387           default: putchar (*p);
388           }
389         p++;
390       }
391   return 0;
392 }
393 #endif
394
395 char itoa_buf[10];
396
397 char const*
398 itoa (int x)
399 {
400   //static char itoa_buf[10];
401   //char *p = buf+9;
402   char *p = itoa_buf;
403   p += 9;
404   *p-- = 0;
405
406   //int sign = x < 0;
407   int sign;
408   sign = x < 0;
409   if (sign)
410     x = -x;
411
412   do
413     {
414       *p-- = '0' + (x % 10);
415       x = x / 10;
416     } while (x);
417
418   if (sign)
419     *p-- = '-';
420
421   return p+1;
422 }
423
424 #if POSIX
425 #define _GNU_SOURCE
426 #include <assert.h>
427 #include <fcntl.h>
428 #include <string.h>
429 #include <unistd.h>
430 #endif // POSIX
431
432 int
433 fdputs (char const* s, int fd)
434 {
435   int i = strlen (s);
436   write (fd, s, i);
437   return 0;
438 }
439
440 #if POSIX
441
442 int
443 fdputc (int c, int fd)
444 {
445   write (fd, (char*)&c, 1);
446   return 0;
447 }
448
449 int
450 putchar (int c)
451 {
452   write (STDOUT, (char*)&c, 1);
453   return 0;
454 }
455
456 int ungetc_char = -1;
457 char ungetc_buf[2];
458
459 int
460 getchar ()
461 {
462   char c;
463   int i;
464   if (ungetc_char == -1)
465     {
466       int r = read (g_stdin, &c, 1);
467       if (r < 1) return -1;
468       i = c;
469     }
470   else
471     i = ungetc_buf[ungetc_char--];
472
473   if (i < 0) i += 256;
474
475   return i;
476 }
477
478 int
479 fdungetc (int c, int fd)
480 {
481   assert (ungetc_char < 2);
482   ungetc_buf[++ungetc_char] = c;
483   return c;
484 }
485
486 #endif // POSIX