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