Commit ae709b76d88fc2891cec477d859b46df1632caab

Thomas de Grivel 2023-12-13T21:53:07

ic3 with wineditline

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