]> git.draconx.ca Git - cdecl99.git/commitdiff
cdecl99: Fall back to getline, instead of Gnulib's readline.
authorNick Bowler <nbowler@draconx.ca>
Wed, 5 Jul 2023 01:15:39 +0000 (21:15 -0400)
committerNick Bowler <nbowler@draconx.ca>
Wed, 5 Jul 2023 01:15:39 +0000 (21:15 -0400)
When building without readline, instead of using Gnulib's readline
replacement, use getline directly.  We can combine most of the batch
and interactive mode processing loops which saves a bunch of pointless
extra code in the readline-disabled case.

To actually do this, we prepare a Gnulib "local dir" to implement
a cut-down readline module that includes the configure tests only.

.gitignore
lib/.gitignore [new file with mode: 0644]
lib/local/modules/gnulib-local [new file with mode: 0644]
lib/local/modules/readline [new file with mode: 0644]
m4/gnulib-cache.m4
src/cdecl99.c

index 2a3a25d0f130e8b37b4035a96a465b1dae0d71dd..b99d82d575b9895a93d4daf943ba4e7cfb7e87c1 100644 (file)
@@ -19,7 +19,6 @@
 /exported.sh
 /gitlog-to-changelog
 /install-sh
-/lib
 /libtool
 /ltmain.sh
 /missing
diff --git a/lib/.gitignore b/lib/.gitignore
new file mode 100644 (file)
index 0000000..baacf4f
--- /dev/null
@@ -0,0 +1,3 @@
+/*
+!/.gitignore
+!/local
diff --git a/lib/local/modules/gnulib-local b/lib/local/modules/gnulib-local
new file mode 100644 (file)
index 0000000..20e3120
--- /dev/null
@@ -0,0 +1,35 @@
+Description:
+Helper to export gnulib-tool local-dir settings to Automake and distribute
+files automatically.
+
+configure.ac:
+AC_REQUIRE([AC_PROG_AWK])dnl
+m4_pushdef([gl_LOCAL_DIR],
+  [m4_define([_GNULIB_LOCAL_DIR_], $][@)])m4_divert_push([KILL])
+m4_include([m4/gnulib-cache.m4])
+m4_popdef([gl_LOCAL_DIR])m4_divert_pop([KILL])dnl
+AC_SUBST([GNULIB_LOCAL_DIR], m4_defn([_GNULIB_LOCAL_DIR_]))
+
+Makefile.am:
+GNULIB_LOCAL_DIST = modules/gnulib-local
+GNULIB_LOCAL_DIRS_AWK = \
+       { for (i=1; i<=NF; i++) { sub(/\/[^\/]*$$/, "", $$i); dirs[$$i]=1; } } \
+       END { for (i in dirs) print outdir "/" i; }
+
+dist-hook: dist-gnulib-local
+dist-gnulib-local:
+       save_IFS=$$IFS; \
+       IFS=:; set x $(GNULIB_LOCAL_DIR); shift; \
+       IFS=$$save_IFS; \
+       outdir="$(top_distdir)/$$1"; \
+       dirs=`echo $(GNULIB_LOCAL_DIST) \
+             | $(AWK) '$(GNULIB_LOCAL_DIRS_AWK)' outdir="$$outdir"`; \
+       ( set -x; $(MKDIR_P) $$dirs && chmod u+w $$dirs ) || exit; \
+       for f in $(GNULIB_LOCAL_DIST); do \
+         for indir; do \
+           test -f "$(top_srcdir)/$$indir/$$f" || continue; \
+           ( set -x; cp -p "$(top_srcdir)/$$indir/$$f" "$$outdir/$$f" ) || exit; \
+           break; \
+         done; \
+       done
+.PHONY: dist-gnulib-local
diff --git a/lib/local/modules/readline b/lib/local/modules/readline
new file mode 100644 (file)
index 0000000..3a9c7f4
--- /dev/null
@@ -0,0 +1,30 @@
+Description:
+Simple implementation of readline, modified to include only the
+Autoconf library tests (2023-07).
+
+Files:
+m4/readline.m4
+
+Depends-on:
+gnulib-local
+havelib
+
+configure.ac:
+gl_FUNC_READLINE
+
+Makefile.am:
+GNULIB_LOCAL_DIST += modules/readline
+
+Include:
+#if HAVE_READLINE_READLINE_H
+#  include <readline/readline.h>
+#endif
+
+Link:
+$(LTLIBREADLINE) when linking with libtool, $(LIBREADLINE) otherwise
+
+License:
+GPL
+
+Maintainer:
+Simon Josefsson
index 2b29495f30616c654937ee92354abbe5f8565991..c9703057da93505b034b7d51d6ed5ef969960bf8 100644 (file)
@@ -27,7 +27,7 @@
 
 
 # Specification in the form of a command-line invocation:
-# gnulib-tool --import \
+# gnulib-tool --import --local-dir=lib/local \
 #  --lib=libgnu \
 #  --source-base=lib \
 #  --m4-base=m4 \
@@ -53,7 +53,7 @@
 #  tls
 
 # Specification in the form of a few gnulib-tool.m4 macro invocations:
-gl_LOCAL_DIR([])
+gl_LOCAL_DIR([lib/local])
 gl_MODULES([
   getline
   getopt-gnu
index 5ddc889f05168d279d32eb88612231a848f1a8f3..d7ddd77960a284fa07844a5bf67331b1453ae36a 100644 (file)
@@ -29,7 +29,6 @@
 
 #include <getopt.h>
 #include <gettext.h>
-#include <readline.h>
 #include <localcharset.h>
 #include <mbswidth.h>
 
 #include "copysym.h"
 #include "options.h"
 
+#if HAVE_READLINE_READLINE_H
+#  include <readline/readline.h>
+#endif
+
 static const char *progname = "cdecl99";
 static bool interactive = true;
 
@@ -112,22 +115,6 @@ static int is_blank_line(const char *line)
        return !line[strspn(line, " \t")];
 }
 
-static int repl(void)
-{
-       char *line;
-
-       for (; (line = readline("> ")); free(line)) {
-               if (!is_blank_line(line))
-                       add_history(line);
-
-               if (run_command(line, true) > 0)
-                       break;
-       }
-
-       free(line);
-       return 0;
-}
-
 static int repl_cmdline(unsigned count, char **commands)
 {
        int ret = 0;
@@ -144,32 +131,59 @@ static int repl_cmdline(unsigned count, char **commands)
        return ret;
 }
 
-static int repl_noninteractive(void)
+static int do_getline(char **linebuf, size_t *n)
 {
-       int rc, ret = 0, saved_errno;
-       char *line = NULL;
-       size_t n;
+       ssize_t rc;
 
-       while (getline(&line, &n, stdin) >= 0) {
-               char *c = strchr(line, '\n');
-               if (c)
-                       *c = '\0';
+       if ((rc = getline(linebuf, n, stdin)) < 0) {
+               if (ferror(stdin))
+                       print_error("%s", strerror(errno));
+               return 0;
+       }
 
-               rc = run_command(line, false);
-               if (rc < 0)
-                       ret = -1;
-               else if (rc > 0)
-                       break;
+       if (rc-- && (*linebuf)[rc] == '\n')
+               (*linebuf)[rc] = '\0';
+       return 1;
+}
+
+static int do_readline(char **linebuf, size_t *n, int interactive)
+{
+#if !HAVE_READLINE
+       if (interactive) {
+               fputs("> ", stdout);
+               fflush(stdout);
        }
 
-       saved_errno = errno;
-       free(line);
+       return do_getline(linebuf, n);
+#else
+       if (!interactive)
+               return do_getline(linebuf, n);
+
+       free(*linebuf);
+       if (!(*linebuf = readline("> ")))
+               return 0;
+
+       if (!is_blank_line(*linebuf))
+               add_history(*linebuf);
+       return 1;
+#endif
+}
+
+static int repl(int interactive)
+{
+       char *line = NULL;
+       int ret = 0;
+       size_t n;
 
-       if (ferror(stdin)) {
-               print_error("%s", strerror(saved_errno));
-               return -1;
+       while (do_readline(&line, &n, interactive)) {
+               int rc = run_command(line, interactive);
+               if (rc > 0)
+                       break;
+               else if (rc < 0)
+                       ret = -!interactive;
        }
 
+       free(line);
        return ret;
 }
 
@@ -270,12 +284,10 @@ int main(int argc, char **argv)
        case INIT_EXIT_FAILURE: return EXIT_FAILURE;
        }
 
-       if (interactive)
-               rc = repl();
-       else if (execute)
+       if (execute)
                rc = repl_cmdline(execute, argv);
        else
-               rc = repl_noninteractive();
+               rc = repl(interactive);
 
        if (rc != 0)
                return EXIT_FAILURE;