diff --git a/Makefile b/Makefile index ad38866..d4e354a 100644 --- a/Makefile +++ b/Makefile @@ -160,6 +160,8 @@ OBJ=\ ui/stdcmd.o \ ui/aliasdb.o \ ui/power.o \ + ui/input.o \ + ui/input_console.o \ ui/main.o $(BINARY): $(OBJ) diff --git a/ui/input.c b/ui/input.c new file mode 100644 index 0000000..d21788f --- /dev/null +++ b/ui/input.c @@ -0,0 +1,23 @@ +/* MSPDebug - debugging tool for MSP430 MCUs + * Copyright (C) 2009-2012 Daniel Beer + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "input.h" +#include "input_console.h" + +/* Default input module */ +const struct input_interface *input_module = &input_console; diff --git a/ui/input.h b/ui/input.h new file mode 100644 index 0000000..31fb66c --- /dev/null +++ b/ui/input.h @@ -0,0 +1,51 @@ +/* MSPDebug - debugging tool for MSP430 MCUs + * Copyright (C) 2009-2012 Daniel Beer + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef INPUT_H_ +#define INPUT_H_ + +/* This defines the interface to an input module. The input module is + * responsible for providing a way of fetching commands to be executed, + * and a way of presenting yes/no questions to the user ("are you sure + * you want to ...?"). + */ +struct input_interface { + /* Initialize/tear down the input subsystem. */ + int (*init)(void); + void (*exit)(void); + + /* Read a command from the user into the supplied buffer. This + * function returns 0 on success, -1 if an error occurs, and 1 + * if the end of input has been reached. + */ + int (*read_command)(char *buf, int max_len); + + /* Prompt the user before performing a destructive operation. + * The question should be phrased so that "yes" confirms that + * the operation should proceed. + * + * Returns 1 for no (abort), 0 for yes (continue), and -1 if an + * error occurs. + */ + int (*prompt_abort)(const char *message); +}; + +/* Variable which holds a reference to the selected input module. */ +extern const struct input_interface *input_module; + +#endif diff --git a/ui/input_console.c b/ui/input_console.c new file mode 100644 index 0000000..e9ca1aa --- /dev/null +++ b/ui/input_console.c @@ -0,0 +1,127 @@ +/* MSPDebug - debugging tool for MSP430 MCUs + * Copyright (C) 2009-2012 Daniel Beer + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +#ifdef USE_READLINE +#include +#include +#endif + +#include "input_console.h" +#include "util.h" + +#ifndef USE_READLINE +#define LINE_BUF_SIZE 128 + +static char *readline(const char *prompt) +{ + char *buf = malloc(LINE_BUF_SIZE); + + if (!buf) { + fprintf(stdout, "readline: can't allocate memory: %s\n", + last_error()); + return NULL; + } + + for (;;) { + printf("%s", prompt); + fflush(stdout); + + if (fgets(buf, LINE_BUF_SIZE, stdin)) { + int len = strlen(buf); + + while (len > 0 && isspace(buf[len - 1])) + len--; + + buf[len] = 0; + return buf; + } + + if (feof(stdin)) + break; + + printf("\n"); + } + + free(buf); + return NULL; +} + +#define add_history(x) +#endif + +static int console_init(void) +{ + return 0; +} + +static void console_exit(void) { } + +static int console_read_command(char *out, int max_len) +{ + char *buf = readline("(mspdebug) "); + + if (!buf) { + printf("\n"); + return 1; + } + + if (*buf) + add_history(buf); + + strncpy(out, buf, max_len); + out[max_len - 1] = 0; + free(buf); + + return 0; +} + +static int console_prompt_abort(const char *message) +{ + char buf[32]; + + for (;;) { + printf("%s ", message); + fflush(stdout); + + if (!fgets(buf, sizeof(buf), stdin)) { + printf("\n"); + return 1; + } + + if (toupper(buf[0]) == 'Y') + return 0; + if (toupper(buf[0]) == 'N') + return 1; + + printf("Please answer \"y\" or \"n\".\n"); + } + + return 0; +} + +const struct input_interface input_console = { + .init = console_init, + .exit = console_exit, + .read_command = console_read_command, + .prompt_abort = console_prompt_abort +}; diff --git a/ui/input_console.h b/ui/input_console.h new file mode 100644 index 0000000..691b185 --- /dev/null +++ b/ui/input_console.h @@ -0,0 +1,26 @@ +/* MSPDebug - debugging tool for MSP430 MCUs + * Copyright (C) 2009-2012 Daniel Beer + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef INPUT_CONSOLE_H_ +#define INPUT_CONSOLE_H_ + +#include "input.h" + +extern const struct input_interface input_console; + +#endif diff --git a/ui/main.c b/ui/main.c index 83da0a9..7950dd9 100644 --- a/ui/main.c +++ b/ui/main.c @@ -51,6 +51,7 @@ #include "gdbc.h" #include "tilib.h" #include "goodfet.h" +#include "input.h" struct cmdline_args { const char *driver_name; @@ -374,6 +375,9 @@ int main(int argc, char **argv) if (parse_cmdline_args(argc, argv, &args) < 0) return -1; + if (input_module->init() < 0) + return -1; + if (sockets_init() < 0) return -1; @@ -407,6 +411,7 @@ int main(int argc, char **argv) stab_exit(); device_destroy(); sockets_exit(); + input_module->exit(); return ret; } diff --git a/ui/reader.c b/ui/reader.c index 691ca9b..43dfae4 100644 --- a/ui/reader.c +++ b/ui/reader.c @@ -22,11 +22,6 @@ #include #include -#ifdef USE_READLINE -#include -#include -#endif - #include "vector.h" #include "util.h" #include "output.h" @@ -36,6 +31,7 @@ #include "opdb.h" #include "aliasdb.h" #include "ctrlc.h" +#include "input.h" #define MAX_READER_LINE 1024 @@ -56,64 +52,13 @@ void unmark_modified(int flags) int prompt_abort(int flags) { - char buf[32]; + if (!(in_reader_loop && (modify_flags & flags))) + return 0; - if (!(in_reader_loop && (modify_flags & flags))) - return 0; - - for (;;) { - printf("Symbols have not been saved since modification. " - "Continue (y/n)? "); - fflush(stdout); - - if (!fgets(buf, sizeof(buf), stdin)) { - printc("\n"); - return 1; - } - - if (toupper(buf[0]) == 'Y') - return 0; - if (toupper(buf[0]) == 'N') - return 1; - - printc("Please answer \"y\" or \"n\".\n"); - } - - return 0; + return input_module->prompt_abort("Symbols have not been saved " + "since modification. Continue (y/n)?"); } -#ifndef USE_READLINE -#define LINE_BUF_SIZE 128 - -static char *readline(const char *prompt) -{ - char *buf = malloc(LINE_BUF_SIZE); - - if (!buf) { - pr_error("readline: can't allocate memory"); - return NULL; - } - - for (;;) { - printf("(mspdebug) "); - fflush(stdout); - - if (fgets(buf, LINE_BUF_SIZE, stdin)) - return buf; - - if (feof(stdin)) - break; - - printc("\n"); - } - - free(buf); - return NULL; -} - -#define add_history(x) -#endif - static int do_command(char *arg, int interactive) { const char *cmd_text; @@ -189,26 +134,16 @@ void reader_loop(void) want_exit = 0; for (;;) { - char *buf = readline("(mspdebug) "); char tmpbuf[MAX_READER_LINE]; + char *buf = tmpbuf; - if (!buf) { - printc("\n"); + if (input_module->read_command(tmpbuf, sizeof(tmpbuf))) break; - } - /* Copy into our local buffer and free */ - strncpy(tmpbuf, buf, sizeof(tmpbuf)); - tmpbuf[sizeof(tmpbuf) - 1] = 0; - free(buf); - buf = tmpbuf; - - if (*buf) { - add_history(buf); + if (*buf) repeat_buf[0] = 0; - } else { + else memcpy(tmpbuf, repeat_buf, sizeof(tmpbuf)); - } ctrlc_clear(); do_command(buf, 1);