35b76770f47607ce42ca874df43577adec67d68c
[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 main (int,char*[]);
27
28 int
29 _start ()
30 {
31   asm ("mov____%ebp,%eax");
32   asm ("add____$i8,%eax !4");
33
34   asm ("movzbl_(%eax),%eax");
35   asm ("add____$i8,%eax !3");
36
37   asm ("shl____$i8,%eax !0x02");
38   asm ("add____%ebp,%eax");
39   asm ("mov____%eax,0x32 &g_environment");
40
41   asm ("mov____%ebp,%eax");
42   asm ("add____$i8,%eax !8");
43   asm ("push___%eax");
44
45   asm ("mov____%ebp,%eax");
46   asm ("add____$i8,%eax !4");
47   asm ("movzbl_(%eax),%eax");
48   asm ("push___%eax");
49
50   main ();
51
52   asm ("mov____%eax,%ebx");
53   asm ("mov____$i32,%eax %1");
54   asm ("int____$0x80");
55   asm ("hlt");
56 }
57
58 void
59 exit ()
60 {
61   asm ("mov____0x8(%ebp),%ebx !8");               // mov    0x8(%ebp),%ebx
62
63   asm ("mov____$i32,%eax SYS_exit");              // mov    $0x1,%eax
64   asm ("int____$0x80");                           // int    $0x80
65 }
66
67 void
68 read ()
69 {
70   asm ("mov____0x8(%ebp),%ebx !8");               // mov    0x8(%ebp),%ebx
71   asm ("mov____0x8(%ebp),%ecx !12");              // mov    0x8(%ebp),%ecx
72   asm ("mov____0x8(%ebp),%edx !16");              // mov    0x8(%ebp),%edx
73
74   asm ("mov____$i32,%eax SYS_read");              // mov    $0x3,%eax
75   asm ("int____$0x80");                           // int    $0x80
76 }
77
78 void
79 write ()
80 {
81   asm ("mov____0x8(%ebp),%ebx !8");               // mov    0x8(%ebp),%ebx
82   asm ("mov____0x8(%ebp),%ecx !12");              // mov    0x8(%ebp),%ecx
83   asm ("mov____0x8(%ebp),%edx !16");              // mov    0x8(%ebp),%edx
84
85   asm ("mov____$i32,%eax SYS_write");             // mov    $0x4,%eax
86   asm ("int____$0x80");                           // int    $0x80
87 }
88
89 void
90 open ()
91 {
92   asm ("mov____0x8(%ebp),%ebx !8");               // mov    0x8(%ebp),%ebx
93   asm ("mov____0x8(%ebp),%ecx !12");              // mov    0x8(%ebp),%ecx
94   asm ("mov____0x8(%ebp),%edx !16");              // mov    0x8(%ebp),%edx
95
96   asm ("mov____$i32,%eax SYS_open");              // mov    $0x5,%eax
97   asm ("int____$0x80");                           // int    $0x80
98 }
99
100 void
101 access ()
102 {
103   asm ("mov____0x8(%ebp),%ebx !8");               // mov    0x8(%ebp),%ebx
104   asm ("mov____0x8(%ebp),%ecx !12");              // mov    0x8(%ebp),%ecx
105
106   asm ("mov____$i32,%eax SYS_access");            // mov    $0x21,%eax
107   asm ("int____$0x80");                           // int    $0x80
108 }
109
110 void
111 brk ()
112 {
113   asm ("mov____0x8(%ebp),%ebx !8");               // mov    0x8(%ebp),%ebx
114
115   asm ("mov____$i32,%eax SYS_brk");               // mov    $0x2d,%eax
116   asm ("int____$0x80");                           // int    $0x80
117 }
118
119 void
120 fsync ()
121 {
122   asm ("mov____0x8(%ebp),%ebx !8");               // mov    0x8(%ebp),%ebx
123
124   asm ("mov____$i32,%eax SYS_fsync");             // mov    $0x7c,%eax
125   asm ("int____$0x80");                           // int    $0x80
126 }
127
128 int
129 strlen (char const* s)
130 {
131   int i = 0;
132   while (s[i]) i++;
133   return i;
134 }
135
136 int
137 eputc (int c)
138 {
139   return fputc (c, 2);
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 int
220 fgetc (int fd)
221 {
222   char c;
223   int r = read (fd, &c, 1);
224   return c == 1 ? c : (-1);
225 }
226
227 void
228 free (void *ptr)
229 {
230 }
231
232 //#define assert(x) ((x) ? (void)0 : assert_fail (#x))
233 int
234 ungetc (int c, int fd)
235 {
236   //FIXME
237   //assert (ungetc_char < 2);
238   //assert (ungetc_char == -1 || ungetc_char < 2);
239   //FIXME
240   //ungetc_buf[++ungetc_char] = c;
241   ungetc_char++;
242   ungetc_buf[ungetc_char] = c;
243   return c;
244 }
245
246 int
247 strcmp (char const* a, char const* b)
248 {
249   while (*a && *b && *a == *b)
250     {
251       a++;b++;
252     }
253   return *a - *b;
254 }
255
256
257 char *
258 strcpy (char *dest, char const *src)
259 {
260   char *p = dest;
261   while (*src) *p++ = *src++;
262   *p = 0;
263   return dest;
264 }
265
266 char itoa_buf[10];
267
268 char const*
269 itoa (int x)
270 {
271   //static char itoa_buf[10];
272   //char *p = buf+9;
273   char *p = itoa_buf;
274   p += 9;
275   *p-- = 0;
276
277   //int sign = x < 0; // FIXME
278   int sign = 0;
279   if (x < 0) sign = 1;
280   if (sign)
281     x = -x;
282
283   do
284      {
285        *p-- = '0' + (x % 10);
286        x = x / 10;
287      } while (x);
288
289   if (sign && *(p + 1) != '0')
290     *p-- = '-';
291
292   return p+1;
293 }
294
295 int
296 isdigit (int c)
297 {
298   return (c>='0') && (c<='9');
299 }
300
301 int
302 isxdigit (int c)
303 {
304   return isdigit (c) || (c>='a') && (c<='f');
305 }
306
307 int
308 isnumber (int c, int base)
309 {
310   if (base == 2)
311     return (c>='0') && (c<='1');
312   if (base == 8)
313     return (c>='0') && (c<='7');
314   if (base == 10)
315     return isdigit (c);
316   if (base == 16)
317     return isxdigit (c);
318 }
319
320 int
321 _atoi (char const **p, int base)
322 {
323   char const *s = *p;
324   int i = 0;
325   int sign = 1;
326   if (!base) base = 10;
327   if (*s && *s == '-')
328     {
329       sign = -1;
330       s++;
331     }
332   while (isnumber (*s, base))
333     {
334       i *= base;
335       int m = *s > '9' ? 'a' - 10 : '0';
336       i += *s - m;
337       s++;
338     }
339   *p = s;
340   return i * sign;
341 }
342
343 int
344 atoi (char const *s)
345 {
346   char const *p = s;
347   return _atoi (&p, 0);
348 }
349
350 char *g_brk = 0;
351
352 void *
353 malloc (size_t size)
354 {
355   if (!g_brk)
356     g_brk = brk (0);
357   if (brk (g_brk + size) == -1)
358     return 0;
359   char *p = g_brk;
360   g_brk += size;
361   return p;
362 }
363
364 void *
365 memcpy (void *dest, void const *src, size_t n)
366 {
367   char* p = dest;
368   char* q = src;
369   while (n--) *p++ = *q++;
370   return dest;
371 }
372
373 void *
374 realloc (void *ptr, size_t size)
375 {
376   void *new = malloc (size);
377   if (ptr && new)
378     {
379       memcpy (new, ptr, size);
380       free (ptr);
381     }
382   return new;
383 }
384
385 int
386 strncmp (char const* a, char const* b, int length)
387 {
388   while (*a && *b && *a == *b && --length) {a++;b++;}
389   return *a - *b;
390 }
391
392 char *
393 getenv (char const* s)
394 {
395   char **p = g_environment;
396   int length = strlen (s);
397   while (*p)
398     {
399       if (!strncmp (s, *p, length) && *(*p + length) == '=') return (*p + length + 1);
400       p++;
401     }
402   return 0;
403 }
404
405 int
406 vprintf (char const* format, va_list ap)
407 {
408   char const *p = format;
409   while (*p)
410     if (*p != '%')
411       putchar (*p++);
412     else
413       {
414         p++;
415         char c = *p;
416         switch (c)
417           {
418           case '%': {putchar (*p); break;}
419           case 'c': {char c; c = va_arg (ap, char); putchar (c); break;}
420           case 'd': {int d; d = va_arg (ap, int); puts (itoa (d)); break;}
421           case 's': {char *s; s = va_arg (ap, char *); puts (s); break;}
422           default: {putchar (*p); break;}
423           }
424         p++;
425       }
426   va_end (ap);
427   return 0;
428 }
429
430 int
431 printf (char const* format, ...)
432 {
433   va_list ap;
434   va_start (ap, format);
435   int r = vprintf (format, ap);
436   va_end (ap);
437   return r;
438 }
439
440 int
441 vsprintf (char *str, char const* format, va_list ap)
442 {
443   char const *p = format;
444   while (*p)
445     if (*p != '%')
446       *str++ = *p++;
447     else
448       {
449         p++;
450         char c = *p;
451         switch (c)
452           {
453           case '%': {*str++ = *p; break;}
454           case 'c': {char c; c = va_arg (ap, char); *str++ = c; break;}
455           case 'd': {int d; d = va_arg (ap, int); char const *s; s = itoa (d); while (*s) *str++ = *s++; break;}
456           case 's': {char *s; s = va_arg (ap, char *); while (*s) *str++ = *s++; break;}
457           default: {*str++ = *p; break;}
458           }
459         p++;
460       }
461   va_end (ap);
462   *str = 0;
463   return strlen (str);
464 }
465
466 int
467 sprintf (char *str, char const* format, ...)
468 {
469   va_list ap;
470   va_start (ap, format);
471   int r = vsprintf (str, format, ap);
472   va_end (ap);
473   return r;
474 }