build: compile crt1.c, libc-mesc.c and <input>.c separately.
[mes.git] / mlibc / libc-gcc.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 #include <stdio.h>
24 #include <mlibc.h>
25
26 #if __GNUC__
27 #include <stdlib.h>
28 #endif
29
30 #if __GNUC__ && !POSIX
31
32 void
33 exit (int code)
34 {
35   asm (
36        "mov    %0,%%ebx\n\t"
37        "mov    $1,%%eax\n\t"
38        "int    $0x80"
39        : // no outputs "=" (r)
40        : "" (code)
41        );
42   // not reached
43   exit (0);
44 }
45
46 int
47 read (int fd, void* buf, size_t n)
48 {
49   int r;
50   //syscall (SYS_write, fd, s, n));
51   asm (
52        "mov    %1,%%ebx\n\t"
53        "mov    %2,%%ecx\n\t"
54        "mov    %3,%%edx\n\t"
55
56        "movl $0x3,%%eax\n\t"
57        "int  $0x80\n\t"
58
59        "mov    %%eax,%0\n\t"
60        : "=r" (r)
61        : "" (fd), "" (buf), "" (n)
62        : "eax", "ebx", "ecx", "edx"
63        );
64   return r;
65 }
66
67 int
68 write (int fd, char const* s, int n)
69 {
70   int r;
71   //syscall (SYS_write, fd, s, n));
72   asm (
73        "mov    %1,%%ebx\n\t"
74        "mov    %2,%%ecx\n\t"
75        "mov    %3,%%edx\n\t"
76
77        "mov    $0x4, %%eax\n\t"
78        "int    $0x80\n\t"
79        "mov    %%eax,%0\n\t"
80        : "=r" (r)
81        : "" (fd), "" (s), "" (n)
82        : "eax", "ebx", "ecx", "edx"
83        );
84   return r;
85 }
86
87 int
88 open (char const *s, int flags, ...)
89 {
90   int mode;
91   asm (
92        "mov    %%ebp,%%eax\n\t"
93        "add    $0x10,%%eax\n\t"
94        "mov    (%%eax),%%eax\n\t"
95        "mov    %%eax,%0\n\t"
96        : "=mode" (mode)
97        : //no inputs ""
98        );
99   int r;
100   //syscall (SYS_open, mode));
101   asm (
102        "mov    %1,%%ebx\n\t"
103        "mov    %2,%%ecx\n\t"
104        "mov    %3,%%edx\n\t"
105        "mov    $0x5,%%eax\n\t"
106        "int    $0x80\n\t"
107        "mov    %%eax,%0\n\t"
108        : "=r" (r)
109        : "" (s), "" (flags), "" (mode)
110        : "eax", "ebx", "ecx", "edx"
111        );
112   return r;
113 }
114
115 int
116 access (char const *s, int mode)
117 {
118   int r;
119   //syscall (SYS_access, mode));
120   asm (
121        "mov    %1,%%ebx\n\t"
122        "mov    %2,%%ecx\n\t"
123        "mov    $0x21,%%eax\n\t"
124        "int    $0x80\n\t"
125        "mov    %%eax,%0\n\t"
126        : "=r" (r)
127        : "" (s), "" (mode)
128        : "eax", "ebx", "ecx"
129        );
130   return r;
131 }
132
133 void *
134 brk (void *p)
135 {
136   void *r;
137   asm (
138        "mov    %1,%%ebx\n\t"
139
140        "mov    $0x2d,%%eax\n\t"
141        "int    $0x80\n\t"
142
143        "mov    %%eax,%0\n\t"
144        : "=r" (r)
145        : "" (p)
146        : "eax", "ebx"
147        );
148   return r;
149 }
150
151 int
152 fsync (int fd)
153 {
154   int r;
155   //syscall (SYS_fsync, fd));
156   asm (
157        "mov    %1,%%ebx\n\t"
158
159        "mov    $0x76, %%eax\n\t"
160        "int    $0x80\n\t"
161        "mov    %%eax,%0\n\t"
162        : "=r" (r)
163        : "" (fd)
164        : "eax", "ebx"
165        );
166   return r;
167 }
168
169 int
170 fputc (int c, int fd)
171 {
172   write (fd, (char*)&c, 1);
173   return 0;
174 }
175
176 void
177 free (void *ptr)
178 {
179 }
180
181 char *g_brk = 0;
182
183 void *
184 malloc (size_t size)
185 {
186   if (!g_brk)
187     g_brk = brk (0);
188   if ((int)brk (g_brk + size) == -1)
189     return 0;
190   char *p = g_brk;
191   g_brk += size;
192   return p;
193 }
194
195 void *
196 memcpy (void *dest, void const *src, size_t n)
197 {
198   char* p = dest;
199   char const* q = src;
200   while (n--) *p++ = *q++;
201   return dest;
202 }
203
204 int
205 putchar (int c)
206 {
207   write (STDOUT, (char*)&c, 1);
208   return 0;
209 }
210
211 void *
212 realloc (void *ptr, size_t size)
213 {
214   void *new = malloc (size);
215   if (ptr && new)
216     {
217       memcpy (new, ptr, size);
218       free (ptr);
219     }
220   return new;
221 }
222
223 size_t
224 strlen (char const* s)
225 {
226   int i = 0;
227   while (s[i]) i++;
228   return i;
229 }
230
231 int
232 strcmp (char const* a, char const* b)
233 {
234   while (*a && *b && *a == *b) {a++;b++;}
235   return *a - *b;
236 }
237
238 char *
239 strcpy (char *dest, char const *src)
240 {
241   char *p = dest;
242   while (*src) *p++ = *src++;
243   *p = 0;
244   return dest;
245 }
246
247 int
248 fputs (char const* s, int fd)
249 {
250   int i = strlen (s);
251   write (fd, s, i);
252   return 0;
253 }
254
255 int
256 puts (char const* s)
257 {
258   int i = strlen (s);
259   write (STDOUT, s, i);
260   return 0;
261 }
262
263 void
264 assert_fail (char* s)
265 {
266   eputs ("assert fail: ");
267   eputs (s);
268   eputs ("\n");
269   *((int*)0) = 0;
270 }
271
272 #define assert(x) ((x) ? (void)0 : assert_fail (#x))
273
274 int ungetc_char = -1;
275 char ungetc_buf[2];
276
277 int
278 getchar ()
279 {
280   char c;
281   int i;
282   if (ungetc_char == -1)
283     {
284       int r = read (g_stdin, &c, 1);
285       if (r < 1) return -1;
286       i = c;
287     }
288   else
289     i = ungetc_buf[ungetc_char--];
290
291   if (i < 0) i += 256;
292
293   return i;
294 }
295
296 int
297 ungetc (int c, int fd)
298 {
299   assert (ungetc_char < 2);
300   ungetc_buf[++ungetc_char] = c;
301   return c;
302 }
303
304 char const* itoa (int);
305
306 int
307 strncmp (char const* a, char const* b, size_t length)
308 {
309   while (*a && *b && *a == *b && --length) {a++;b++;}
310   return *a - *b;
311 }
312
313 char *
314 getenv (char const* s)
315 {
316   char **p = g_environment;
317   int length = strlen (s);
318   while (*p)
319     {
320       if (!strncmp (s, *p, length) && *(*p + length) == '=') return (*p + length + 1);
321       p++;
322     }
323   return 0;
324 }
325
326 int
327 isdigit (int c)
328 {
329   return (c>='0') && (c<='9');
330 }
331
332 int
333 isxdigit (int c)
334 {
335   return isdigit (c) || (c>='a') && (c<='f');
336 }
337
338 int
339 isnumber (int c, int base)
340 {
341   if (base == 2)
342     return (c>='0') && (c<='1');
343   if (base == 8)
344     return (c>='0') && (c<='7');
345   if (base == 10)
346     return isdigit (c);
347   if (base == 16)
348     return isxdigit (c);
349 }
350
351 int
352 _atoi (char const **p, int base)
353 {
354   char const *s = *p;
355   int i = 0;
356   int sign = 1;
357   if (!base) base = 10;
358   if (*s && *s == '-')
359     {
360       sign = -1;
361       s++;
362     }
363   while (isnumber (*s, base))
364     {
365       i *= base;
366       int m = *s > '9' ? 'a' - 10 : '0';
367       i += *s - m;
368       s++;
369     }
370   *p = s;
371   return i * sign;
372 }
373
374 int
375 atoi (char const *s)
376 {
377   char const *p = s;
378   return _atoi (&p, 0);
379 }
380
381 // FIXME: copied from libc-mes.c now
382 #include <stdarg.h>
383
384 int
385 vprintf (char const* format, va_list ap)
386 {
387   char const *p = format;
388   while (*p)
389     if (*p != '%')
390       putchar (*p++);
391     else
392       {
393         p++;
394         char c = *p;
395         switch (c)
396           {
397           case '%': {putchar (*p); break;}
398           case 'c': {char c; c = va_arg (ap, char); putchar (c); break;}
399           case 'd': {int d; d = va_arg (ap, int); puts (itoa (d)); break;}
400           case 's': {char *s; s = va_arg (ap, char *); puts (s); break;}
401           default: putchar (*p);
402           }
403         p++;
404       }
405   va_end (ap);
406   return 0;
407 }
408
409 int
410 printf (char const* format, ...)
411 {
412   va_list ap;
413   va_start (ap, format);
414   int r = vprintf (format, ap);
415   va_end (ap);
416   return r;
417 }
418
419 int
420 vsprintf (char *str, char const* format, va_list ap)
421 {
422   char const *p = format;
423   while (*p)
424     if (*p != '%')
425       *str++ = *p++;
426     else
427       {
428         p++;
429         char c = *p;
430         switch (c)
431           {
432           case '%': {*str++ = *p; break;}
433           case 'c': {char c; c = va_arg (ap, char); *str++ = c; break;}
434           case 'd': {int d; d = va_arg (ap, int); char const *s = itoa (d); while (*s) *str++ = *s++; break;}
435           case 's': {char *s; s = va_arg (ap, char *); while (*s) *str++ = *s++; break;}
436           default: *str++ = *p;
437           }
438         p++;
439       }
440
441   *str = 0;
442   return strlen (str);
443 }
444
445 int
446 sprintf (char *str, char const* format, ...)
447 {
448   va_list ap;
449   va_start (ap, format);
450   int r = vsprintf (str, format, ap);
451   va_end (ap);
452   return r;
453 }
454 #endif
455
456 char itoa_buf[10];
457
458 char const*
459 itoa (int x)
460 {
461   //static char itoa_buf[10];
462   //char *p = buf+9;
463   char *p = itoa_buf;
464   p += 9;
465   *p-- = 0;
466
467   //int sign = x < 0;
468   int sign;
469   sign = x < 0;
470   if (sign)
471     x = -x;
472
473   do
474     {
475       *p-- = '0' + (x % 10);
476       x = x / 10;
477     } while (x);
478
479   if (sign)
480     *p-- = '-';
481
482   return p+1;
483 }
484
485 #if POSIX
486 #define _GNU_SOURCE
487 #include <assert.h>
488 #include <fcntl.h>
489 #include <string.h>
490 #include <unistd.h>
491 #endif // POSIX
492
493 int
494 fdputs (char const* s, int fd)
495 {
496   int i = strlen (s);
497   write (fd, s, i);
498   return 0;
499 }
500
501 int
502 eputc (int c)
503 {
504   return fdputc (c, STDERR);
505 }
506
507 int
508 eputs (char const* s)
509 {
510   return fdputs (s, STDERR);
511 }
512
513 int
514 fdputc (int c, int fd)
515 {
516   write (fd, (char*)&c, 1);
517   return 0;
518 }
519
520 #if POSIX
521
522 int
523 putchar (int c)
524 {
525   write (STDOUT, (char*)&c, 1);
526   return 0;
527 }
528
529 int ungetc_char = -1;
530 char ungetc_buf[2];
531
532 int
533 getchar ()
534 {
535   char c;
536   int i;
537   if (ungetc_char == -1)
538     {
539       int r = read (g_stdin, &c, 1);
540       if (r < 1) return -1;
541       i = c;
542     }
543   else
544     i = ungetc_buf[ungetc_char--];
545
546   if (i < 0) i += 256;
547
548   return i;
549 }
550
551 int
552 fdungetc (int c, int fd)
553 {
554   assert (ungetc_char < 2);
555   ungetc_buf[++ungetc_char] = c;
556   return c;
557 }
558
559 #endif // POSIX