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