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