mescc: Support binutils 2.25: memcmp: Support size 0.
[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 © 2018 Jeremiah Orians <jeremiah@pdp10.guru>
5  * Copyright (C) 2018 Han-Wen Nienhuys <hanwen@xs4all.nl>
6  *
7  * This file is part of Mes.
8  *
9  * Mes is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 3 of the License, or (at
12  * your option) any later version.
13  *
14  * Mes is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with Mes.  If not, see <http://www.gnu.org/licenses/>.
21  */
22
23 #include <errno.h>
24 #include <fcntl.h>
25 #include <setjmp.h>
26 #include <stdarg.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <time.h>
31 #include <signal.h>
32 #include <sys/mman.h>
33 #include <sys/stat.h>
34 #include <sys/time.h>
35 #include <unistd.h>
36
37 #include <libc.c>
38 #include <linux+tcc.c>
39
40 #if __MESC__
41
42 #include <libc+tcc-mes.c>
43
44 #else // !__MESC__
45
46 #include <libc+tcc-gcc.c>
47
48 #endif // !__MESC__
49
50 int
51 dlclose (void *handle)
52 {
53   return 0;
54 }
55
56 void *
57 dlopen (char const *filename, int flags)
58 {
59   return 0;
60 }
61
62 char *
63 search_path (char const *file_name)
64 {
65   static char buf[256];
66   char *path = getenv ("PATH");
67   if (__mes_debug ())
68     {
69       eputs ("\n search-path: "); eputs (file_name); eputs ("\n");
70     }
71   while (*path)
72     {
73       char *end = strchr (path, ':');
74       if (!end)
75         end = strchr (path, '\0');
76       strncpy (buf, path, end - path);
77       buf[end - path] = 0;
78       if (__mes_debug ())
79         {
80           eputs (" dir: "); eputs (buf); eputs ("\n");
81         }
82       if (buf[end - path] != '/')
83         strcat (buf, "/");
84       strcat (buf, file_name);
85       if (!access (buf, X_OK))
86         {
87           if (__mes_debug ())
88             {
89               eputs (" found: "); eputs (buf); eputs ("\n");
90             }
91           return buf;
92         }
93       path = end + 1;
94     }
95   return 0;
96 }
97
98 int
99 execvp (char const *file_name, char *const argv[])
100 {
101   if (file_name[0] != '/')
102     file_name = search_path (file_name);
103   if (!file_name)
104     {
105       errno = ENOENT;
106       return -1;
107     }
108   if (__mes_debug ())
109     {
110       eputs (" EXEC: "); eputs (file_name); eputs ("\n");
111       int i = 0;
112       while (argv[i])
113         {
114           eputs (" arg["); eputs (itoa (i)); eputs ("]: "); eputs (argv[i]); eputs ("\n");
115           i++;
116         }
117     }
118   return execve (file_name, argv, environ);
119 }
120
121 int
122 fclose (FILE *stream)
123 {
124   int fd = (int)stream;
125   return close (fd);
126 }
127
128 FILE *
129 fdopen (int fd, char const *mode)
130 {
131   return (FILE*)fd;
132 }
133
134 int
135 ferror (FILE *stream)
136 {
137   int fd = (int)stream;
138   if (fd == -1) return -1;
139   return 0;
140 }
141
142 int
143 fflush (FILE *stream)
144 {
145   fsync ((int)stream);
146 }
147
148 int
149 fprintf (FILE *stream, char const *format, ...)
150 {
151   va_list ap;
152   va_start (ap, format);
153   int r = vfprintf (stream, format, ap);
154   va_end (ap);
155   return r;
156 }
157
158 int
159 _fungetc_p (FILE *stream)
160 {
161   return _fdungetc_p ((int)stream);
162 }
163
164 size_t
165 fread (void *data, size_t size, size_t count, FILE *stream)
166 {
167   if (! size || !count)
168     return 0;
169
170   size_t todo = size * count;
171   char *buf = (char*)data;
172
173   int bytes = 0;
174   while (_fungetc_p (stream) && todo-- && ++bytes)
175     *buf++ = fgetc (stream);
176   if (todo)
177     {
178       int r = read ((int)stream, buf, todo);
179       if (r < 0 && !bytes)
180         bytes = r;
181       else
182         bytes += r;
183     }
184
185   if (__mes_debug ())
186     {
187       eputs ("fread fd="); eputs (itoa ((int)stream));
188       eputs (" bytes="); eputs (itoa (bytes)); eputs ("\n");
189       static char buf[4096];
190       if (bytes > 0 && bytes < sizeof (buf))
191         {
192           strncpy (buf, data, bytes);
193           buf[bytes] = 0;
194           eputs ("fread buf="); eputs (buf); eputs ("\n");
195         }
196     }
197
198   if (bytes > 0)
199     return bytes/size;
200
201   return 0;
202 }
203
204 size_t
205 fwrite (void const *data, size_t size, size_t count, FILE *stream)
206 {
207   if (__mes_debug ())
208     {
209       eputs ("fwrite "); eputs (itoa ((int)stream));
210       eputs ("  "); eputs (itoa (size)); eputs ("\n");
211     }
212
213   if (! size || !count)
214     return 0;
215   int bytes = write ((int)stream, data, size * count);
216
217   if (__mes_debug ())
218     {
219       eputs (" => "); eputs (itoa (bytes)); eputs ("\n");
220     }
221
222   if (bytes > 0)
223     return bytes/size;
224   return 0;
225 }
226
227 long
228 ftell (FILE *stream)
229 {
230   return lseek ((int)stream, 0, SEEK_CUR);
231 }
232
233 FILE*
234 fopen (char const *file_name, char const *opentype)
235 {
236   if (__mes_debug ())
237     {
238       eputs ("fopen "); eputs (file_name);
239       eputs (" "); eputs (opentype); eputs ("\n");
240     }
241
242   int fd;
243   int mode = 0600;
244   if ((opentype[0] == 'a' || !strcmp (opentype, "r+"))
245       && !access (file_name, O_RDONLY))
246     {
247       int flags = O_RDWR;
248       if (opentype[0] == 'a')
249         flags |= O_APPEND;
250       fd = open (file_name, flags, mode);
251     }
252   else if (opentype[0] == 'w' || opentype[0] == 'a' || !strcmp (opentype, "r+"))
253     {
254       char *plus_p = strchr (opentype, '+');
255       int flags = plus_p ? O_RDWR | O_CREAT : O_WRONLY | O_CREAT | O_TRUNC;
256       fd = open (file_name, flags, mode);
257     }
258   else
259     fd = open (file_name, 0, 0);
260
261   if (__mes_debug ())
262     {
263       eputs (" => fd="); eputs (itoa (fd)); eputs ("\n");
264     }
265
266   if (!fd)
267     {
268       eputs (" ***MES LIB C*** fopen of stdin: signal me in band\n");
269       exit (1);
270     }
271   if (fd < 0)
272     fd = 0;
273   return (FILE*)fd;
274 }
275
276 int
277 fseek (FILE *stream, long offset, int whence)
278 {
279   int pos = lseek ((int)stream, offset, whence);
280   if (pos >= 0)
281     return 0;
282   return -1;
283 }
284
285 int
286 gettimeofday (struct timeval *tv, struct timezone *tz)
287 {
288   static int stub = 0;
289   if (__mes_debug () && !stub)
290     eputs ("gettimeofday stub\n");
291   stub = 1;
292   errno = 0;
293   return 0;
294 }
295
296 double
297 ldexp (double x, int exp)
298 {
299   static int stub = 0;
300   if (__mes_debug () && !stub)
301     eputs ("ldexp stub\n");
302   stub = 1;
303   return 0;
304 }
305
306 struct tm *
307 localtime (time_t const *timep)
308 {
309   static int stub = 0;
310   if (__mes_debug () && !stub)
311     eputs ("localtime stub\n");
312   stub = 1;
313   errno = 0;
314   return 0;
315 }
316
317 void *
318 memmove (void *dest, void const *src, size_t n)
319 {
320   if (dest < src)
321     return memcpy (dest, src, n);
322   char *p = dest + n;
323   char const *q = src +n;
324   while (n--)
325     *--p = *--q;
326   return dest;
327 }
328
329 void *
330 memset (void *s, int c, size_t n)
331 {
332   char *p = s;
333   while (n--) *p++ = c;
334   return s;
335 }
336
337 int
338 memcmp (void const *s1, void const *s2, size_t size)
339 {
340   if (!size)
341     return 0;
342   char *a = s1;
343   char *b = s2;
344   while (*a == *b && --size)
345     {
346       a++;
347       b++;
348     }
349   return *a - *b;
350 }
351
352 int
353 mprotect (void *addr, size_t len, int prot)
354 {
355   return 0;
356 }
357
358 void
359 qswap (void *a, void *b, size_t size)
360 {
361   char *buf[8];
362   memcpy (buf, a, size);
363   memcpy (a, b, size);
364   memcpy (b, buf, size);
365 }
366
367 size_t
368 qpart (void *base, size_t count, size_t size, int (*compare)(void const *, void const *))
369 {
370   void* p = base + count*size;
371   size_t i = 0;
372   for (size_t j = 0; j < count; j++)
373     {
374       if (compare (base+j*size, p) < 0)
375         {
376           qswap (base+i*size, base+j*size, size);
377           i++;
378         }
379     }
380   if (compare (base+count*size, base+i*size) < 0)
381     qswap (base+i*size, base+count*size, size);
382   return i;
383 }
384
385 void
386 qsort (void *base, size_t count, size_t size, int (*compare)(void const *, void const *))
387 {
388   if (count > 1)
389     {
390       int p = qpart (base, count-1, size, compare);
391       qsort (base, p, size, compare);
392       qsort (base+p*size, count-p, size, compare);
393     }
394 }
395
396 int
397 remove (char const *file_name)
398 {
399   struct stat buf;
400   if (stat (file_name, &buf) < 0)
401     return -1;
402   if (S_ISDIR (buf.st_mode))
403     return rmdir (file_name);
404   return unlink (file_name);
405 }
406
407 int
408 sigaction (int signum, struct sigaction const *act, struct sigaction *oldact)
409 {
410   return 0;
411 }
412
413 int
414 sigemptyset (sigset_t *set)
415 {
416   return 0;
417 }
418
419 int
420 snprintf(char *str,  size_t size,  char const *format, ...)
421 {
422   va_list ap;
423   va_start (ap, format);
424   int r = vsprintf (str, format, ap);
425   va_end (ap);
426   return r;
427 }
428
429 int
430 sscanf (char const *str, const char *template, ...)
431 {
432   va_list ap;
433   va_start (ap, template);
434   int r = vsscanf (str, template, ap);
435   va_end (ap);
436   return r;
437 }
438
439 char *
440 strcat (char *to, char const *from)
441 {
442   char *p = strchr (to, '\0');
443   while (*from)
444     *p++ = *from++;
445   *p = 0;
446   return to;
447 }
448
449 char *
450 strchr (char const *s, int c)
451 {
452   char const *p = s;
453   while (*p || !c)
454     {
455       if (c == *p)
456         return p;
457       *p++;
458     }
459   return 0;
460 }
461
462 char *
463 strncpy (char *to, char const *from, size_t size)
464 {
465   if (size == 0)
466     return to;
467   char *p = to;
468   while (*from && size--)
469     *p++ = *from++;
470   if (*from)
471     size++;
472   while (size--)
473     *p++ = 0;
474   return to;
475 }
476
477 char *
478 strrchr (char const *s, int c)
479 {
480   int n = strlen (s);
481   if (!n) return 0;
482   char const *p = s + n - 1;
483   while (*p || !c)
484     {
485       if (c == *p) return p;
486       *p--;
487     }
488   return 0;
489 }
490
491 /** locate a substring. #memmem# finds the first occurrence of
492     #needle# in #haystack#.  This is not ANSI-C.
493
494     The prototype is not in accordance with the Linux Programmer's
495     Manual v1.15, but it is with /usr/include/string.h   */
496
497 unsigned char *
498 _memmem (unsigned char const *haystack, int haystack_len,
499          unsigned char const *needle, int needle_len)
500 {
501   unsigned char const *end_haystack = haystack + haystack_len - needle_len + 1;
502   unsigned char const *end_needle = needle + needle_len;
503
504   /* Ahhh ... Some minimal lowlevel stuff. This *is* nice; Varation
505      is the spice of life */
506   while (haystack < end_haystack)
507     {
508       unsigned char const *subneedle = needle;
509       unsigned char const *subhaystack = haystack;
510       while (subneedle < end_needle)
511         if (*subneedle++ != *subhaystack++)
512           goto next;
513
514       /* Completed the needle.  Gotcha.  */
515       return (unsigned char *) haystack;
516     next:
517       haystack++;
518     }
519   return 0;
520 }
521
522 void *
523 memmem (void const *haystack, int haystack_len,
524         void const *needle, int needle_len)
525 {
526   unsigned char const *haystack_byte_c = (unsigned char const *)haystack;
527   unsigned char const *needle_byte_c = (unsigned char const *)needle;
528   return _memmem (haystack_byte_c, haystack_len, needle_byte_c, needle_len);
529 }
530
531 char *
532 strstr (char const *haystack, char const *needle)
533 {
534   return memmem (haystack, strlen (haystack), needle, strlen (needle));
535 }
536
537 double
538 strtod (char const *string, char **tailptr)
539 {
540   static int stub = 0;
541   if (__mes_debug () && !stub)
542     eputs ("strtod stub\n");
543   stub = 1;
544   return 0;
545 }
546
547 float
548 strtof (char const *string, char **tailptr)
549 {
550   return strtod (string, tailptr);
551 }
552
553 long double
554 strtold (char const *string, char **tailptr)
555 {
556   return strtod (string, tailptr);
557 }
558
559 long
560 strtol (char const *string, char **tailptr, int base)
561 {
562   if (!strncmp (string, "0x", 2))
563     {
564       string += 2;
565       base = 16;
566     }
567   if (tailptr)
568     {
569       *tailptr = string;
570       return abtoi (tailptr, base);
571     }
572   char **p = &string;
573   return abtoi (p, base);
574 }
575
576 long long int
577 strtoll (char const *string, char **tailptr, int base)
578 {
579   return strtol (string, tailptr, base);
580 }
581
582 unsigned long
583 strtoul (char const *string, char **tailptr, int base)
584 {
585   return strtol (string, tailptr, base);
586 }
587
588 unsigned long long
589 strtoull (char const *string, char **tailptr, int base)
590 {
591   return strtol (string, tailptr, base);
592 }
593
594 time_t
595 time (time_t *tloc)
596 {
597   static int stub = 0;
598   if (__mes_debug () && !stub)
599     eputs ("time stub\n");
600   stub = 1;
601   errno = 0;
602   return 0;
603 }
604
605 int
606 vsnprintf (char *str, size_t size, char const *format, va_list ap)
607 {
608   return vsprintf (str, format, ap);
609 }
610
611 void *
612 calloc (size_t nmemb, size_t size)
613 {
614   size_t count = nmemb * size;
615   void *p = malloc (count);
616   memset (p, 0, count);
617   return p;
618 }
619
620 int
621 islower (int c)
622 {
623   return c >= 'a' && c <= 'z';
624 }
625
626 int
627 isupper (int c)
628 {
629   return c >= 'A' && c <= 'Z';
630 }
631
632 int
633 tolower (int c)
634 {
635   if (isupper (c))
636     return c + ('a' - 'A');
637   return c;
638 }
639
640 int
641 toupper (int c)
642 {
643   if (islower (c))
644     return c - ('a' - 'A');
645   return c;
646 }
647
648 char *
649 strlwr (char *string)
650 {
651   char *p = string;
652   while (*p)
653     {
654       *p = tolower (*p);
655       p++;
656     }
657   return string;
658 }
659
660 char *
661 strupr (char *string)
662 {
663   char *p = string;
664   while (*p)
665     {
666       *p = toupper (*p);
667       p++;
668     }
669   return string;
670 }
671
672 int
673 vfprintf (FILE* f, char const* format, va_list ap)
674 {
675   int fd = (int)f;
676   char const *p = format;
677   int count = 0;
678   while (*p)
679     if (*p != '%')
680       {
681         count++;
682         fputc (*p++, fd);
683       }
684     else
685       {
686         p++;
687         char c = *p;
688         int left_p = 0;
689         int precision_p = 0;
690         int width = -1;
691         if (c == 'l')
692           c = *++p;
693         if (c == '-')
694           {
695             left_p = 1;
696             c = *++p;
697           }
698         if (c == '.')
699           {
700             precision_p = 1;
701             c = *++p;
702           }
703         char pad = ' ';
704         if (c == '0')
705           {
706             pad = c;
707             c = *p++;
708           }
709         if (c >= '0' && c <= '9')
710           {
711             width = abtoi (&p, 10);
712             c = *p;
713           }
714         else if (c == '*')
715           {
716             width = va_arg (ap, int);
717             c = *++p;
718           }
719         if (c == 'l')
720           c = *++p;
721         switch (c)
722           {
723           case '%': {fputc (*p, fd); count++; break;}
724           case 'c': {char c; c = va_arg (ap, int); fputc (c, fd); break;}
725           case 'd':
726           case 'i':
727           case 'o':
728           case 'u':
729           case 'x':
730           case 'X':
731             {
732               int d = va_arg (ap, int);
733               int base = c == 'o' ? 8
734                 : c == 'x' || c == 'X' ? 16
735                 : 10;
736               char const *s = number_to_ascii (d, base, c != 'u' && c != 'x' && c != 'X');
737               if (c == 'X')
738                 strupr (s);
739               if (!precision_p && width >= 0)
740                 width = width - strlen (s);
741               if (!left_p && !precision_p)
742                 while (!precision_p && width-- > 0)
743                   {
744                     fputc (pad, f);
745                     count++;
746                   }
747               while (*s)
748                 {
749                   if (precision_p && width-- == 0)
750                     break;
751                   fputc (*s++, f);
752                   count++;
753                 }
754               while (!precision_p && width-- > 0)
755                 {
756                   fputc (pad, f);
757                   count++;
758                 }
759               break;
760             }
761           case 's':
762             {
763               char *s = va_arg (ap, char *);
764               if (!precision_p && width >= 0)
765                 width = width - strlen (s);
766               if (!left_p && !precision_p)
767                 while (!precision_p && width-- > 0)
768                   {
769                     fputc (pad, f);
770                     count++;
771                   }
772               while (*s)
773                 {
774                   if (precision_p && width-- == 0)
775                     break;
776                   fputc (*s++, f);
777                   count++;
778                 }
779               while (!precision_p && width-- > 0)
780                 {
781                   fputc (pad, f);
782                   count++;
783                 }
784               break;
785             }
786           case 'n':
787             {
788               int *n = va_arg (ap, int *);
789               *n = count;
790               break;
791             }
792           default:
793             {
794               eputs ("vfprintf: not supported: %");
795               eputc (c);
796               eputs ("\n");
797               p++;
798             }
799           }
800         p++;
801       }
802   va_end (ap);
803   return 0;
804 }
805
806 int
807 vprintf (char const* format, va_list ap)
808 {
809   return vfprintf (STDOUT, format, ap);
810 }
811
812 int
813 vsscanf (char const *s, char const *template, va_list ap)
814 {
815   char const *p = s;
816   char const *t = template;
817   int count = 0;
818   while (*t && *p)
819     if (*t != '%')
820       {
821         t++;
822         p++;
823       }
824     else
825       {
826         t++;
827         char c = *t;
828         if (c == 'l')
829           c = *++t;
830         switch (c)
831           {
832           case '%': {p++; break;}
833           case 'c':
834             {
835               char *c = va_arg (ap, char*);
836               *c = *p++;
837               count++;
838               break;
839             }
840           case 'd':
841           case 'i':
842           case 'u':
843             {
844               int *d = va_arg (ap, int*);
845               *d = abtoi (&p, 10);
846               count++;
847               break;
848             }
849           default:
850             {
851               eputs ("vsscanf: not supported: %");
852               eputc (c);
853               eputs ("\n");
854               t++;
855               p++;
856             }
857           }
858         t++;
859       }
860   va_end (ap);
861   return count;
862 }
863
864 int
865 vsprintf (char *str, char const* format, va_list ap)
866 {
867   char const *p = format;
868   int count = 0;
869   while (*p)
870     if (*p != '%')
871       {
872         *str++ = *p++;
873         count++;
874       }
875     else
876       {
877         p++;
878         char c = *p;
879         int left_p = 0;
880         int precision_p = 0;
881         int width = -1;
882         if (c == 'l')
883           c = *++p;
884         if (c == '-')
885           {
886             left_p = 1;
887             c = *++p;
888           }
889         if (c == '.')
890           {
891             precision_p = 1;
892             c = *++p;
893           }
894         char pad = ' ';
895         if (c == '0')
896           {
897             pad = c;
898             c = *p++;
899           }
900         if (c >= '0' && c <= '9')
901           {
902             width = abtoi (&p, 10);
903             c = *p;
904           }
905         else if (c == '*')
906           {
907             width = va_arg (ap, int);
908             c = *++p;
909           }
910         if (c == 'l')
911           c = *++p;
912         switch (c)
913           {
914           case '%': {*str++ = *p; count++; break;}
915           case 'c': {c = va_arg (ap, int); *str++ = c; count++; break;}
916           case 'd':
917           case 'i':
918           case 'o':
919           case 'u':
920           case 'x':
921           case 'X':
922             {
923               int d = va_arg (ap, int);
924               int base = c == 'o' ? 8
925                 : c == 'x' || c == 'X' ? 16
926                 : 10;
927               char const *s = number_to_ascii (d, base, c != 'u' && c != 'x' && c != 'X');
928               if (c == 'X')
929                 strupr (s);
930               if (!precision_p && width >= 0)
931                 width = width - strlen (s);
932               if (!left_p && !precision_p)
933                 while (!precision_p && width-- > 0)
934                   {
935                     *str++ = pad;
936                     count++;
937                   }
938               while (*s)
939                 {
940                   if (precision_p && width-- == 0)
941                     break;
942                   *str++ = *s++;
943                   count++;
944                 }
945               while (!precision_p && width-- > 0)
946                 {
947                   *str++ = pad;
948                   count++;
949                 }
950               break;
951             }
952           case 's':
953             {
954               char *s = va_arg (ap, char *);
955               if (!precision_p && width >= 0)
956                 width = width - strlen (s);
957               if (!left_p && !precision_p)
958                 while (!precision_p && width-- > 0)
959                   {
960                     *str++ = pad;
961                     count++;
962                   }
963               while (*s)
964                 {
965                   if (precision_p && width-- == 0)
966                     break;
967                   *str++ = *s++;
968                   count++;
969                 }
970               while (!precision_p && width-- > 0)
971                 {
972                   *str++ = pad;
973                   count++;
974                 }
975               break;
976             }
977           case 'n':
978             {
979               int *n = va_arg (ap, int *);
980               *n = count;
981               break;
982             }
983           default:
984             {
985               eputs ("vsprintf: not supported: %");
986               eputc (c);
987               eputs ("\n");
988               p++;
989             }
990           }
991         p++;
992       }
993   va_end (ap);
994   *str = 0;
995   return strlen (str);
996 }
997
998 int
999 sprintf (char *str, char const* format, ...)
1000 {
1001   va_list ap;
1002   va_start (ap, format);
1003   int r = vsprintf (str, format, ap);
1004   va_end (ap);
1005   return r;
1006 }
1007
1008 int
1009 printf (char const* format, ...)
1010 {
1011   va_list ap;
1012   va_start (ap, format);
1013   int r = vprintf (format, ap);
1014   va_end (ap);
1015   return r;
1016 }