mescc: Produce M1 output instead of hex2.
[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   p = *g_environment;
343   int length = strlen (s);
344   while (*p)
345     {
346       if (!strncmp (s, *p, length) && *(*p + length) == '=') return (*p + length + 1);
347       p++;
348     }
349   return 0;
350 }
351
352
353 #if 0
354
355 // !__MESC__
356 // FIXME: mes+nyacc parser bug here
357 // works fine with Guile, but let's keep a single input source
358
359 #define pop_va_arg \
360   asm ("mov____0x8(%ebp),%eax !-4");  /* mov   -<0x4>(%ebp),%eax :va_arg */ \
361   asm ("shl____$i8,%eax !2");         /* shl   $0x2,%eax */ \
362   asm ("add____%ebp,%eax");           /* add   %ebp,%eax */ \
363   asm ("add____$i8,%eax !12");        /* add   $0xc,%eax */ \
364   asm ("mov____(%eax),%eax");         /* mov   (%eax),%eax */ \
365   asm ("mov____%eax,0x8(%ebp) !-8");  /* mov   %eax,-0x8(%ebp) :va */ \
366   asm ("push___%eax");                /* push   %eax */
367
368 #else // __MESC__
369
370 #define pop_va_arg asm ("mov____0x8(%ebp),%eax !-4\nshl____$i8,%eax !2\nadd____%ebp,%eax add____$i8,%eax !12\nmov____(%eax),%eax\nmov____%eax,0x8(%ebp) !-8\npush___%eax")
371
372 #endif
373
374 int
375 printf (char const* format, int va_args)
376 {
377   int va_arg = 0;
378   int va;
379   char *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': {pop_va_arg; putchar ((char)va); va_arg++; break;}
391           case 'd': {pop_va_arg; puts (itoa (va)); va_arg++; break;}
392           case 's': {pop_va_arg; puts ((char*)va); va_arg++; break;}
393           default: putchar (*p);
394           }
395         p++;
396       }
397   return 0;
398 }
399