mlibc: Implement strstr.
[mes.git] / lib / libc+tcc.c
1 /* -*-comment-start: "//";comment-end:""-*-
2  * Mes --- Maxwell Equations of Software
3  * Copyright © 2017,2018 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
4  * Copyright (C) 2018 Han-Wen Nienhuys <hanwen@xs4all.nl>
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 <setjmp.h>
23 #include <stdarg.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <time.h>
28 #include <signal.h>
29 #include <sys/mman.h>
30 #include <sys/time.h>
31 #include <unistd.h>
32
33 int
34 dlclose (void *handle)
35 {
36   return 0;
37 }
38
39 void *
40 dlopen (char const *filename, int flags)
41 {
42   return 0;
43 }
44
45 int
46 execvp (char const *file, char *const argv[])
47 {
48   eputs ("execvp stub\n");
49   return 0;
50 }
51
52 int
53 fclose (FILE *stream)
54 {
55   int fd = (int)stream;
56   return close (fd);
57 }
58
59 FILE *
60 fdopen (int fd, char const *mode)
61 {
62   return (FILE*)fd;
63 }
64
65 int
66 ferror (FILE *stream)
67 {
68   int fd = (int)stream;
69   if (fd == -1) return -1;
70   return 0;
71 }
72
73 int
74 fflush (FILE *stream)
75 {
76   eputs ("fflush stub\n");
77   return 0;
78 }
79
80 int
81 fprintf (FILE *stream, char const *format, ...)
82 {
83   va_list ap;
84   va_start (ap, format);
85   int r = vfprintf (stream, format, ap);
86   va_end (ap);
87   return r;
88 }
89
90 size_t
91 fread (void *data, size_t size, size_t count, FILE *stream)
92 {
93   if (! size || !count)
94     return 0;
95   int bytes = read ((int)stream, data, size * count);
96   if (bytes > 0)
97     return bytes/size;
98
99   return bytes;
100 }
101
102 long
103 ftell (FILE *stream)
104 {
105   return lseek ((int)stream, 0, SEEK_CUR);
106 }
107
108 int
109 fseek (FILE *stream, long offset, int whence)
110 {
111   return lseek ((int)stream, offset, whence);
112 }
113
114 int
115 gettimeofday (struct timeval *tv, struct timezone *tz)
116 {
117   return 0;
118 }
119
120 double
121 ldexp (double x, int exp)
122 {
123   eputs ("ldexp stub\n");
124   return 0;
125 }
126
127 struct tm *
128 localtime (time_t const *timep)
129 {
130   eputs ("localtime stub\n");
131   return 0;
132 }
133
134 void *
135 memmove (void *dest, void const *src, size_t n)
136 {
137   if (dest < src)
138     return memcpy (dest, src, n);
139   char *p = dest + n;
140   char const *q = src +n;
141   while (n--)
142     *--p = *--q;
143   return dest;
144 }
145
146 void *
147 memset (void *s, int c, size_t n)
148 {
149   char *p = s;
150   while (n--) *p++ = c;
151   return s;
152 }
153
154 int
155 memcmp (void const *s1, void const *s2, size_t n)
156 {
157   char *a = s1;
158   char *b = s2;
159   while (*a == *b && --n) {a++;b++;}
160   return *a - *b;
161 }
162
163 int
164 mprotect (void *addr, size_t len, int prot)
165 {
166   return 0;
167 }
168
169 void
170 qswap (void *a, void *b, size_t size)
171 {
172   char *buf[8];
173   memcpy (buf, a, size);
174   memcpy (a, b, size);
175   memcpy (b, buf, size);
176 }
177
178 size_t
179 qpart (void *base, size_t count, size_t size, int (*compare)(void const *, void const *))
180 {
181   void* p = base + count*size;
182   size_t i = 0;
183   for (size_t j = 0; j < count; j++)
184     {
185       if (compare (base+j*size, p) < 0)
186         {
187           qswap (base+i*size, base+j*size, size);
188           i++;
189         }
190     }
191   if (compare (base+count*size, base+i*size) < 0)
192     qswap (base+i*size, base+count*size, size);
193   return i;
194 }
195
196 void
197 qsort (void *base, size_t count, size_t size, int (*compare)(void const *, void const *))
198 {
199   if (count > 1)
200     {
201       int p = qpart (base, count-1, size, compare);
202       qsort (base, p, size, compare);
203       qsort (base+p*size, count-p, size, compare);
204     }
205 }
206
207 int
208 remove (char const *file_name)
209 {
210   eputs ("remove stub\n");
211   return 0;
212 }
213
214 int
215 sigaction (int signum, struct sigaction const *act, struct sigaction *oldact)
216 {
217   return 0;
218 }
219
220 int
221 sigemptyset (sigset_t *set)
222 {
223   return 0;
224 }
225
226 int
227 snprintf(char *str,  size_t size,  char const *format, ...)
228 {
229   va_list ap;
230   va_start (ap, format);
231   int r = vsprintf (str, format, ap);
232   va_end (ap);
233   return r;
234 }
235
236 int
237 sscanf (char const *str, const char *format, ...)
238 {
239   eputs ("sscanf stub\n");
240   return 0;
241 }
242
243 char *
244 strcat (char *dest, char const *src)
245 {
246   char *p = strchr (dest, '\0');
247   while (*src++) *p++ = *src++;
248   *p = 0;
249   return dest;
250 }
251
252 char *
253 strchr (char const *s, int c)
254 {
255   char const *p = s;
256   while (*p || !c)
257     {
258       if (c == *p) return p;
259       *p++;
260     }
261   return 0;
262 }
263
264 char *
265 strncpy (char *dest, char const *src, size_t length)
266 {
267   char *p = dest;
268   while (*src && length--)
269     *p++ = *src++;
270   if (*src)
271     length++;
272   while (length--)
273     *p++ = 0;
274   return dest;
275 }
276
277 char *
278 strrchr (char const *s, int c)
279 {
280   int n = strlen (s);
281   if (!n) return 0;
282   char const *p = s + n - 1;
283   while (*p || !c)
284     {
285       if (c == *p) return p;
286       *p--;
287     }
288   return 0;
289 }
290
291 /** locate a substring. #memmem# finds the first occurrence of
292     #needle# in #haystack#.  This is not ANSI-C.
293
294     The prototype is not in accordance with the Linux Programmer's
295     Manual v1.15, but it is with /usr/include/string.h   */
296
297 unsigned char *
298 _memmem (unsigned char const *haystack, int haystack_len,
299          unsigned char const *needle, int needle_len)
300 {
301   unsigned char const *end_haystack = haystack + haystack_len - needle_len + 1;
302   unsigned char const *end_needle = needle + needle_len;
303
304   /* Ahhh ... Some minimal lowlevel stuff. This *is* nice; Varation
305      is the spice of life */
306   while (haystack < end_haystack)
307     {
308       unsigned char const *subneedle = needle;
309       unsigned char const *subhaystack = haystack;
310       while (subneedle < end_needle)
311         if (*subneedle++ != *subhaystack++)
312           goto next;
313
314       /* Completed the needle.  Gotcha.  */
315       return (unsigned char *) haystack;
316     next:
317       haystack++;
318     }
319   return 0;
320 }
321
322 void *
323 memmem (void const *haystack, int haystack_len,
324         void const *needle, int needle_len)
325 {
326   unsigned char const *haystack_byte_c = (unsigned char const *)haystack;
327   unsigned char const *needle_byte_c = (unsigned char const *)needle;
328   return _memmem (haystack_byte_c, haystack_len, needle_byte_c, needle_len);
329 }
330
331 char *
332 strstr (char const *haystack, char const *needle)
333 {
334   return memmem (haystack, strlen (haystack), needle, strlen (needle));
335 }
336
337 double
338 strtod (char const *nptr, char **endptr)
339 {
340   eputs ("strtoul stub\n");
341 }
342
343 float
344 strtof (char const *nptr, char **endptr)
345 {
346   return strtod (nptr, endptr);
347 }
348
349 long double
350 strtold (char const *nptr, char **endptr)
351 {
352   return strtod (nptr, endptr);
353 }
354
355 long
356 strtol (char const *nptr, char **endptr, int base)
357 {
358   if (!strncmp (nptr, "0x", 2))
359     {
360       char const *p = nptr + 2;
361       return abtoi (&p, 16);
362     }
363   return abtoi (&nptr, base);
364 }
365
366 long long int
367 strtoll (char const *nptr, char **endptr, int base)
368 {
369   eputs ("strtoll stub\n");
370   return 0;
371 }
372
373 unsigned long
374 strtoul (char const *nptr, char **endptr, int base)
375 {
376   eputs ("strtoul stub\n");
377   return 0;
378 }
379
380 unsigned long long
381 strtoull (char const *p, char **endptr, int base)
382 {
383   *endptr = p;
384   return abtoi (endptr, base);
385 }
386
387 time_t time (time_t *tloc)
388 {
389   return 0;
390 }
391
392 int
393 vsnprintf (char *str, size_t size, char const *format, va_list ap)
394 {
395   return vsprintf (str, format, ap);
396 }
397
398 void *
399 calloc (size_t nmemb, size_t size)
400 {
401   size_t count = nmemb * size;
402   void *p = malloc (count);
403   memset (p, 0, count);
404   return p;
405 }
406
407 int
408 vfprintf (FILE* f, char const* format, va_list ap)
409 {
410   int fd = (int)f;
411   char const *p = format;
412   while (*p)
413     if (*p != '%')
414       fputc (*p++, fd);
415     else
416       {
417         p++;
418         char c = *p;
419         switch (c)
420           {
421           case '%': {fputc (*p, fd); break;}
422           case 'c': {char c; c = va_arg (ap, char); fputc (c, fd); break;}
423           case 'd': {int d; d = va_arg (ap, int); fputs (itoa (d), fd); break;}
424           case 's': {char *s; s = va_arg (ap, char *); fputs (s, fd); break;}
425           default: {fputc (*p, fd); break;}
426           }
427         p++;
428       }
429   va_end (ap);
430   return 0;
431 }