mescc: Support binutils-2.10.1: Stubs set errno to 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 (getenv ("MESC_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 (getenv ("MESC_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 (getenv ("MESC_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 (getenv ("MESC_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 size_t
159 fread (void *data, size_t size, size_t count, FILE *stream)
160 {
161   if (! size || !count)
162     return 0;
163   int bytes = read ((int)stream, data, size * count);
164   if (bytes > 0)
165     return bytes/size;
166
167   return 0;
168 }
169
170 size_t
171 fwrite (void const *data, size_t size, size_t count, FILE *stream)
172 {
173   if (getenv ("MESC_DEBUG"))
174     {
175       eputs ("fwrite "); eputs (itoa ((int)stream));
176       eputs ("  "); eputs (itoa (size)); eputs ("\n");
177     }
178
179   if (! size || !count)
180     return 0;
181   int bytes = write ((int)stream, data, size * count);
182
183   if (getenv ("MESC_DEBUG"))
184     {
185       eputs (" => "); eputs (itoa (bytes)); eputs ("\n");
186     }
187
188   if (bytes > 0)
189     return bytes/size;
190   return 0;
191 }
192
193 long
194 ftell (FILE *stream)
195 {
196   return lseek ((int)stream, 0, SEEK_CUR);
197 }
198
199 FILE*
200 fopen (char const *file_name, char const *opentype)
201 {
202   if (getenv ("MESC_DEBUG"))
203     {
204       eputs ("fopen "); eputs (file_name);
205       eputs (" "); eputs (opentype); eputs ("\n");
206     }
207
208   int fd;
209   int mode = 0600;
210   if ((opentype[0] == 'a' || !strcmp (opentype, "r+"))
211       && !access (file_name, O_RDONLY))
212     {
213       fd = open (file_name, O_RDWR, mode);
214       if (opentype[0] == 'a')
215         lseek (fd, 0, SEEK_END);
216     }
217   else if (opentype[0] == 'w' || opentype[0] == 'a' || !strcmp (opentype, "r+"))
218     {
219       char *plus_p = strchr (opentype, '+');
220       int flags = plus_p ? O_RDWR | O_CREAT : O_WRONLY | O_CREAT | O_TRUNC;
221       fd = open (file_name, flags, mode);
222     }
223   else
224     fd = open (file_name, 0, 0);
225
226   if (getenv ("MESC_DEBUG"))
227     {
228       eputs (" => fd="); eputs (itoa (fd)); eputs ("\n");
229     }
230
231   return (FILE*)fd;
232 }
233
234 int
235 fseek (FILE *stream, long offset, int whence)
236 {
237   int pos = lseek ((int)stream, offset, whence);
238   if (pos >= 0)
239     return 0;
240   return -1;
241 }
242
243 int
244 gettimeofday (struct timeval *tv, struct timezone *tz)
245 {
246 #if NOISY_TIMES
247   eputs ("gettimeofday stub\n");
248 #endif
249   errno = 0;
250   return 0;
251 }
252
253 double
254 ldexp (double x, int exp)
255 {
256   eputs ("ldexp stub\n");
257   return 0;
258 }
259
260 struct tm *
261 localtime (time_t const *timep)
262 {
263 #if NOISY_TIMES
264   eputs ("localtime stub\n");
265 #endif
266   errno = 0;
267   return 0;
268 }
269
270 void *
271 memmove (void *dest, void const *src, size_t n)
272 {
273   if (dest < src)
274     return memcpy (dest, src, n);
275   char *p = dest + n;
276   char const *q = src +n;
277   while (n--)
278     *--p = *--q;
279   return dest;
280 }
281
282 void *
283 memset (void *s, int c, size_t n)
284 {
285   char *p = s;
286   while (n--) *p++ = c;
287   return s;
288 }
289
290 int
291 memcmp (void const *s1, void const *s2, size_t n)
292 {
293   char *a = s1;
294   char *b = s2;
295   while (*a == *b && --n) {a++;b++;}
296   return *a - *b;
297 }
298
299 int
300 mprotect (void *addr, size_t len, int prot)
301 {
302   return 0;
303 }
304
305 void
306 qswap (void *a, void *b, size_t size)
307 {
308   char *buf[8];
309   memcpy (buf, a, size);
310   memcpy (a, b, size);
311   memcpy (b, buf, size);
312 }
313
314 size_t
315 qpart (void *base, size_t count, size_t size, int (*compare)(void const *, void const *))
316 {
317   void* p = base + count*size;
318   size_t i = 0;
319   for (size_t j = 0; j < count; j++)
320     {
321       if (compare (base+j*size, p) < 0)
322         {
323           qswap (base+i*size, base+j*size, size);
324           i++;
325         }
326     }
327   if (compare (base+count*size, base+i*size) < 0)
328     qswap (base+i*size, base+count*size, size);
329   return i;
330 }
331
332 void
333 qsort (void *base, size_t count, size_t size, int (*compare)(void const *, void const *))
334 {
335   if (count > 1)
336     {
337       int p = qpart (base, count-1, size, compare);
338       qsort (base, p, size, compare);
339       qsort (base+p*size, count-p, size, compare);
340     }
341 }
342
343 int
344 remove (char const *file_name)
345 {
346   struct stat buf;
347   if (stat (file_name, &buf) < 0)
348     return -1;
349   if (S_ISDIR (buf.st_mode))
350     return rmdir (file_name);
351   return unlink (file_name);
352 }
353
354 int
355 sigaction (int signum, struct sigaction const *act, struct sigaction *oldact)
356 {
357   return 0;
358 }
359
360 int
361 sigemptyset (sigset_t *set)
362 {
363   return 0;
364 }
365
366 int
367 snprintf(char *str,  size_t size,  char const *format, ...)
368 {
369   va_list ap;
370   va_start (ap, format);
371   int r = vsprintf (str, format, ap);
372   va_end (ap);
373   return r;
374 }
375
376 int
377 sscanf (char const *str, const char *template, ...)
378 {
379   va_list ap;
380   va_start (ap, template);
381   int r = vsscanf (str, template, ap);
382   va_end (ap);
383   return r;
384 }
385
386 char *
387 strcat (char *to, char const *from)
388 {
389   char *p = strchr (to, '\0');
390   while (*from)
391     *p++ = *from++;
392   *p = 0;
393   return to;
394 }
395
396 char *
397 strchr (char const *s, int c)
398 {
399   char const *p = s;
400   while (*p || !c)
401     {
402       if (c == *p)
403         return p;
404       *p++;
405     }
406   return 0;
407 }
408
409 char *
410 strncpy (char *to, char const *from, size_t size)
411 {
412   if (size == 0)
413     return to;
414   char *p = to;
415   while (*from && size--)
416     *p++ = *from++;
417   if (*from)
418     size++;
419   while (size--)
420     *p++ = 0;
421   return to;
422 }
423
424 char *
425 strrchr (char const *s, int c)
426 {
427   int n = strlen (s);
428   if (!n) return 0;
429   char const *p = s + n - 1;
430   while (*p || !c)
431     {
432       if (c == *p) return p;
433       *p--;
434     }
435   return 0;
436 }
437
438 /** locate a substring. #memmem# finds the first occurrence of
439     #needle# in #haystack#.  This is not ANSI-C.
440
441     The prototype is not in accordance with the Linux Programmer's
442     Manual v1.15, but it is with /usr/include/string.h   */
443
444 unsigned char *
445 _memmem (unsigned char const *haystack, int haystack_len,
446          unsigned char const *needle, int needle_len)
447 {
448   unsigned char const *end_haystack = haystack + haystack_len - needle_len + 1;
449   unsigned char const *end_needle = needle + needle_len;
450
451   /* Ahhh ... Some minimal lowlevel stuff. This *is* nice; Varation
452      is the spice of life */
453   while (haystack < end_haystack)
454     {
455       unsigned char const *subneedle = needle;
456       unsigned char const *subhaystack = haystack;
457       while (subneedle < end_needle)
458         if (*subneedle++ != *subhaystack++)
459           goto next;
460
461       /* Completed the needle.  Gotcha.  */
462       return (unsigned char *) haystack;
463     next:
464       haystack++;
465     }
466   return 0;
467 }
468
469 void *
470 memmem (void const *haystack, int haystack_len,
471         void const *needle, int needle_len)
472 {
473   unsigned char const *haystack_byte_c = (unsigned char const *)haystack;
474   unsigned char const *needle_byte_c = (unsigned char const *)needle;
475   return _memmem (haystack_byte_c, haystack_len, needle_byte_c, needle_len);
476 }
477
478 char *
479 strstr (char const *haystack, char const *needle)
480 {
481   return memmem (haystack, strlen (haystack), needle, strlen (needle));
482 }
483
484 double
485 strtod (char const *string, char **tailptr)
486 {
487 #if NOISY_FLOATS
488   eputs ("strtod stub\n");
489 #endif
490   return 0;
491 }
492
493 float
494 strtof (char const *string, char **tailptr)
495 {
496   return strtod (string, tailptr);
497 }
498
499 long double
500 strtold (char const *string, char **tailptr)
501 {
502   return strtod (string, tailptr);
503 }
504
505 long
506 strtol (char const *string, char **tailptr, int base)
507 {
508   if (!strncmp (string, "0x", 2))
509     {
510       string += 2;
511       base = 16;
512     }
513   if (tailptr)
514     {
515       *tailptr = string;
516       return abtoi (tailptr, base);
517     }
518   char **p = &string;
519   return abtoi (p, base);
520 }
521
522 #if 1
523
524 long long int
525 strtoll (char const *string, char **tailptr, int base)
526 {
527   return strtol (string, tailptr, base);
528 }
529
530 unsigned long
531 strtoul (char const *string, char **tailptr, int base)
532 {
533   return strtol (string, tailptr, base);
534 }
535
536 unsigned long long
537 strtoull (char const *string, char **tailptr, int base)
538 {
539   return strtol (string, tailptr, base);
540 }
541
542 #else
543
544 long long int
545 strtoll (char const *string, char **tailptr, int base)
546 {
547   eputs ("strtoll stub\n");
548   return 0;
549 }
550
551 unsigned long
552 strtoul (char const *string, char **tailptr, int base)
553 {
554   eputs ("strtoul stub\n");
555   return 0;
556 }
557
558 unsigned long long
559 strtoull (char const *string, char **tailptr, int base)
560 {
561   // *endptr = p;
562   // return abtoi (endptr, base);
563   eputs ("strtoull stub\n");
564   return 0;
565 }
566
567 #endif
568
569 time_t
570 time (time_t *tloc)
571 {
572 #if NOISY_TIMES
573   eputs ("time stub\n");
574 #endif
575   errno = 0;
576   return 0;
577 }
578
579 int
580 vsnprintf (char *str, size_t size, char const *format, va_list ap)
581 {
582   return vsprintf (str, format, ap);
583 }
584
585 void *
586 calloc (size_t nmemb, size_t size)
587 {
588   size_t count = nmemb * size;
589   void *p = malloc (count);
590   memset (p, 0, count);
591   return p;
592 }
593
594 int
595 islower (int c)
596 {
597   return c >= 'a' && c <= 'z';
598 }
599
600 int
601 isupper (int c)
602 {
603   return c >= 'A' && c <= 'Z';
604 }
605
606 int
607 tolower (int c)
608 {
609   if (isupper (c))
610     return c + ('a' - 'A');
611   return c;
612 }
613
614 int
615 toupper (int c)
616 {
617   if (islower (c))
618     return c - ('a' - 'A');
619   return c;
620 }
621
622 char *
623 strlwr (char *string)
624 {
625   char *p = string;
626   while (*p)
627     {
628       *p = tolower (*p);
629       p++;
630     }
631   return string;
632 }
633
634 char *
635 strupr (char *string)
636 {
637   char *p = string;
638   while (*p)
639     {
640       *p = toupper (*p);
641       p++;
642     }
643   return string;
644 }
645
646 int
647 vfprintf (FILE* f, char const* format, va_list ap)
648 {
649   int fd = (int)f;
650   char const *p = format;
651   int count = 0;
652   while (*p)
653     if (*p != '%')
654       {
655         count++;
656         fputc (*p++, fd);
657       }
658     else
659       {
660         p++;
661         char c = *p;
662         int left_p = 0;
663         int precision_p = 0;
664         int width = -1;
665         if (c == 'l')
666           c = *++p;
667         if (c == '-')
668           {
669             left_p = 1;
670             c = *++p;
671           }
672         if (c == '.')
673           {
674             precision_p = 1;
675             c = *++p;
676           }
677         char pad = ' ';
678         if (c == '0')
679           {
680             pad = c;
681             c = *p++;
682           }
683         if (c >= '0' && c <= '9')
684           {
685             width = abtoi (&p, 10);
686             c = *p;
687           }
688         else if (c == '*')
689           {
690             width = va_arg (ap, int);
691             c = *++p;
692           }
693         if (c == 'l')
694           c = *++p;
695         switch (c)
696           {
697           case '%': {fputc (*p, fd); count++; break;}
698           case 'c': {char c; c = va_arg (ap, int); fputc (c, fd); break;}
699           case 'd':
700           case 'i':
701           case 'o':
702           case 'u':
703           case 'x':
704           case 'X':
705             {
706               int d = va_arg (ap, int);
707               int base = c == 'o' ? 8
708                 : c == 'x' || c == 'X' ? 16
709                 : 10;
710               char const *s = number_to_ascii (d, base, c != 'u' && c != 'x' && c != 'X');
711               if (c == 'X')
712                 strupr (s);
713               if (!precision_p && width >= 0)
714                 width = width - strlen (s);
715               if (!left_p && !precision_p)
716                 while (!precision_p && width-- > 0)
717                   {
718                     fputc (pad, f);
719                     count++;
720                   }
721               while (*s)
722                 {
723                   if (precision_p && width-- == 0)
724                     break;
725                   fputc (*s++, f);
726                   count++;
727                 }
728               while (!precision_p && width-- > 0)
729                 {
730                   fputc (pad, f);
731                   count++;
732                 }
733               break;
734             }
735           case 's':
736             {
737               char *s = va_arg (ap, char *);
738               if (!precision_p && width >= 0)
739                 width = width - strlen (s);
740               if (!left_p && !precision_p)
741                 while (!precision_p && width-- > 0)
742                   {
743                     fputc (pad, f);
744                     count++;
745                   }
746               while (*s)
747                 {
748                   if (precision_p && width-- == 0)
749                     break;
750                   fputc (*s++, f);
751                   count++;
752                 }
753               while (!precision_p && width-- > 0)
754                 {
755                   fputc (pad, f);
756                   count++;
757                 }
758               break;
759             }
760           case 'n':
761             {
762               int *n = va_arg (ap, int *);
763               *n = count;
764               break;
765             }
766           default:
767             {
768               eputs ("vfprintf: not supported: %");
769               eputc (c);
770               eputs ("\n");
771               p++;
772             }
773           }
774         p++;
775       }
776   va_end (ap);
777   return 0;
778 }
779
780 int
781 vprintf (char const* format, va_list ap)
782 {
783   return vfprintf (STDOUT, format, ap);
784 }
785
786 int
787 vsscanf (char const *s, char const *template, va_list ap)
788 {
789   char const *p = s;
790   char const *t = template;
791   int count = 0;
792   while (*t && *p)
793     if (*t != '%')
794       {
795         t++;
796         p++;
797       }
798     else
799       {
800         t++;
801         char c = *t;
802         switch (c)
803           {
804           case '%': {p++; break;}
805           case 'c':
806             {
807               char *c = va_arg (ap, char*);
808               *c = *p++;
809               count++;
810               break;
811             }
812           case 'd':
813           case 'i':
814           case 'u':
815             {
816               int *d = va_arg (ap, int*);
817               *d = abtoi (&p, 10);
818               count++;
819               break;
820             }
821           default:
822             {
823               eputs ("vsscanf: not supported: %");
824               eputc (c);
825               eputs ("\n");
826               t++;
827               p++;
828             }
829           }
830         t++;
831       }
832   va_end (ap);
833   return count;
834 }
835
836 int
837 vsprintf (char *str, char const* format, va_list ap)
838 {
839   char const *p = format;
840   int count = 0;
841   while (*p)
842     if (*p != '%')
843       {
844         *str++ = *p++;
845         count++;
846       }
847     else
848       {
849         p++;
850         char c = *p;
851         int left_p = 0;
852         int precision_p = 0;
853         int width = -1;
854         if (c == 'l')
855           c = *++p;
856         if (c == '-')
857           {
858             left_p = 1;
859             c = *++p;
860           }
861         if (c == '.')
862           {
863             precision_p = 1;
864             c = *++p;
865           }
866         char pad = ' ';
867         if (c == '0')
868           {
869             pad = c;
870             c = *p++;
871           }
872         if (c >= '0' && c <= '9')
873           {
874             width = abtoi (&p, 10);
875             c = *p;
876           }
877         else if (c == '*')
878           {
879             width = va_arg (ap, int);
880             c = *++p;
881           }
882         if (c == 'l')
883           c = *++p;
884         switch (c)
885           {
886           case '%': {*str++ = *p; count++; break;}
887           case 'c': {c = va_arg (ap, int); *str++ = c; count++; break;}
888           case 'd':
889           case 'i':
890           case 'o':
891           case 'u':
892           case 'x':
893           case 'X':
894             {
895               int d = va_arg (ap, int);
896               int base = c == 'o' ? 8
897                 : c == 'x' || c == 'X' ? 16
898                 : 10;
899               char const *s = number_to_ascii (d, base, c != 'u' && c != 'x' && c != 'X');
900               if (c == 'X')
901                 strupr (s);
902               if (!precision_p && width >= 0)
903                 width = width - strlen (s);
904               if (!left_p && !precision_p)
905                 while (!precision_p && width-- > 0)
906                   {
907                     *str++ = pad;
908                     count++;
909                   }
910               while (*s)
911                 {
912                   if (precision_p && width-- == 0)
913                     break;
914                   *str++ = *s++;
915                   count++;
916                 }
917               while (!precision_p && width-- > 0)
918                 {
919                   *str++ = pad;
920                   count++;
921                 }
922               break;
923             }
924           case 's':
925             {
926               char *s = va_arg (ap, char *);
927               if (!precision_p && width >= 0)
928                 width = width - strlen (s);
929               if (!left_p && !precision_p)
930                 while (!precision_p && width-- > 0)
931                   {
932                     *str++ = pad;
933                     count++;
934                   }
935               while (*s)
936                 {
937                   if (precision_p && width-- == 0)
938                     break;
939                   *str++ = *s++;
940                   count++;
941                 }
942               while (!precision_p && width-- > 0)
943                 {
944                   *str++ = pad;
945                   count++;
946                 }
947               break;
948             }
949           case 'n':
950             {
951               int *n = va_arg (ap, int *);
952               *n = count;
953               break;
954             }
955           default:
956             {
957               eputs ("vsprintf: not supported: %");
958               eputc (c);
959               eputs ("\n");
960               p++;
961             }
962           }
963         p++;
964       }
965   va_end (ap);
966   *str = 0;
967   return strlen (str);
968 }
969
970 int
971 sprintf (char *str, char const* format, ...)
972 {
973   va_list ap;
974   va_start (ap, format);
975   int r = vsprintf (str, format, ap);
976   va_end (ap);
977   return r;
978 }
979
980 int
981 printf (char const* format, ...)
982 {
983   va_list ap;
984   va_start (ap, format);
985   int r = vprintf (format, ap);
986   va_end (ap);
987   return r;
988 }