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