diff --git a/config.subr b/config.subr
index e520590..01465a9 100644
--- a/config.subr
+++ b/config.subr
@@ -314,8 +314,8 @@ update_sources_sh() {
CONFIG_H=config.h
CONFIG_H=".config.h.tmp"
echo "/* config.h generated by configure */" > ${CONFIG_H}
-echo "#ifndef CONFIG_H" >> ${CONFIG_H}
-echo "#define CONFIG_H" >> ${CONFIG_H}
+echo "#ifndef ${CONFIG_H_PREFIX}CONFIG_H" >> ${CONFIG_H}
+echo "#define ${CONFIG_H_PREFIX}CONFIG_H" >> ${CONFIG_H}
CONFIG_MK=config.mk
CONFIG_MK=".config.mk.tmp"
diff --git a/ic3/buf_wineditline.c b/ic3/buf_wineditline.c
new file mode 100644
index 0000000..06acb84
--- /dev/null
+++ b/ic3/buf_wineditline.c
@@ -0,0 +1,125 @@
+/* c3
+ * Copyright 2022,2023 kmx.io <contact@kmx.io>
+ *
+ * Permission is hereby granted to use this software granted the above
+ * copyright notice and this permission paragraph are included in all
+ * copies and substantial portions of this software.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS-IS" WITHOUT ANY GUARANTEE OF
+ * PURPOSE AND PERFORMANCE. IN NO EVENT WHATSOEVER SHALL THE
+ * AUTHOR BE CONSIDERED LIABLE FOR THE USE AND PERFORMANCE OF
+ * THIS SOFTWARE.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <readline.h>
+#include "../libc3/c3.h"
+
+typedef struct buf_wineditline {
+ s_buf buf;
+ bool eof;
+ const s8 *prompt;
+} s_buf_wineditline;
+
+sw buf_wineditline_refill_fgets (s_buf *buf);
+sw buf_wineditline_refill_wineditline (s_buf *buf);
+
+void buf_wineditline_close (s_buf *buf, const s8 *history_path)
+{
+ assert(buf);
+ if (history_path)
+ write_history(history_path);
+ buf->refill = NULL;
+ free(buf->user_ptr);
+ buf->user_ptr = NULL;
+ if (isatty(STDIN_FILENO))
+ puts("");
+}
+
+s_buf * buf_wineditline_open_r (s_buf *buf, const s8 *prompt,
+ const s8 *history_path)
+{
+ s_buf_wineditline *buf_wineditline;
+ assert(buf);
+ buf_wineditline = malloc(sizeof(s_buf_wineditline));
+ if (! buf_wineditline) {
+ err_puts("buf_wineditline_open_r: failed to allocate memory");
+ return NULL;
+ }
+ buf_init(&buf_wineditline->buf, false, 1, "");
+ buf_wineditline->eof = false;
+ if (isatty(STDIN_FILENO))
+ buf->refill = buf_wineditline_refill_wineditline;
+ else
+ buf->refill = buf_wineditline_refill_fgets;
+ buf_wineditline->prompt = prompt;
+ if (history_path) {
+ using_history();
+ read_history(history_path);
+ }
+ buf->user_ptr = buf_wineditline;
+ return buf;
+}
+
+sw buf_wineditline_refill_fgets (s_buf *buf)
+{
+ sw c = 0;
+ uw result = 0;
+ assert(buf);
+ assert(buf->user_ptr);
+ if (buf->rpos > buf->wpos ||
+ buf->wpos > buf->size)
+ return -1;
+ if (feof(stdin))
+ return -1;
+ while (buf->wpos < buf->size &&
+ c != '\n' &&
+ (c = getchar()) != EOF &&
+ c <= 255) {
+ buf_write_u8(buf, c);
+ result++;
+ }
+ return result;
+}
+
+sw buf_wineditline_refill_wineditline (s_buf *buf)
+{
+ s_buf_wineditline *buf_wineditline;
+ uw buf_wineditline_len;
+ uw r;
+ uw size;
+ assert(buf);
+ assert(buf->user_ptr);
+ if (buf->rpos > buf->wpos ||
+ buf->wpos > buf->size)
+ return -1;
+ size = buf->size - buf->wpos;
+ if (size == 0)
+ return 0;
+ buf_wineditline = buf->user_ptr;
+ if (buf_wineditline->eof)
+ return -1;
+ buf_wineditline_len = buf_wineditline->buf.wpos - buf_wineditline->buf.rpos;
+ if (buf_wineditline_len == 0) {
+ free(buf_wineditline->buf.ptr.p);
+ if (! (buf_wineditline->buf.ptr.p = readline(buf_wineditline->prompt))) {
+ buf_wineditline->eof = true;
+ buf_wineditline->buf.rpos =
+ buf_wineditline->buf.wpos =
+ buf_wineditline->buf.size = 0;
+ return -1;
+ }
+ add_history(buf_wineditline->buf.ptr.p);
+ buf_wineditline_len = strlen(buf_wineditline->buf.ptr.p);
+ buf_wineditline->buf.ptr.ps8[buf_wineditline_len++] = '\n';
+ buf_wineditline->buf.size = buf_wineditline->buf.wpos = buf_wineditline_len;
+ buf_wineditline->buf.rpos = 0;
+ }
+ if (buf_wineditline_len < size)
+ size = buf_wineditline_len;
+ if ((r = buf_xfer(buf, &buf_wineditline->buf, size)) != size)
+ return -1;
+ return size;
+}
diff --git a/ic3/buf_wineditline.h b/ic3/buf_wineditline.h
new file mode 100644
index 0000000..abe6083
--- /dev/null
+++ b/ic3/buf_wineditline.h
@@ -0,0 +1,24 @@
+/* c3
+ * Copyright 2022,2023 kmx.io <contact@kmx.io>
+ *
+ * Permission is hereby granted to use this software granted the above
+ * copyright notice and this permission paragraph are included in all
+ * copies and substantial portions of this software.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS-IS" WITHOUT ANY GUARANTEE OF
+ * PURPOSE AND PERFORMANCE. IN NO EVENT WHATSOEVER SHALL THE
+ * AUTHOR BE CONSIDERED LIABLE FOR THE USE AND PERFORMANCE OF
+ * THIS SOFTWARE.
+ */
+/**
+ * @file buf_wineditline.h
+ * @brief Wineditline backend for s_buf.
+ */
+#ifndef IC3_BUF_WINEDITLINE_H
+#define IC3_BUF_WINEDITLINE_H
+
+void buf_wineditline_close (s_buf *buf, const s8 *history_path);
+s_buf * buf_wineditline_open_r (s_buf *buf, const s8 *prompt,
+ const s8 *history_path);
+
+#endif /* IC3_BUF_WINEDITLINE_H */
diff --git a/ic3/configure b/ic3/configure
index 2481b5f..75006cf 100755
--- a/ic3/configure
+++ b/ic3/configure
@@ -14,6 +14,7 @@
set -e
export SRC_TOP="$(dirname "$PWD")"
+CONFIG_H_PREFIX=IC3_
. ../config.subr
@@ -24,6 +25,31 @@ PROG_DEBUG=ic3_debug
. ./sources.sh
+# Common config for all targets
+CFLAGS="$CFLAGS -W -Wall -Werror -std=c99 -pedantic"
+CPPFLAGS="-I../libffi/include $CPPFLAGS"
+config_asan
+config_gnu
+pkg_config libbsd-overlay
+pkg_config libmd
+config_lib libmd -lmd 2>/dev/null
+config_lib dl -ldl 2>/dev/null
+pkg_config wineditline
+LIBS="$LIBS ../libffi/libffi.la -pthread"
+
+if pkg-config wineditline; then
+ echo "#define HAVE_WINEDITLINE 1" >> ${CONFIG_H}
+ HAVE_WINEDITLINE=true
+ SOURCES="$SOURCES $SOURCES_WINEDITLINE"
+else
+ echo "#define HAVE_WINEDITLINE 0" >> ${CONFIG_H}
+ HAVE_WINEDITLINE=false
+ SOURCES="$SOURCES $SOURCES_LINENOISE"
+fi
+
+update_config_h
+
+# Sources
OBJECTS="$(c2ext .main.lo "$SOURCES")"
echo "OBJECTS = $OBJECTS" >> ${CONFIG_MK}
@@ -38,17 +64,6 @@ fi
OBJECTS_DEBUG="$(c2ext .debug.lo "$SOURCES")"
echo "OBJECTS_DEBUG = $OBJECTS_DEBUG" >> ${CONFIG_MK}
-# Common config for all targets
-CFLAGS="$CFLAGS -W -Wall -Werror -std=c99 -pedantic"
-CPPFLAGS="-I../libffi/include $CPPFLAGS"
-config_asan
-config_gnu
-pkg_config libbsd-overlay
-pkg_config libmd
-config_lib libmd -lmd 2>/dev/null
-config_lib dl -ldl 2>/dev/null
-LIBS="$LIBS ../libffi/libffi.la -pthread"
-
# Asan config
CFLAGS_ASAN="$CFLAGS -fsanitize=address -O1 -fno-omit-frame-pointer -g"
LDFLAGS_ASAN="$LDFLAGS"
diff --git a/ic3/ic3.c b/ic3/ic3.c
index 97f06d7..68af6bc 100644
--- a/ic3/ic3.c
+++ b/ic3/ic3.c
@@ -11,7 +11,13 @@
* THIS SOFTWARE.
*/
#include "../libc3/c3.h"
-#include "buf_linenoise.h"
+#include "config.h"
+
+#if HAVE_WINEDITLINE
+# include "buf_wineditline.h"
+#else
+# include "buf_linenoise.h"
+#endif
#define BUFSZ 0x10000
@@ -96,7 +102,11 @@ int main (int argc, char **argv)
if (argc < 1)
return usage(argv[0]);
buf_init(&in, false, sizeof(i), i);
+#if HAVE_WINEDITLINE
+ buf_wineditline_open_r(&in, "ic3> ", ".ic3_history");
+#else
buf_linenoise_open_r(&in, "ic3> ", ".ic3_history");
+#endif
in.line = 0;
buf_init(&out, false, sizeof(o), o);
buf_file_open_w(&out, stdout);
@@ -122,7 +132,11 @@ int main (int argc, char **argv)
(r = buf_ignore_character(&in)) <= 0))
break;
}
+#if HAVE_WINEDITLINE
+ buf_wineditline_close(&in, ".ic3_history");
+#else
buf_linenoise_close(&in, ".ic3_history");
+#endif
buf_file_close(&out);
c3_clean(NULL);
return 0;
diff --git a/ic3/sources.mk b/ic3/sources.mk
index acb82db..dbbce8e 100644
--- a/ic3/sources.mk
+++ b/ic3/sources.mk
@@ -1,2 +1,11 @@
# sources.mk generated by update_sources
-SOURCES = buf_linenoise.c ic3.c linenoise.c
+SOURCES = \
+ ic3.c \
+
+SOURCES_LINENOISE = \
+ buf_linenoise.c \
+ linenoise.c \
+
+SOURCES_WINEDITLINE = \
+ buf_wineditline.c \
+
diff --git a/ic3/sources.sh b/ic3/sources.sh
index 387d915..2d72ec5 100644
--- a/ic3/sources.sh
+++ b/ic3/sources.sh
@@ -1,2 +1,4 @@
# sources.sh generated by update_sources
-SOURCES='buf_linenoise.c ic3.c linenoise.c '
+SOURCES='ic3.c '
+SOURCES_LINENOISE='buf_linenoise.c linenoise.c '
+SOURCES_WINEDITLINE='buf_wineditline.c '
diff --git a/ic3/update_sources b/ic3/update_sources
index d9a351b..82701d0 100755
--- a/ic3/update_sources
+++ b/ic3/update_sources
@@ -16,10 +16,14 @@
echo "# sources.mk generated by update_sources" > ${SOURCES_MK}
echo "# sources.sh generated by update_sources" > ${SOURCES_SH}
-SOURCES="$(ls *.c)"
-SOURCES="$(echo "$SOURCES" | tr '\n' ' ')"
-echo "SOURCES = $SOURCES" >> ${SOURCES_MK}
-echo "SOURCES='$SOURCES'" >> ${SOURCES_SH}
+SOURCES="$(ls *.c | grep -v -e linenoise -e wineditline)"
+sources SOURCES "$SOURCES"
+
+SOURCES_LINENOISE="$(ls *.c | grep linenoise)"
+sources SOURCES_LINENOISE "$SOURCES_LINENOISE"
+
+SOURCES_WINEDITLINE="$(ls *.c | grep wineditline)"
+sources SOURCES_WINEDITLINE "$SOURCES_WINEDITLINE"
update_sources_mk
update_sources_sh
diff --git a/libc3/configure b/libc3/configure
index 8c372ac..f5f07d5 100755
--- a/libc3/configure
+++ b/libc3/configure
@@ -14,6 +14,7 @@
set -e
export SRC_TOP="$(dirname "$PWD")"
+CONFIG_H_PREFIX=C3_
. ../config.subr