changeset 11:b652a5528fb1

handle EOF on input; more misc refactoring
author John W. Eaton <jwe@octave.org>
date Thu, 23 May 2019 13:42:57 -0400
parents 69f5d5e42d2b
children 894be158b32d
files command-window.cpp command-window.h gui-main.cpp parser.yy
diffstat 4 files changed, 48 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- 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 ();
--- 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
--- 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 ();
   }
 }
--- 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)