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