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