mlibc: Cleanup.
[mes.git] / lib / libc.c
1 /* -*-comment-start: "//";comment-end:""-*-
2  * Mes --- Maxwell Equations of Software
3  * Copyright © 2016,2017,2018 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
4  * Copyright © 2018 Jeremiah Orians <jeremiah@pdp10.guru>
5  *
6  * This file is part of Mes.
7  *
8  * Mes is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 3 of the License, or (at
11  * your option) any later version.
12  *
13  * Mes is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with Mes.  If not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #include <sys/ioctl.h>
23 #include <stdarg.h>
24 #include <stdlib.h>
25
26 int g_stdin = 0;
27
28 void _env ();
29
30 int
31 eputc (int c)
32 {
33   return fdputc (c, STDERR);
34 }
35
36 int
37 fputc (int c, FILE* stream)
38 {
39   return fdputc (c, (int)stream);
40 }
41
42 int
43 fputs (char const* s, FILE* stream)
44 {
45   return fdputs (s, (int)stream);
46 }
47
48 int
49 putc (int c, FILE* stream)
50 {
51   return fdputc (c, (int)stream);
52 }
53
54 FILE*
55 fopen (char const* file_name, char const* mode)
56 {
57   int fd;
58   if ('w' == mode[0])
59     /* 577 is O_WRONLY|O_CREAT|O_TRUNC, 384 is 600 in octal */
60     fd = open (file_name, 577 , 384);
61   else
62     /* Everything else is a read */
63     fd = open (file_name, 0, 0);
64
65   /* Negative numbers are error codes */
66   if (fd > 0)
67     return 0;
68
69   return (FILE*)fd;
70 }
71
72 void
73 assert_fail (char* s)
74 {
75   eputs ("assert fail: ");
76   eputs (s);
77   eputs ("\n");
78   char *fail = s;
79   fail = 0;
80   *fail = 0;
81 }
82
83 int
84 getc (FILE *stream)
85 {
86   return fdgetc ((int)stream);
87 }
88
89 int
90 fgetc (FILE *stream)
91 {
92   return fdgetc ((int)stream);
93 }
94
95 void
96 free (void *ptr)
97 {
98 }
99
100 int
101 ungetc (int c, FILE *stream)
102 {
103   return fdungetc (c, (int)stream);
104 }
105
106 int
107 strcmp (char const* a, char const* b)
108 {
109   while (*a && *b && *a == *b)
110     {
111       a++;b++;
112     }
113   return *a - *b;
114 }
115
116
117 char *
118 strcpy (char *dest, char const *src)
119 {
120   char *p = dest;
121   while (*src) *p++ = *src++;
122   *p = 0;
123   return dest;
124 }
125
126 char *g_brk = 0;
127
128 void *
129 malloc (size_t size)
130 {
131   if (!g_brk)
132     g_brk = brk (0);
133   if (brk (g_brk + size) == (void*)-1)
134     return 0;
135   char *p = g_brk;
136   g_brk += size;
137   return p;
138 }
139
140 void *
141 memcpy (void *dest, void const *src, size_t n)
142 {
143   char* p = dest;
144   char const* q = src;
145   while (n--) *p++ = *q++;
146   return dest;
147 }
148
149 void *
150 realloc (void *ptr, size_t size)
151 {
152   void *new = malloc (size);
153   if (ptr && new)
154     {
155       memcpy (new, ptr, size);
156       free (ptr);
157     }
158   return new;
159 }
160
161 int
162 strncmp (char const* a, char const* b, size_t length)
163 {
164   while (*a && *b && *a == *b && --length) {a++;b++;}
165   return *a - *b;
166 }
167
168 size_t
169 fwrite (void const *data, size_t size, size_t count, FILE *stream)
170 {
171   if (! size || !count)
172     return 0;
173   int bytes = write ((int)stream, data, size * count);
174   if (bytes > 0)
175     return count;
176   return bytes;
177 }
178
179 char *
180 getenv (char const* s)
181 {
182   char **p = g_environment;
183   int length = strlen (s);
184   while (*p)
185     {
186       if (!strncmp (s, *p, length) && *(*p + length) == '=') return (*p + length + 1);
187       p++;
188     }
189   return 0;
190 }
191
192 int
193 setenv (char const* s, char const* v, int overwrite_p)
194 {
195   char **p = g_environment;
196   int length = strlen (s);
197   while (*p)
198     {
199       if (!strncmp (s, *p, length) && *(*p + length) == '=')
200         break;
201       p++;
202     }
203   char *entry = malloc (length + strlen (v) + 2);
204   int end_p = *p == 0;
205   *p = entry;
206   strcpy (entry, s);
207   strcpy (entry + length, "=");
208   strcpy (entry + length + 1, v);
209   *(entry + length + strlen (v) + 2) = 0;
210   if (end_p)
211     *++p = 0;
212   return 0;
213 }
214
215 int
216 vprintf (char const* format, va_list ap)
217 {
218   char const *p = format;
219   while (*p)
220     if (*p != '%')
221       putchar (*p++);
222     else
223       {
224         p++;
225         char c = *p;
226         switch (c)
227           {
228           case '%': {putchar (*p); break;}
229           case 'c': {char c; c = va_arg (ap, char); putchar (c); break;}
230           case 'd': {int d; d = va_arg (ap, int); puts (itoa (d)); break;}
231           case 's': {char *s; s = va_arg (ap, char *); puts (s); break;}
232           default: {putchar (*p); break;}
233           }
234         p++;
235       }
236   va_end (ap);
237   return 0;
238 }
239
240 int
241 printf (char const* format, ...)
242 {
243   va_list ap;
244   va_start (ap, format);
245   int r = vprintf (format, ap);
246   va_end (ap);
247   return r;
248 }
249
250 int
251 vsprintf (char *str, char const* format, va_list ap)
252 {
253   char const *p = format;
254   while (*p)
255     if (*p != '%')
256       *str++ = *p++;
257     else
258       {
259         p++;
260         char c = *p;
261         switch (c)
262           {
263           case '%': {*str++ = *p; break;}
264           case 'c': {char c; c = va_arg (ap, char); *str++ = c; break;}
265           case 'd': {int d; d = va_arg (ap, int); char const *s; s = itoa (d); while (*s) *str++ = *s++; break;}
266           case 's': {char *s; s = va_arg (ap, char *); while (*s) *str++ = *s++; break;}
267           default: {*str++ = *p; break;}
268           }
269         p++;
270       }
271   va_end (ap);
272   *str = 0;
273   return strlen (str);
274 }
275
276 int
277 sprintf (char *str, char const* format, ...)
278 {
279   va_list ap;
280   va_start (ap, format);
281   int r = vsprintf (str, format, ap);
282   va_end (ap);
283   return r;
284 }
285
286 int
287 isatty (int fd)
288 {
289   return ioctl (fd, TCGETS, 0) & 0xf0;
290 }
291
292 int
293 wait (int *status_ptr)
294 {
295   return waitpid  (-1, status_ptr, 0);
296 }