diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b26ac50..ccab47e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -48,7 +48,7 @@ option(WITH_HOST_FST "Enable host fst support" ON) option(TOGGLE_STATUS "Enable F10 Toggle Status support (win32/x11)" OFF) option(WITH_RAWNET "Enable Uthernet emulation" OFF) option(WITH_ATBRIDGE "Enable AT Bridge" OFF) - +set(READLINE "NONE" CACHE STRING "Readline library (NONE, READLINE, LIBEDIT") set(generated_headers 8inst_c.h 16inst_c.h 8inst_s.h 16inst_s.h size_c.h size_s.h 8size_s.h 16size_s.h) add_custom_command( @@ -142,6 +142,8 @@ SET_SOURCE_FILES_PROPERTIES( MACOSX_PACKAGE_LOCATION Resources ) + + if(APPLE) add_custom_command(TARGET GSplus POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different @@ -152,6 +154,16 @@ if(APPLE) endif() # SET_SOURCE_FILES_PROPERTIES(vmnet_helper PROPERTIES MACOSX_PACKAGE_LOCATION MacOS) +add_library(x_readline readline.c) +if(READLINE MATCHES "READLINE") + target_compile_definitions(x_readline PRIVATE USE_READLINE) + target_link_libraries(x_readline PUBLIC history readline) +elseif(READLINE MATCHES "LIBEDIT") + target_compile_definitions(x_readline PRIVATE USE_LIBEDIT) + target_link_libraries(x_readline PUBLIC edit) +endif() + +target_link_libraries(GSplus x_readline) if (WITH_RAWNET) target_link_libraries(GSplus rawnet) diff --git a/src/debug_shell.re2c b/src/debug_shell.re2c index 1f89f2a..f516ff2 100644 --- a/src/debug_shell.re2c +++ b/src/debug_shell.re2c @@ -16,7 +16,7 @@ #include "disasm.h" - +extern char *x_readline(const char *prompt); extern int g_fullscreen; extern int g_config_control_panel; @@ -865,31 +865,13 @@ command: */ } -char *readline(const char *prompt) { - static char buffer[1024]; - fputs(prompt, stdout); - fflush(stdout); +enum { + MODE_NORMAL, + MODE_ASSEMBER +}; - for(;;) { - int ok = read(STDIN_FILENO, buffer, sizeof(buffer)-1); - if (ok < 0) { - if (ok == EINTR) continue; - return NULL; - } - if (ok == 0) return NULL; - while (ok) { - char c = buffer[ok-1]; - if (c == ' ' || c == '\r' || c == '\n') { - --ok; - continue; - } - break; - } - buffer[ok] = 0; +static int g_debugger_mode = MODE_NORMAL; - return buffer; - } -} int debug_shell(int code) { int c; @@ -923,7 +905,7 @@ int debug_shell(int code) { do_list(engine.kpc, &psr, 1); for(;;) { - cp = readline("> "); + cp = x_readline("> "); if (!cp) return 0; if (!*cp) continue; c = parse_command(cp); diff --git a/src/readline.c b/src/readline.c new file mode 100644 index 0000000..041d0d7 --- /dev/null +++ b/src/readline.c @@ -0,0 +1,164 @@ +#include +#include +#include +#include +#include + +#if defined(USE_LIBEDIT) + +#include + + + /* BSD libedit support */ +EditLine *el = NULL; +History *hist = NULL; +HistEvent ev; + +static const char *el_prompt = NULL; +static char *prompt_fn(EditLine *el) { + return el_prompt ? (char *)el_prompt : ""; +} + +char *x_readline(const char *prompt) { + static char buffer[1024]; + int ok = 0; + const char *cp; + + if (!el) { + hist = history_init(); + history(hist, &ev, H_SETSIZE, 50); + history(hist, &ev, H_SETUNIQUE, 1); + + el = el_init("GS+", stdin, stdout, stderr); + el_set(el, EL_EDITOR, "emacs"); + el_set(el, EL_BIND, "-e", NULL, NULL, NULL); + el_set(el, EL_HIST, history, hist); + el_set(el, EL_PROMPT, prompt_fn); + el_set(el, EL_SIGNAL, 1); + el_source(el, NULL); + } + + el_prompt = prompt; + cp = el_gets(el, &ok); + el_prompt = NULL; + if (ok <= 0) return NULL; + if (ok > sizeof(buffer) - 1) return ""; + + + memcpy(buffer, cp, ok); + while (ok) { + unsigned c = buffer[ok-1]; + if (c == ' ' || c == '\r' || c == '\n') { + --ok; + continue; + } + break; + } + buffer[ok] = 0; + + if (*buffer) + history(hist, &ev, H_ENTER, buffer); + + return buffer; +} + +void x_readline_end(void) { + if (el) { + el_end(el); + el = NULL; + } + if (hist) { + history_end(hist); + hist = NULL; + } +} + +#elif defined(USE_READLINE) + /* GNU Readline support */ + +#include +#include + +static int readline_init = 0; +/* suppress tab completion, which defaults to filenames */ +static char **rl_acf(const char* text, int start, int end) { + return NULL; +} +char *x_readline(const char *prompt) { + static char buffer[1024]; + + char *cp; + int ok; + + if (!readline_init) { + rl_readline_name = "GS+"; + rl_attempted_completion_function = rl_acf; + + using_history(); + stifle_history(50); + + readline_init = 1; + } + + char *cp = readline(prompt); + if (!cp) return NULL; + ok = strlen(cp); + if (ok > sizeof(buffer1) - 1) { + free(cp); + return ""; + } + memcpy(buffer, cp, ok); + while (ok) { + unsigned c = buffer[ok-1]; + if (c == ' ' || c == '\r' || c == '\n') { + --ok; + continue; + } + break; + } + buffer[ok] = 0; + free(cp); + + /* append to history, but only if unique from prev. entry */ + if (*buffer) { + HIST_ENTRY *h = history_get(history_length-1); + if (h == NULL || strcmp(buffer, h->line)) + add_history(buffer); + } + return buffer; +} + +void x_readline_end(void) { +} +#else + +char *x_readline(const char *prompt) { + static char buffer[1024]; + fputs(prompt, stdout); + fflush(stdout); + + for(;;) { + int ok = read(STDIN_FILENO, buffer, sizeof(buffer)-1); + if (ok < 0) { + if (ok == EINTR) continue; + return NULL; + } + if (ok == 0) return NULL; + while (ok) { + unsigned c = buffer[ok-1]; + if (c == ' ' || c == '\r' || c == '\n') { + --ok; + continue; + } + break; + } + buffer[ok] = 0; + + return buffer; + } +} + +void x_readline_end(void) { + +} +#endif