mescc: Have ungetc remember 2 positions.
[mes.git] / 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 #if __GNUC__
22 int g_stdin = 0;
23 typedef long size_t;
24 void *malloc (size_t i);
25 int open (char const *s, int mode);
26 int read (int fd, void* buf, size_t n);
27 void write (int fd, char const* s, int n);
28
29 #define INT_MIN -2147483648
30 #define INT_MAX 2147483647
31
32 void
33 exit (int code)
34 {
35   asm (
36        "movl %0,%%ebx\n\t"
37        "movl $1,%%eax\n\t"
38        "int  $0x80"
39        : // no outputs "=" (r)
40        : "" (code)
41        );
42   // not reached
43   exit (0);
44 }
45
46 char const*
47 getenv (char const* p)
48 {
49   return 0;
50 }
51
52 int
53 read (int fd, void* buf, size_t n)
54 {
55   int r;
56   //syscall (SYS_write, fd, s, n));
57   asm (
58        "movl %1,%%ebx\n\t"
59        "movl %2,%%ecx\n\t"
60        "movl %3,%%edx\n\t"
61
62        "movl $0x3,%%eax\n\t"
63        "int  $0x80\n\t"
64
65        "mov %%eax,%0\n\t"
66        : "=r" (r)
67        : "" (fd), "" (buf), "" (n)
68        : "eax", "ebx", "ecx", "edx"
69        );
70   return r;
71 }
72
73 int
74 open (char const *s, int mode)
75 {
76   int r;
77   //syscall (SYS_open, mode));
78   asm (
79        "mov %1,%%ebx\n\t"
80        "mov %2,%%ecx\n\t"
81        "mov $0x5,%%eax\n\t"
82        "int $0x80\n\t"
83        "mov %%eax,%0\n\t"
84        : "=r" (r)
85        : "" (s), "" (mode)
86        : "eax", "ebx", "ecx"
87        );
88   return r;
89 }
90
91 int puts (char const*);
92 char const* itoa (int);
93
94 void
95 write (int fd, char const* s, int n)
96 {
97   int r;
98   //syscall (SYS_write, fd, s, n));
99   asm (
100        "mov %0,%%ebx\n\t"
101        "mov %1,%%ecx\n\t"
102        "mov %2,%%edx\n\t"
103
104        "mov $0x4, %%eax\n\t"
105        "int $0x80\n\t"
106        : // no outputs "=" (r)
107        : "" (fd), "" (s), "" (n)
108        : "eax", "ebx", "ecx", "edx"
109        );
110 }
111
112 void *
113 brk (void *p)
114 {
115   void *r;
116   asm (
117        "mov %1,%%ebx\n\t"
118
119        "mov $0x2d,%%eax\n\t"
120        "int $0x80\n\t"
121
122        "mov %%eax,%0\n\t"
123        : "=r" (r)
124        : "" (p)
125        : "eax", "ebx"
126        );
127   return r;
128 }
129
130 int
131 putchar (int c)
132 {
133   //write (STDOUT, s, strlen (s));
134   //int i = write (STDOUT, s, strlen (s));
135   write (1, (char*)&c, 1);
136   return 0;
137 }
138
139 void *g_malloc_base = 0;
140
141 void *
142 malloc (size_t size)
143 {
144   void *p = brk (0);
145   if (!g_malloc_base) g_malloc_base = p;
146   brk (p+size);
147   return p;
148 }
149
150 void *
151 realloc (void *p, size_t size)
152 {
153   (void)p;
154   brk (g_malloc_base + size);
155   return g_malloc_base;
156 }
157
158 void
159 free (void *p)
160 {
161   int *n = (int*)p-1;
162   //munmap ((void*)p, *n);
163 }
164
165 #define EOF -1
166 #define STDIN 0
167 #define STDOUT 1
168 #define STDERR 2
169
170 size_t
171 strlen (char const* s)
172 {
173   int i = 0;
174   while (s[i]) i++;
175   return i;
176 }
177
178 int
179 strcmp (char const* a, char const* b)
180 {
181   while (*a && *b && *a == *b) {a++;b++;}
182   return *a - *b;
183 }
184
185 int
186 eputs (char const* s)
187 {
188   //int i = write (STDERR, s, strlen (s));
189   int i = strlen (s);
190   write (2, s, i);
191   return 0;
192 }
193
194 int
195 fputs (char const* s, int fd)
196 {
197   //int i = write (fd, s, strlen (s));
198   int i = strlen (s);
199   write (fd, s, i);
200   return 0;
201 }
202
203 int
204 puts (char const* s)
205 {
206   //int i = write (STDOUT, s, strlen (s));
207   int i = strlen (s);
208   write (1, s, i);
209   return 0;
210 }
211
212 void
213 assert_fail (char* s)
214 {
215   eputs ("assert fail: ");
216   eputs (s);
217   eputs ("\n");
218   *((int*)0) = 0;
219 }
220
221 #define assert(x) ((x) ? (void)0 : assert_fail (#x))
222
223
224 int ungetc_char = -1;
225 char ungetc_buf[2];
226
227 int
228 getchar ()
229 {
230   char c;
231   int i;
232   if (ungetc_char == -1)
233     {
234       int r = read (g_stdin, &c, 1);
235       if (r < 1) return -1;
236       i = c;
237     }
238   else
239     i = ungetc_buf[ungetc_char--];
240
241   if (i < 0) i += 256;
242   return i;
243 }
244
245 int
246 ungetc (int c, int fd)
247 {
248   assert (ungetc_char < 2);
249   ungetc_buf[++ungetc_char] = c;
250   return c;
251 }
252
253 char itoa_buf[10];
254
255 char const*
256 itoa (int x)
257 {
258   //static char itoa_buf[10];
259   //char *p = buf+9;
260   char *p = itoa_buf;
261   p += 9;
262   *p-- = 0;
263
264   //int sign = x < 0;
265   int sign;
266   sign = x < 0;
267   if (sign)
268     x = -x;
269
270   do
271     {
272       *p-- = '0' + (x % 10);
273       x = x / 10;
274     } while (x);
275
276   if (sign)
277     *p-- = '-';
278
279   return p+1;
280 }
281
282 int
283 isdigit (int c)
284 {
285   return (c>='0') && (c<='9');
286 }
287 #endif