mlibc: Tinycc support: itoab, for debugging.
[mes.git] / lib / 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 chmod ()
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_chmod");             // mov    $0x0f,%eax
78   asm ("int____$0x80");                           // int    $0x80
79 }
80
81 void
82 access ()
83 {
84   asm ("mov____0x8(%ebp),%ebx !8");               // mov    0x8(%ebp),%ebx
85   asm ("mov____0x8(%ebp),%ecx !12");              // mov    0x8(%ebp),%ecx
86
87   asm ("mov____$i32,%eax SYS_access");            // mov    $0x21,%eax
88   asm ("int____$0x80");                           // int    $0x80
89 }
90
91 void
92 brk ()
93 {
94   asm ("mov____0x8(%ebp),%ebx !8");               // mov    0x8(%ebp),%ebx
95
96   asm ("mov____$i32,%eax SYS_brk");               // mov    $0x2d,%eax
97   asm ("int____$0x80");                           // int    $0x80
98 }
99
100 void
101 fsync ()
102 {
103   asm ("mov____0x8(%ebp),%ebx !8");               // mov    0x8(%ebp),%ebx
104
105   asm ("mov____$i32,%eax SYS_fsync");             // mov    $0x7c,%eax
106   asm ("int____$0x80");                           // int    $0x80
107 }
108
109 int
110 strlen (char const* s)
111 {
112   int i = 0;
113   while (s[i]) i++;
114   return i;
115 }
116
117 int
118 eputc (int c)
119 {
120   return fputc (c, 2);
121 }
122
123 int
124 eputs (char const* s)
125 {
126   int i = strlen (s);
127   write (2, s, i);
128   return 0;
129 }
130
131 int
132 fputs (char const* s, int fd)
133 {
134   int i = strlen (s);
135   write (fd, s, i);
136   return 0;
137 }
138
139 int
140 puts (char const* s)
141 {
142   int i = strlen (s);
143   write (1, s, i);
144   return 0;
145 }
146
147 int
148 putchar (int c)
149 {
150   write (1, (char*)&c, 1);
151   return 0;
152 }
153
154 int
155 fputc (int c, int fd)
156 {
157   write (fd, (char*)&c, 1);
158   return 0;
159 }
160
161 void
162 assert_fail (char* s)
163 {
164   eputs ("assert fail: ");
165   eputs (s);
166   eputs ("\n");
167   //*((int*)0) = 0;
168   char *fail = s;
169   fail = 0;
170   *fail = 0;
171 }
172
173 int ungetc_char = -1;
174 char ungetc_buf[2];
175
176 int
177 getchar ()
178 {
179   char c;
180   int i;
181   if (ungetc_char == -1)
182     {
183       int r = read (g_stdin, &c, 1);
184       if (r < 1) return -1;
185       i = c;
186    }
187   else
188     {
189        //FIXME
190        //i = ungetc_buf[ungetc_char--];
191        i = ungetc_buf[ungetc_char];
192        //ungetc_char--;
193        ungetc_char = ungetc_char - 1;
194      }
195   if (i < 0) i += 256;
196
197   return i;
198 }
199
200 int
201 fgetc (int fd)
202 {
203   char c;
204   int i;
205   int r = read (fd, &c, 1);
206   if (r < 1) return -1;
207   i = c;
208   return i;
209 }
210
211 void
212 free (void *ptr)
213 {
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 char const*
280 itoab (int x, int base)
281 {
282   //static char itoa_buf[10];
283   //char *p = buf+9;
284   char *p = itoa_buf;
285   p += 9;
286   *p-- = 0;
287
288   //int sign = x < 0; // FIXME
289   int sign = 0;
290   if (x < 0) sign = 1;
291   if (sign)
292     x = -x;
293
294   do
295      {
296        int i = x % base;
297        *p-- = i > 9 ? 'a' + i - 10 : '0' + i;
298        x = x / base;
299      } while (x);
300
301   if (sign && *(p + 1) != '0')
302     *p-- = '-';
303
304   return p+1;
305 }
306
307 int
308 isdigit (int c)
309 {
310   return (c>='0') && (c<='9');
311 }
312
313 int
314 isxdigit (int c)
315 {
316   return isdigit (c) || (c>='a') && (c<='f');
317 }
318
319 int
320 isnumber (int c, int base)
321 {
322   if (base == 2)
323     return (c>='0') && (c<='1');
324   if (base == 8)
325     return (c>='0') && (c<='7');
326   if (base == 10)
327     return isdigit (c);
328   if (base == 16)
329     return isxdigit (c);
330 }
331
332 int
333 _atoi (char const **p, int base)
334 {
335   char const *s = *p;
336   int i = 0;
337   int sign = 1;
338   if (!base) base = 10;
339   if (*s && *s == '-')
340     {
341       sign = -1;
342       s++;
343     }
344   while (isnumber (*s, base))
345     {
346       i *= base;
347       int m = *s > '9' ? 'a' - 10 : '0';
348       i += *s - m;
349       s++;
350     }
351   *p = s;
352   return i * sign;
353 }
354
355 int
356 atoi (char const *s)
357 {
358   char const *p = s;
359   return _atoi (&p, 0);
360 }
361
362 char *g_brk = 0;
363
364 void *
365 malloc (size_t size)
366 {
367   if (!g_brk)
368     g_brk = brk (0);
369   if (brk (g_brk + size) == -1)
370     return 0;
371   char *p = g_brk;
372   g_brk += size;
373   return p;
374 }
375
376 void *
377 memcpy (void *dest, void const *src, size_t n)
378 {
379   char* p = dest;
380   char* q = src;
381   while (n--) *p++ = *q++;
382   return dest;
383 }
384
385 void *
386 realloc (void *ptr, size_t size)
387 {
388   void *new = malloc (size);
389   if (ptr && new)
390     {
391       memcpy (new, ptr, size);
392       free (ptr);
393     }
394   return new;
395 }
396
397 int
398 strncmp (char const* a, char const* b, int length)
399 {
400   while (*a && *b && *a == *b && --length) {a++;b++;}
401   return *a - *b;
402 }
403
404 char *
405 getenv (char const* s)
406 {
407   char **p = g_environment;
408   int length = strlen (s);
409   while (*p)
410     {
411       if (!strncmp (s, *p, length) && *(*p + length) == '=') return (*p + length + 1);
412       p++;
413     }
414   return 0;
415 }
416
417 int
418 vprintf (char const* format, va_list ap)
419 {
420   char const *p = format;
421   while (*p)
422     if (*p != '%')
423       putchar (*p++);
424     else
425       {
426         p++;
427         char c = *p;
428         switch (c)
429           {
430           case '%': {putchar (*p); break;}
431           case 'c': {char c; c = va_arg (ap, char); putchar (c); break;}
432           case 'd': {int d; d = va_arg (ap, int); puts (itoa (d)); break;}
433           case 's': {char *s; s = va_arg (ap, char *); puts (s); break;}
434           default: {putchar (*p); break;}
435           }
436         p++;
437       }
438   va_end (ap);
439   return 0;
440 }
441
442 int
443 printf (char const* format, ...)
444 {
445   va_list ap;
446   va_start (ap, format);
447   int r = vprintf (format, ap);
448   va_end (ap);
449   return r;
450 }
451
452 int
453 vsprintf (char *str, char const* format, va_list ap)
454 {
455   char const *p = format;
456   while (*p)
457     if (*p != '%')
458       *str++ = *p++;
459     else
460       {
461         p++;
462         char c = *p;
463         switch (c)
464           {
465           case '%': {*str++ = *p; break;}
466           case 'c': {char c; c = va_arg (ap, char); *str++ = c; break;}
467           case 'd': {int d; d = va_arg (ap, int); char const *s; s = itoa (d); while (*s) *str++ = *s++; break;}
468           case 's': {char *s; s = va_arg (ap, char *); while (*s) *str++ = *s++; break;}
469           default: {*str++ = *p; break;}
470           }
471         p++;
472       }
473   va_end (ap);
474   *str = 0;
475   return strlen (str);
476 }
477
478 int
479 sprintf (char *str, char const* format, ...)
480 {
481   va_list ap;
482   va_start (ap, format);
483   int r = vsprintf (str, format, ap);
484   va_end (ap);
485   return r;
486 }