build: compile crt1.c, libc-mesc.c and <input>.c separately.
[mes.git] / mlibc / libc-mes.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 #include <stdarg.h>
22 #include <stdlib.h>
23
24 char **g_environment = 0; // FIXME: todo extern
25 int g_stdin = 0;
26
27 void _env ();
28
29 void
30 exit ()
31 {
32   asm ("mov____0x8(%ebp),%ebx !8");               // mov    0x8(%ebp),%ebx
33
34   asm ("mov____$i32,%eax SYS_exit");              // mov    $0x1,%eax
35   asm ("int____$0x80");                           // int    $0x80
36 }
37
38 void
39 read ()
40 {
41   asm ("mov____0x8(%ebp),%ebx !8");               // mov    0x8(%ebp),%ebx
42   asm ("mov____0x8(%ebp),%ecx !12");              // mov    0x8(%ebp),%ecx
43   asm ("mov____0x8(%ebp),%edx !16");              // mov    0x8(%ebp),%edx
44
45   asm ("mov____$i32,%eax SYS_read");              // mov    $0x3,%eax
46   asm ("int____$0x80");                           // int    $0x80
47 }
48
49 void
50 write ()
51 {
52   asm ("mov____0x8(%ebp),%ebx !8");               // mov    0x8(%ebp),%ebx
53   asm ("mov____0x8(%ebp),%ecx !12");              // mov    0x8(%ebp),%ecx
54   asm ("mov____0x8(%ebp),%edx !16");              // mov    0x8(%ebp),%edx
55
56   asm ("mov____$i32,%eax SYS_write");             // mov    $0x4,%eax
57   asm ("int____$0x80");                           // int    $0x80
58 }
59
60 void
61 open ()
62 {
63   asm ("mov____0x8(%ebp),%ebx !8");               // mov    0x8(%ebp),%ebx
64   asm ("mov____0x8(%ebp),%ecx !12");              // mov    0x8(%ebp),%ecx
65   asm ("mov____0x8(%ebp),%edx !16");              // mov    0x8(%ebp),%edx
66
67   asm ("mov____$i32,%eax SYS_open");              // mov    $0x5,%eax
68   asm ("int____$0x80");                           // int    $0x80
69 }
70
71 void
72 access ()
73 {
74   asm ("mov____0x8(%ebp),%ebx !8");               // mov    0x8(%ebp),%ebx
75   asm ("mov____0x8(%ebp),%ecx !12");              // mov    0x8(%ebp),%ecx
76
77   asm ("mov____$i32,%eax SYS_access");            // mov    $0x21,%eax
78   asm ("int____$0x80");                           // int    $0x80
79 }
80
81 void
82 brk ()
83 {
84   asm ("mov____0x8(%ebp),%ebx !8");               // mov    0x8(%ebp),%ebx
85
86   asm ("mov____$i32,%eax SYS_brk");               // mov    $0x2d,%eax
87   asm ("int____$0x80");                           // int    $0x80
88 }
89
90 void
91 fsync ()
92 {
93   asm ("mov____0x8(%ebp),%ebx !8");               // mov    0x8(%ebp),%ebx
94
95   asm ("mov____$i32,%eax SYS_fsync");             // mov    $0x7c,%eax
96   asm ("int____$0x80");                           // int    $0x80
97 }
98
99 int
100 strlen (char const* s)
101 {
102   int i = 0;
103   while (s[i]) i++;
104   return i;
105 }
106
107 int
108 eputc (int c)
109 {
110   return fputc (c, 2);
111 }
112
113 int
114 eputs (char const* s)
115 {
116   int i = strlen (s);
117   write (2, s, i);
118   return 0;
119 }
120
121 int
122 fputs (char const* s, int fd)
123 {
124   int i = strlen (s);
125   write (fd, s, i);
126   return 0;
127 }
128
129 int
130 puts (char const* s)
131 {
132   int i = strlen (s);
133   write (1, s, i);
134   return 0;
135 }
136
137 int
138 putchar (int c)
139 {
140   write (1, (char*)&c, 1);
141   return 0;
142 }
143
144 int
145 fputc (int c, int fd)
146 {
147   write (fd, (char*)&c, 1);
148   return 0;
149 }
150
151 void
152 assert_fail (char* s)
153 {
154   eputs ("assert fail: ");
155   eputs (s);
156   eputs ("\n");
157   //*((int*)0) = 0;
158   char *fail = s;
159   fail = 0;
160   *fail = 0;
161 }
162
163 int ungetc_char = -1;
164 char ungetc_buf[2];
165
166 int
167 getchar ()
168 {
169   char c;
170   int i;
171   if (ungetc_char == -1)
172     {
173       int r = read (g_stdin, &c, 1);
174       if (r < 1) return -1;
175       i = c;
176    }
177   else
178     {
179        //FIXME
180        //i = ungetc_buf[ungetc_char--];
181        i = ungetc_buf[ungetc_char];
182        //ungetc_char--;
183        ungetc_char = ungetc_char - 1;
184      }
185   if (i < 0) i += 256;
186
187   return i;
188 }
189
190 int
191 fgetc (int fd)
192 {
193   char c;
194   int r = read (fd, &c, 1);
195   return c == 1 ? c : (-1);
196 }
197
198 void
199 free (void *ptr)
200 {
201 }
202
203 //#define assert(x) ((x) ? (void)0 : assert_fail (#x))
204 int
205 ungetc (int c, int fd)
206 {
207   //FIXME
208   //assert (ungetc_char < 2);
209   //assert (ungetc_char == -1 || ungetc_char < 2);
210   //FIXME
211   //ungetc_buf[++ungetc_char] = c;
212   ungetc_char++;
213   ungetc_buf[ungetc_char] = c;
214   return c;
215 }
216
217 int
218 strcmp (char const* a, char const* b)
219 {
220   while (*a && *b && *a == *b)
221     {
222       a++;b++;
223     }
224   return *a - *b;
225 }
226
227
228 char *
229 strcpy (char *dest, char const *src)
230 {
231   char *p = dest;
232   while (*src) *p++ = *src++;
233   *p = 0;
234   return dest;
235 }
236
237 char itoa_buf[10];
238
239 char const*
240 itoa (int x)
241 {
242   //static char itoa_buf[10];
243   //char *p = buf+9;
244   char *p = itoa_buf;
245   p += 9;
246   *p-- = 0;
247
248   //int sign = x < 0; // FIXME
249   int sign = 0;
250   if (x < 0) sign = 1;
251   if (sign)
252     x = -x;
253
254   do
255      {
256        *p-- = '0' + (x % 10);
257        x = x / 10;
258      } while (x);
259
260   if (sign && *(p + 1) != '0')
261     *p-- = '-';
262
263   return p+1;
264 }
265
266 int
267 isdigit (int c)
268 {
269   return (c>='0') && (c<='9');
270 }
271
272 int
273 isxdigit (int c)
274 {
275   return isdigit (c) || (c>='a') && (c<='f');
276 }
277
278 int
279 isnumber (int c, int base)
280 {
281   if (base == 2)
282     return (c>='0') && (c<='1');
283   if (base == 8)
284     return (c>='0') && (c<='7');
285   if (base == 10)
286     return isdigit (c);
287   if (base == 16)
288     return isxdigit (c);
289 }
290
291 int
292 _atoi (char const **p, int base)
293 {
294   char const *s = *p;
295   int i = 0;
296   int sign = 1;
297   if (!base) base = 10;
298   if (*s && *s == '-')
299     {
300       sign = -1;
301       s++;
302     }
303   while (isnumber (*s, base))
304     {
305       i *= base;
306       int m = *s > '9' ? 'a' - 10 : '0';
307       i += *s - m;
308       s++;
309     }
310   *p = s;
311   return i * sign;
312 }
313
314 int
315 atoi (char const *s)
316 {
317   char const *p = s;
318   return _atoi (&p, 0);
319 }
320
321 char *g_brk = 0;
322
323 void *
324 malloc (size_t size)
325 {
326   if (!g_brk)
327     g_brk = brk (0);
328   if (brk (g_brk + size) == -1)
329     return 0;
330   char *p = g_brk;
331   g_brk += size;
332   return p;
333 }
334
335 void *
336 memcpy (void *dest, void const *src, size_t n)
337 {
338   char* p = dest;
339   char* q = src;
340   while (n--) *p++ = *q++;
341   return dest;
342 }
343
344 void *
345 realloc (void *ptr, size_t size)
346 {
347   void *new = malloc (size);
348   if (ptr && new)
349     {
350       memcpy (new, ptr, size);
351       free (ptr);
352     }
353   return new;
354 }
355
356 int
357 strncmp (char const* a, char const* b, int length)
358 {
359   while (*a && *b && *a == *b && --length) {a++;b++;}
360   return *a - *b;
361 }
362
363 char *
364 getenv (char const* s)
365 {
366   char **p = g_environment;
367   int length = strlen (s);
368   while (*p)
369     {
370       if (!strncmp (s, *p, length) && *(*p + length) == '=') return (*p + length + 1);
371       p++;
372     }
373   return 0;
374 }
375
376 int
377 vprintf (char const* format, va_list ap)
378 {
379   char const *p = format;
380   while (*p)
381     if (*p != '%')
382       putchar (*p++);
383     else
384       {
385         p++;
386         char c = *p;
387         switch (c)
388           {
389           case '%': {putchar (*p); break;}
390           case 'c': {char c; c = va_arg (ap, char); putchar (c); break;}
391           case 'd': {int d; d = va_arg (ap, int); puts (itoa (d)); break;}
392           case 's': {char *s; s = va_arg (ap, char *); puts (s); break;}
393           default: {putchar (*p); break;}
394           }
395         p++;
396       }
397   va_end (ap);
398   return 0;
399 }
400
401 int
402 printf (char const* format, ...)
403 {
404   va_list ap;
405   va_start (ap, format);
406   int r = vprintf (format, ap);
407   va_end (ap);
408   return r;
409 }
410
411 int
412 vsprintf (char *str, char const* format, va_list ap)
413 {
414   char const *p = format;
415   while (*p)
416     if (*p != '%')
417       *str++ = *p++;
418     else
419       {
420         p++;
421         char c = *p;
422         switch (c)
423           {
424           case '%': {*str++ = *p; break;}
425           case 'c': {char c; c = va_arg (ap, char); *str++ = c; break;}
426           case 'd': {int d; d = va_arg (ap, int); char const *s; s = itoa (d); while (*s) *str++ = *s++; break;}
427           case 's': {char *s; s = va_arg (ap, char *); while (*s) *str++ = *s++; break;}
428           default: {*str++ = *p; break;}
429           }
430         p++;
431       }
432   va_end (ap);
433   *str = 0;
434   return strlen (str);
435 }
436
437 int
438 sprintf (char *str, char const* format, ...)
439 {
440   va_list ap;
441   va_start (ap, format);
442   int r = vsprintf (str, format, ap);
443   va_end (ap);
444   return r;
445 }