From a9215931e8d40610cf31b9b90a40ce0e08b62c3b Mon Sep 17 00:00:00 2001 From: Jan Nieuwenhuizen Date: Sat, 16 Jun 2018 20:51:16 +0200 Subject: [PATCH] mescc: Support binutils 2.15a: fread: read ungetc'd chars too. * lib/libmes.c (_ungetc_fd): New variable. (fdgetc): Use it. (_fdungetc_p): New function. * lib/libc+tcc.c (_fungetc_p): New function. * lib/libc+tcc.c (fread): Use it to read ungetc'd chars too. --- lib/libc+tcc.c | 36 +++++++++++++++++++++++++++++++++++- lib/libmes.c | 29 +++++++++++++++++++++++++++++ lib/linux+tcc.c | 5 +++++ lib/linux.c | 8 ++++++++ 4 files changed, 77 insertions(+), 1 deletion(-) diff --git a/lib/libc+tcc.c b/lib/libc+tcc.c index e2a5a1a4..b3e2bb3a 100644 --- a/lib/libc+tcc.c +++ b/lib/libc+tcc.c @@ -155,12 +155,46 @@ fprintf (FILE *stream, char const *format, ...) return r; } +int +_fungetc_p (FILE *stream) +{ + return _fdungetc_p ((int)stream); +} + size_t fread (void *data, size_t size, size_t count, FILE *stream) { if (! size || !count) return 0; - int bytes = read ((int)stream, data, size * count); + + size_t todo = size * count; + char *buf = (char*)data; + + int bytes = 0; + while (_fungetc_p (stream) && todo-- && ++bytes) + *buf++ = fgetc (stream); + if (todo) + { + int r = read ((int)stream, buf, todo); + if (r < 0 && !bytes) + bytes = r; + else + bytes += r; + } + + if (__mes_debug ()) + { + eputs ("fread fd="); eputs (itoa ((int)stream)); + eputs (" bytes="); eputs (itoa (bytes)); eputs ("\n"); + static char buf[4096]; + if (bytes > 0 && bytes < sizeof (buf)) + { + strncpy (buf, data, bytes); + buf[bytes] = 0; + eputs ("fread buf="); eputs (buf); eputs ("\n"); + } + } + if (bytes > 0) return bytes/size; diff --git a/lib/libmes.c b/lib/libmes.c index f6a04d78..0c45310b 100644 --- a/lib/libmes.c +++ b/lib/libmes.c @@ -130,6 +130,7 @@ utoa (unsigned x) } int _ungetc_pos = -1; +int _ungetc_fd = -1; char _ungetc_buf[10]; int @@ -146,8 +147,19 @@ fdgetc (int fd) } else { + if (_ungetc_fd != fd) + { + eputs (" ***MES LIB C*** fdgetc ungetc conflict unget-fd="); + eputs (itoa (_ungetc_fd)); + eputs (", fdgetc-fd="); + eputs (itoa (fd)); + eputs ("\n"); + exit (1); + } i = _ungetc_buf[_ungetc_pos]; _ungetc_pos -= 1; + if (_ungetc_pos == -1) + _ungetc_fd = -1; } if (i < 0) i += 256; @@ -173,11 +185,28 @@ fdputs (char const* s, int fd) int fdungetc (int c, int fd) { + if (_ungetc_pos == -1) + _ungetc_fd = fd; + else if (_ungetc_fd != fd) + { + eputs (" ***MES LIB C*** fdungetc ungetc conflict unget-fd="); + eputs (itoa (_ungetc_fd)); + eputs (", fdungetc-fd="); + eputs (itoa (fd)); + eputs ("\n"); + exit (1); + } _ungetc_pos++; _ungetc_buf[_ungetc_pos] = c; return c; } +int +_fdungetc_p (int fd) +{ + return _ungetc_pos > -1; +} + #if POSIX || __x86_64__ #define STDERR 2 int diff --git a/lib/linux+tcc.c b/lib/linux+tcc.c index cf69a264..092d65dd 100644 --- a/lib/linux+tcc.c +++ b/lib/linux+tcc.c @@ -28,6 +28,11 @@ int close (int filedes) { + if (_ungetc_fd == filedes) + { + _ungetc_pos = -1; + _ungetc_fd = -1; + } return _sys_call1 (SYS_close, (int)filedes); } diff --git a/lib/linux.c b/lib/linux.c index f9dbcd9e..454aa7b2 100644 --- a/lib/linux.c +++ b/lib/linux.c @@ -18,6 +18,7 @@ * along with Mes. If not, see . */ +#include #include #include #include @@ -55,6 +56,13 @@ open (char const *file_name, int flags, ...) va_list ap; va_start (ap, flags); int mask = va_arg (ap, int); +#if !MES_BOOTSTRAP + if (!flags) + { + _ungetc_pos = -1; + _ungetc_fd = -1; + } +#endif int r = _sys_call3 (SYS_open, (int)file_name, (int)flags, (int)mask); va_end (ap); return r;