1 /* -*-comment-start: "//";comment-end:""-*-
2 * GNU 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>
7 * This file is part of GNU Mes.
9 * GNU 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.
14 * GNU 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.
19 * You should have received a copy of the GNU General Public License
20 * along with GNU Mes. If not, see <http://www.gnu.org/licenses/>.
43 #include <linux/tcc.c>
45 #error both __GNU__ and _linux__ are undefined, choose one
50 #include <libc+tcc-mes.c>
54 #include <libc+tcc-gcc.c>
59 search_path (char const *file_name)
62 char *path = getenv ("PATH");
65 eputs ("\n search-path: "); eputs (file_name); eputs ("\n");
69 char *end = strchr (path, ':');
71 end = strchr (path, '\0');
72 strncpy (buf, path, end - path);
76 eputs (" dir: "); eputs (buf); eputs ("\n");
78 if (buf[end - path] != '/')
80 strcat (buf, file_name);
81 if (!access (buf, X_OK))
85 eputs (" found: "); eputs (buf); eputs ("\n");
95 execvp (char const *file_name, char *const argv[])
97 if (file_name[0] != '/')
98 file_name = search_path (file_name);
106 eputs (" EXEC: "); eputs (file_name); eputs ("\n");
110 eputs (" arg["); eputs (itoa (i)); eputs ("]: "); eputs (argv[i]); eputs ("\n");
114 return execve (file_name, argv, environ);
118 fclose (FILE *stream)
120 int fd = (int)stream;
125 fdopen (int fd, char const *mode)
131 ferror (FILE *stream)
133 int fd = (int)stream;
134 if (fd == -1) return -1;
139 fflush (FILE *stream)
145 fprintf (FILE *stream, char const *format, ...)
148 va_start (ap, format);
149 int r = vfprintf (stream, format, ap);
155 _fungetc_p (FILE *stream)
157 return _fdungetc_p ((int)stream);
161 fread (void *data, size_t size, size_t count, FILE *stream)
163 if (! size || !count)
166 size_t todo = size * count;
167 char *buf = (char*)data;
170 while (_fungetc_p (stream) && todo-- && ++bytes)
171 *buf++ = fgetc (stream);
174 int r = read ((int)stream, buf, todo);
183 eputs ("fread fd="); eputs (itoa ((int)stream));
184 eputs (" bytes="); eputs (itoa (bytes)); eputs ("\n");
185 static char buf[4096];
186 if (bytes > 0 && bytes < sizeof (buf))
188 strncpy (buf, data, bytes);
190 eputs ("fread buf="); eputs (buf); eputs ("\n");
201 fwrite (void const *data, size_t size, size_t count, FILE *stream)
203 if (__mes_debug () > 1)
205 eputs ("fwrite "); eputs (itoa ((int)stream));
206 eputs (" "); eputs (itoa (size)); eputs ("\n");
209 if (! size || !count)
211 int bytes = write ((int)stream, data, size * count);
213 if (__mes_debug () > 2)
215 eputs (" => "); eputs (itoa (bytes)); eputs ("\n");
226 return lseek ((int)stream, 0, SEEK_CUR);
230 fopen (char const *file_name, char const *opentype)
234 eputs ("fopen "); eputs (file_name);
235 eputs (" "); eputs (opentype); eputs ("\n");
240 if ((opentype[0] == 'a' || !strcmp (opentype, "r+"))
241 && !access (file_name, O_RDONLY))
244 if (opentype[0] == 'a')
246 fd = open (file_name, flags, mode);
248 else if (opentype[0] == 'w' || opentype[0] == 'a' || !strcmp (opentype, "r+"))
250 char *plus_p = strchr (opentype, '+');
251 int flags = plus_p ? O_RDWR | O_CREAT : O_WRONLY | O_CREAT | O_TRUNC;
252 fd = open (file_name, flags, mode);
255 fd = open (file_name, 0, 0);
259 eputs (" => fd="); eputs (itoa (fd)); eputs ("\n");
264 eputs (" ***MES LIB C*** fopen of stdin: signal me in band\n");
273 fseek (FILE *stream, long offset, int whence)
275 int pos = lseek ((int)stream, offset, whence);
278 eputs ("fread fd="); eputs (itoa ((int)stream));
279 eputs (" =>"); eputs (itoa (pos)); eputs ("\n");
287 gettimeofday (struct timeval *tv, struct timezone *tz)
290 if (__mes_debug () && !stub)
291 eputs ("gettimeofday stub\n");
298 ldexp (double x, int exp)
301 if (__mes_debug () && !stub)
302 eputs ("ldexp stub\n");
308 localtime (time_t const *timep)
311 if (__mes_debug () && !stub)
312 eputs ("localtime stub\n");
319 memmove (void *dest, void const *src, size_t n)
322 return memcpy (dest, src, n);
324 char const *q = src +n;
331 memset (void *s, int c, size_t n)
334 while (n--) *p++ = c;
339 memcmp (void const *s1, void const *s2, size_t size)
345 while (*a == *b && --size)
354 mprotect (void *addr, size_t len, int prot)
360 qswap (void *a, void *b, size_t size)
363 memcpy (buf, a, size);
365 memcpy (b, buf, size);
369 qpart (void *base, size_t count, size_t size, int (*compare)(void const *, void const *))
371 void* p = base + count*size;
373 for (size_t j = 0; j < count; j++)
375 if (compare (base+j*size, p) < 0)
377 qswap (base+i*size, base+j*size, size);
381 if (compare (base+count*size, base+i*size) < 0)
382 qswap (base+i*size, base+count*size, size);
387 qsort (void *base, size_t count, size_t size, int (*compare)(void const *, void const *))
391 int p = qpart (base, count-1, size, compare);
392 qsort (base, p, size, compare);
393 qsort (base+p*size, count-p, size, compare);
398 remove (char const *file_name)
401 if (stat (file_name, &buf) < 0)
403 if (S_ISDIR (buf.st_mode))
404 return rmdir (file_name);
405 return unlink (file_name);
409 sigaction (int signum, struct sigaction const *act, struct sigaction *oldact)
415 sigemptyset (sigset_t *set)
421 snprintf(char *str, size_t size, char const *format, ...)
424 va_start (ap, format);
425 int r = vsprintf (str, format, ap);
431 sscanf (char const *str, const char *template, ...)
434 va_start (ap, template);
435 int r = vsscanf (str, template, ap);
441 strcat (char *to, char const *from)
443 char *p = strchr (to, '\0');
451 strchr (char const *s, int c)
464 strncpy (char *to, char const *from, size_t size)
469 while (*from && size--)
479 strrchr (char const *s, int c)
484 char const *p = s + n;
488 while (n-- && (*p || !c))
497 /** locate a substring. #memmem# finds the first occurrence of
498 #needle# in #haystack#. This is not ANSI-C.
500 The prototype is not in accordance with the Linux Programmer's
501 Manual v1.15, but it is with /usr/include/string.h */
504 _memmem (unsigned char const *haystack, int haystack_len,
505 unsigned char const *needle, int needle_len)
507 unsigned char const *end_haystack = haystack + haystack_len - needle_len + 1;
508 unsigned char const *end_needle = needle + needle_len;
510 /* Ahhh ... Some minimal lowlevel stuff. This *is* nice; Varation
511 is the spice of life */
512 while (haystack < end_haystack)
514 unsigned char const *subneedle = needle;
515 unsigned char const *subhaystack = haystack;
516 while (subneedle < end_needle)
517 if (*subneedle++ != *subhaystack++)
520 /* Completed the needle. Gotcha. */
521 return (unsigned char *) haystack;
529 memmem (void const *haystack, int haystack_len,
530 void const *needle, int needle_len)
532 unsigned char const *haystack_byte_c = (unsigned char const *)haystack;
533 unsigned char const *needle_byte_c = (unsigned char const *)needle;
534 return _memmem (haystack_byte_c, haystack_len, needle_byte_c, needle_len);
538 strstr (char const *haystack, char const *needle)
540 return memmem (haystack, strlen (haystack), needle, strlen (needle));
544 strtod (char const *string, char **tailptr)
547 if (__mes_debug () && !stub)
548 eputs ("strtod stub\n");
554 strtof (char const *string, char **tailptr)
556 return strtod (string, tailptr);
560 strtold (char const *string, char **tailptr)
562 return strtod (string, tailptr);
566 strtol (char const *string, char **tailptr, int base)
568 if (!strncmp (string, "0x", 2))
576 return abtoi (tailptr, base);
579 return abtoi (p, base);
583 strtoll (char const *string, char **tailptr, int base)
585 return strtol (string, tailptr, base);
589 strtoul (char const *string, char **tailptr, int base)
591 return strtol (string, tailptr, base);
595 strtoull (char const *string, char **tailptr, int base)
597 return strtol (string, tailptr, base);
604 if (__mes_debug () && !stub)
605 eputs ("time stub\n");
612 vsnprintf (char *str, size_t size, char const *format, va_list ap)
614 return vsprintf (str, format, ap);
618 calloc (size_t nmemb, size_t size)
620 size_t count = nmemb * size;
621 void *p = malloc (count);
622 memset (p, 0, count);
629 return c >= 'a' && c <= 'z';
635 return c >= 'A' && c <= 'Z';
642 return c + ('a' - 'A');
650 return c - ('a' - 'A');
655 strlwr (char *string)
667 strupr (char *string)
679 vfprintf (FILE* f, char const* format, va_list ap)
682 char const *p = format;
708 if (c >= '0' && c <= '9')
710 width = abtoi (&p, 10);
715 width = va_arg (ap, int);
721 if (c >= '0' && c <= '9')
723 precision = abtoi (&p, 10);
728 precision = va_arg (ap, int);
736 eputs ("vfprintf: skipping second: l\n");
741 case '%': {fputc (*p, fd); count++; break;}
742 case 'c': {char c; c = va_arg (ap, int); fputc (c, fd); break;}
750 int d = va_arg (ap, int);
751 int base = c == 'o' ? 8
752 : c == 'x' || c == 'X' ? 16
754 char const *s = number_to_ascii (d, base, c != 'u' && c != 'x' && c != 'X');
757 int length = strlen (s);
762 while (width-- > precision)
767 while (precision > length)
777 if (precision-- <= 0)
793 char *s = va_arg (ap, char *);
794 int length = strlen (s);
799 while (width-- > precision)
804 while (precision > length)
814 if (precision-- <= 0)
830 int *n = va_arg (ap, int *);
836 eputs ("vfprintf: not supported: %:");
849 vprintf (char const* format, va_list ap)
851 return vfprintf (STDOUT, format, ap);
855 vsscanf (char const *s, char const *template, va_list ap)
858 char const *t = template;
874 case '%': {p++; break;}
877 char *c = va_arg (ap, char*);
886 int *d = va_arg (ap, int*);
893 eputs ("vsscanf: not supported: %:");
907 vsprintf (char *str, char const* format, va_list ap)
909 char const *p = format;
935 if (c >= '0' && c <= '9')
937 width = abtoi (&p, 10);
942 width = va_arg (ap, int);
948 if (c >= '0' && c <= '9')
950 precision = abtoi (&p, 10);
955 precision = va_arg (ap, int);
965 eputs ("vfprintf: skipping second: l\n");
970 case '%': {*str++ = *p; count++; break;}
971 case 'c': {c = va_arg (ap, int); *str++ = c; count++; break;}
979 int d = va_arg (ap, int);
980 int base = c == 'o' ? 8
981 : c == 'x' || c == 'X' ? 16
983 char const *s = number_to_ascii (d, base, c != 'u' && c != 'x' && c != 'X');
986 int length = strlen (s);
991 while (width-- > precision)
996 while (precision > length)
1006 if (precision-- <= 0)
1022 char *s = va_arg (ap, char *);
1023 int length = strlen (s);
1024 if (precision == -1)
1028 while (width-- > precision)
1033 while (width > length)
1043 if (precision-- <= 0)
1059 int *n = va_arg (ap, int *);
1065 eputs ("vsprintf: not supported: %:");
1075 return strlen (str);
1079 sprintf (char *str, char const* format, ...)
1082 va_start (ap, format);
1083 int r = vsprintf (str, format, ap);
1089 printf (char const* format, ...)
1092 va_start (ap, format);
1093 int r = vprintf (format, ap);