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