# HG changeset patch # User John W. Eaton # Date 1558633377 14400 # Node ID b652a5528fb173c81b4ce2e600d4566de528872d # Parent 69f5d5e42d2bf36383f22437d2d52a4c9574b826 handle EOF on input; more misc refactoring diff -r 69f5d5e42d2b -r b652a5528fb1 command-window.cpp --- a/command-window.cpp Thu May 23 12:58:58 2019 -0400 +++ b/command-window.cpp Thu May 23 13:42:57 2019 -0400 @@ -20,6 +20,12 @@ namespace calc { + // We could eliminate this global variable and the global + // command_window::the_command_window variable if readline callbacks + // could be defined as C++ lambda functions. Then the lambdas could + // have direct access to the command_window object and it could + // contain the next available character. + static int available_char = 0; // vvvvv readline vvvvv @@ -39,16 +45,23 @@ static void prep_term (int) { + // Anything to do here? } static void deprep_term (void) { + // Anything to do here? } static void accept_line (char *line) { if (command_window::the_command_window) - command_window::the_command_window->accept_line (line ? line : ""); + { + if (! line) + command_window::the_command_window->eof (); + else + command_window::the_command_window->accept_line (line); + } } static void display_completion_matches (char **matches, int num_matches, @@ -70,7 +83,7 @@ } } - void readline_init (void) + static void readline_init (void) { rl_initialize (); @@ -83,7 +96,7 @@ rl_callback_handler_install (">> ", accept_line); } - void readline_fini (void) + static void readline_fini (void) { rl_callback_handler_remove (); } @@ -93,8 +106,7 @@ command_window *command_window::the_command_window = nullptr; command_window::command_window (QWidget *p) - : QTextEdit (p), - m_buffer (new QTextDocument ()), + : QTextEdit (p), m_buffer (new QTextDocument ()), m_interpreter (new calc::qt_interpreter ()), beg_mark (), prompt_mark () { @@ -127,6 +139,9 @@ connect (this, SIGNAL (accept_line_signal (const QString&)), m_interpreter, SLOT (accept_input_line (const QString&))); + connect (this, SIGNAL (eof_signal (void)), + this, SLOT (close (void))); + insert_at_end ("Qt Example Calculator.\n" "Available operations: + - * / ^ ()\n" @@ -136,11 +151,18 @@ beg_mark = set_mark (); + readline_init (); + // Defer initializing and executing the interpreter until after the main // window and QApplication are running to prevent race conditions QTimer::singleShot (0, m_interpreter, SLOT (execute (void))); } + command_window::~command_window (void) + { + readline_fini (); + } + // Accept an input line, parse and possibly execute it. void command_window::accept_line (const std::string& line) @@ -156,6 +178,11 @@ } } + void command_window::eof (void) + { + emit eof_signal (); + } + void command_window::insert_at_end (const std::string& text) { scroll_to_bottom (); diff -r 69f5d5e42d2b -r b652a5528fb1 command-window.h --- a/command-window.h Thu May 23 12:58:58 2019 -0400 +++ b/command-window.h Thu May 23 13:42:57 2019 -0400 @@ -20,12 +20,16 @@ command_window (QWidget *p = nullptr); - virtual ~command_window (void) = default; + ~command_window (void); // Accept an input line, parse and possibly execute it. void accept_line (const std::string& line); + // Handle EOF on input. + + void eof (void); + // Redisplay current command line. void insert_at_end (const std::string& text); @@ -40,6 +44,8 @@ void accept_line_signal (const QString& line); + void eof_signal (void); + void redisplay_signal (void); public slots: @@ -84,10 +90,6 @@ int beg_mark; int prompt_mark; }; - - extern void readline_init (void); - - extern void readline_fini (void); } #endif diff -r 69f5d5e42d2b -r b652a5528fb1 gui-main.cpp --- a/gui-main.cpp Thu May 23 12:58:58 2019 -0400 +++ b/gui-main.cpp Thu May 23 13:42:57 2019 -0400 @@ -20,12 +20,6 @@ command_window.show (); - readline_init (); - - int status = app.exec (); - - readline_fini (); - - return status; + return app.exec (); } } diff -r 69f5d5e42d2b -r b652a5528fb1 parser.yy --- a/parser.yy Thu May 23 12:58:58 2019 -0400 +++ b/parser.yy Thu May 23 13:42:57 2019 -0400 @@ -16,11 +16,14 @@ namespace parser { - FILE *outfile = 0; + // For communication between the lexer and parser. size_t bufptr = 0; size_t chunk_size = 0; + const char *buf; - const char *buf; + // Used to tell readline whether to display the prompt indicating + // a continuation line. Is there any way we could do this job + // without a global variable? bool beg_of_stmt = true; static int yylex (void); @@ -138,6 +141,9 @@ return c; } + // If we defined a parser object, the parser state could be a + // member variable of that object. + static yypstate *ps = 0; void init (void)