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