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