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