diff --git a/build-aux/configure-lib.sh b/build-aux/configure-lib.sh
index 86d15b22..159aa11b 100644
--- a/build-aux/configure-lib.sh
+++ b/build-aux/configure-lib.sh
@@ -78,6 +78,7 @@ fi
libc_SOURCES="
$libmes_SOURCES
lib/mes/__assert_fail.c
+lib/mes/__buffered_read.c
lib/mes/__mes_debug.c
lib/posix/execv.c
lib/posix/getcwd.c
@@ -101,6 +102,7 @@ lib/stdlib/realloc.c
lib/string/memchr.c
lib/string/memcmp.c
lib/string/memcpy.c
+lib/string/memmove.c
lib/string/memset.c
lib/string/strcmp.c
lib/string/strcpy.c
@@ -171,7 +173,6 @@ lib/stdlib/strtoll.c
lib/stdlib/strtoul.c
lib/stdlib/strtoull.c
lib/string/memmem.c
-lib/string/memmove.c
lib/string/strcat.c
lib/string/strchr.c
lib/string/strlwr.c
diff --git a/include/mes/lib.h b/include/mes/lib.h
index 63d1eba9..1de015fa 100644
--- a/include/mes/lib.h
+++ b/include/mes/lib.h
@@ -54,11 +54,14 @@ ssize_t _read (int fd, void *buffer, size_t size);
extern char *__brk;
extern void (*__call_at_exit) (void);
+#define __FILEDES_MAX 512
+
#if !SYSTEM_LIBC
void __assert_fail (char *s);
+ssize_t __buffered_read (int filedes, void *buffer, size_t size);
+size_t __buffered_read_clear (int filedes);
void _exit (int code);
long brk (void *addr);
-
#endif // !SYSTEM_LIBC
#endif //__MES_LIB_H
diff --git a/lib/linux/_open3.c b/lib/linux/_open3.c
index e1bf1f7b..8f103e7b 100644
--- a/lib/linux/_open3.c
+++ b/lib/linux/_open3.c
@@ -29,6 +29,9 @@ _open3 (char const *file_name, int flags, int mask)
int r = _sys_call3 (SYS_open, (long) file_name, (int) flags, (int) mask);
__ungetc_init ();
if (r > 2)
- __ungetc_clear (r);
+ {
+ __ungetc_clear (r);
+ __buffered_read_clear (r);
+ }
return r;
}
diff --git a/lib/linux/close.c b/lib/linux/close.c
index 91a049c4..e25e8318 100644
--- a/lib/linux/close.c
+++ b/lib/linux/close.c
@@ -25,7 +25,7 @@
int
close (int filedes)
{
- if (filedes > 2)
- __ungetc_clear (filedes);
+ __ungetc_clear (filedes);
+ __buffered_read_clear (filedes);
return _sys_call1 (SYS_close, (int) filedes);
}
diff --git a/lib/linux/lseek.c b/lib/linux/lseek.c
index 9d21659b..94f2f9f7 100644
--- a/lib/linux/lseek.c
+++ b/lib/linux/lseek.c
@@ -18,12 +18,17 @@
* along with GNU Mes. If not, see .
*/
+#include
#include
#include
+#include
#include
off_t
lseek (int filedes, off_t offset, int whence)
{
+ size_t skip = __buffered_read_clear (filedes);
+ if (whence == SEEK_CUR)
+ offset -= skip;
return _sys_call3 (SYS_lseek, (int) filedes, (long) offset, (int) whence);
}
diff --git a/lib/mes/__buffered_read.c b/lib/mes/__buffered_read.c
new file mode 100644
index 00000000..e47cca53
--- /dev/null
+++ b/lib/mes/__buffered_read.c
@@ -0,0 +1,79 @@
+/* -*-comment-start: "//";comment-end:""-*-
+ * GNU Mes --- Maxwell Equations of Software
+ * Copyright © 2019 Jan (janneke) Nieuwenhuizen
+ *
+ * This file is part of GNU Mes.
+ *
+ * GNU Mes is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * GNU Mes is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Mes. If not, see .
+ */
+
+#include
+#include
+#include
+
+#define __READ_BUFFER_MAX 100
+
+struct __read_buffer
+{
+ ssize_t size;
+ char string[__READ_BUFFER_MAX];
+};
+
+struct __read_buffer *__read_cache = 0;
+
+void
+__buffered_read_init (int filedes)
+{
+ if (!__read_cache)
+ __read_cache = (struct __read_buffer *) malloc (sizeof (struct __read_buffer) * __FILEDES_MAX);
+}
+
+size_t
+__buffered_read_clear (int filedes)
+{
+ __buffered_read_init (filedes);
+ size_t size = __read_cache[filedes].size;
+ __read_cache[filedes].size = 0;
+ return size;
+}
+
+ssize_t
+__buffered_read (int filedes, void *buffer, size_t size)
+{
+ size_t todo = size;
+ __buffered_read_init (filedes);
+ struct __read_buffer *cache = &__read_cache[filedes];
+ char *p = buffer;
+ if (!cache->size && size > __READ_BUFFER_MAX)
+ return _read (filedes, buffer, size);
+ while (cache->size > 0 && todo)
+ {
+ todo--;
+ *p++ = cache->string[__READ_BUFFER_MAX - cache->size--];
+ }
+ if (todo)
+ {
+ ssize_t bytes = _read (filedes, cache->string, __READ_BUFFER_MAX);
+ if (bytes < 0)
+ return -1;
+ if (bytes)
+ {
+ cache->size = bytes;
+ if (bytes < __READ_BUFFER_MAX)
+ memmove (cache->string + __READ_BUFFER_MAX - bytes, cache->string, bytes);
+ return size - todo + __buffered_read (filedes, p, todo);
+ }
+ }
+ return size - todo;
+}
diff --git a/lib/mes/fdgetc.c b/lib/mes/fdgetc.c
index 8dfa256c..74a8eaff 100644
--- a/lib/mes/fdgetc.c
+++ b/lib/mes/fdgetc.c
@@ -24,9 +24,7 @@
#include
#include
-#define __UNGETC_MAX 1024
-
-int __ungetc_buf[__UNGETC_MAX + 1] = { 0 };
+int __ungetc_buf[__FILEDES_MAX + 1] = { 0 };
int
__ungetc_p (int filedes)
@@ -37,8 +35,8 @@ __ungetc_p (int filedes)
void
__ungetc_init ()
{
- if (__ungetc_buf[__UNGETC_MAX] == 0)
- memset (__ungetc_buf, -1, (__UNGETC_MAX + 1) * sizeof (int));
+ if (__ungetc_buf[__FILEDES_MAX] == 0)
+ memset (__ungetc_buf, -1, (__FILEDES_MAX + 1) * sizeof (int));
}
void
diff --git a/lib/posix/read.c b/lib/posix/read.c
index 5fbda534..d47d5d15 100644
--- a/lib/posix/read.c
+++ b/lib/posix/read.c
@@ -24,7 +24,7 @@
ssize_t
read (int filedes, void *buffer, size_t size)
{
- ssize_t bytes = _read (filedes, buffer, size);
+ ssize_t bytes = __buffered_read (filedes, buffer, size);
if (__mes_debug () > 4)
{
if (bytes == 1)
diff --git a/lib/posix/write.c b/lib/posix/write.c
index 811bc0ab..6843cd55 100644
--- a/lib/posix/write.c
+++ b/lib/posix/write.c
@@ -18,12 +18,21 @@
* along with GNU Mes. If not, see .
*/
-#include
#include
+#include
ssize_t
write (int filedes, void const *buffer, size_t size)
{
+#if 0 // !MES_MINI
+ // FIXME: libc-mini has no __buffered_read_clear, lseek.
+ // and libc includes libc-mini...how to override?
+ // Let's hope everyone uses fwrite, or lseek for RDWR
+ // semantics...
+ size_t skip = __buffered_read_clear (filedes);
+ if (skip)
+ lseek (filedes, -skip, SEEK_CUR);
+#endif
int r = _write (filedes, buffer, size);
if (r < 0)
{
diff --git a/lib/stdio/fread.c b/lib/stdio/fread.c
index 77f3b864..505700ca 100644
--- a/lib/stdio/fread.c
+++ b/lib/stdio/fread.c
@@ -41,9 +41,10 @@ fread (void *data, size_t size, size_t count, FILE * stream)
int bytes = 0;
while (__fungetc_p (stream) && todo-- && ++bytes)
*buf++ = fgetc (stream);
+ int filedes = (long) stream;
if (todo)
{
- int r = read ((int) (long) stream, buf, todo);
+ int r = read (filedes, buf, todo);
if (r < 0 && !bytes)
bytes = r;
else
@@ -52,18 +53,18 @@ fread (void *data, size_t size, size_t count, FILE * stream)
if (__mes_debug ())
{
+ static char debug_buf[4096];
eputs ("fread fd=");
- eputs (itoa ((int) (long) stream));
+ eputs (itoa (filedes));
eputs (" bytes=");
eputs (itoa (bytes));
eputs ("\n");
- static char buf[4096];
- if (bytes > 0 && bytes < sizeof (buf))
+ if (bytes > 0 && bytes < sizeof (debug_buf))
{
- strncpy (buf, data, bytes);
+ strncpy (debug_buf, data, bytes);
buf[bytes] = 0;
eputs ("fread buf=");
- eputs (buf);
+ eputs (debug_buf);
eputs ("\n");
}
}
diff --git a/lib/stdio/fseek.c b/lib/stdio/fseek.c
index 268f9792..ce468ab3 100644
--- a/lib/stdio/fseek.c
+++ b/lib/stdio/fseek.c
@@ -1,6 +1,6 @@
/* -*-comment-start: "//";comment-end:""-*-
* GNU Mes --- Maxwell Equations of Software
- * Copyright © 2017,2018 Jan (janneke) Nieuwenhuizen
+ * Copyright © 2017,2018,2019 Jan (janneke) Nieuwenhuizen
*
* This file is part of GNU Mes.
*
@@ -25,11 +25,12 @@
int
fseek (FILE * stream, long offset, int whence)
{
- off_t pos = lseek ((int) (long) stream, offset, whence);
+ int filedes = (long) stream;
+ off_t pos = lseek (filedes, offset, whence);
if (__mes_debug ())
{
eputs ("fread fd=");
- eputs (itoa ((int) (long) stream));
+ eputs (itoa (filedes));
eputs (" =>");
eputs (itoa (pos));
eputs ("\n");
diff --git a/lib/stdio/fwrite.c b/lib/stdio/fwrite.c
index 995450e9..6e048ee2 100644
--- a/lib/stdio/fwrite.c
+++ b/lib/stdio/fwrite.c
@@ -20,6 +20,7 @@
#include
#include
+#include
size_t
fwrite (void const *data, size_t size, size_t count, FILE * stream)
@@ -35,7 +36,12 @@ fwrite (void const *data, size_t size, size_t count, FILE * stream)
if (!size || !count)
return 0;
- int bytes = write ((int) (long) stream, data, size * count);
+ // FIXME: should be in write, but that's libc-mini.
+ int filedes = (long) stream;
+ size_t skip = __buffered_read_clear (filedes);
+ if (skip)
+ lseek (filedes, -skip, SEEK_CUR);
+ int bytes = write (filedes, data, size * count);
if (__mes_debug () > 2)
{
diff --git a/mes/module/mes/repl.mes b/mes/module/mes/repl.mes
index 4f4ab5a3..f3244203 100644
--- a/mes/module/mes/repl.mes
+++ b/mes/module/mes/repl.mes
@@ -29,7 +29,7 @@
(define welcome
(string-append "GNU Mes " %version "
-Copyright (C) 2016,2017,2018 Jan (janneke) Nieuwenhuizen
+Copyright (C) 2016,2017,2018,2019 Jan (janneke) Nieuwenhuizen
GNU Mes comes with ABSOLUTELY NO WARRANTY; for details type `,show w'.
This program is free software, and you are welcome to redistribute it
diff --git a/simple.sh b/simple.sh
index b0b02d7d..97e249e6 100755
--- a/simple.sh
+++ b/simple.sh
@@ -167,12 +167,14 @@ $CC -g -D HAVE_CONFIG_H=1 -I include -I include/$mes_kernel/$mes_cpu\
lib/ctype/isxdigit.c\
\
lib/mes/__assert_fail.c\
+ lib/mes/__buffered_read.c\
lib/mes/__mes_debug.c\
lib/posix/execv.c\
lib/posix/getcwd.c\
lib/posix/getenv.c\
lib/posix/isatty.c\
lib/posix/open.c\
+ lib/posix/read.c\
lib/posix/setenv.c\
lib/posix/wait.c\
lib/stdio/fgetc.c\
@@ -189,6 +191,7 @@ $CC -g -D HAVE_CONFIG_H=1 -I include -I include/$mes_kernel/$mes_cpu\
lib/string/memchr.c\
lib/string/memcmp.c\
lib/string/memcpy.c\
+ lib/string/memmove.c\
lib/string/memset.c\
lib/string/strcmp.c\
lib/string/strcpy.c\
@@ -207,7 +210,7 @@ $CC -g -D HAVE_CONFIG_H=1 -I include -I include/$mes_kernel/$mes_cpu\
lib/linux/gettimeofday.c\
lib/linux/ioctl.c\
lib/linux/_open3.c\
- lib/linux/read.c\
+ lib/linux/_read.c\
lib/linux/time.c\
lib/linux/unlink.c\
lib/linux/waitpid.c\