changeset 916:2f35156aa18b

[project @ 1994-11-11 00:36:31 by jwe]
author jwe
date Fri, 11 Nov 1994 00:36:31 +0000
parents b632b159b4ed
children b843a65fa977
files src/lex.l src/parse.y src/pt-cmd.cc src/pt-cmd.h
diffstat 4 files changed, 151 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/src/lex.l
+++ b/src/lex.l
@@ -1107,6 +1107,25 @@
       token_stack.push (yylval.tok_val);
       return WHILE;
     }
+  else if (strcmp ("unwind_protect", s) == 0)
+    {
+      promptflag--;
+      yylval.tok_val = new token (l, c);
+      token_stack.push (yylval.tok_val);
+      return UNWIND_PROTECT;
+    }
+  else if (strcmp ("unwind_protect_cleanup", s) == 0)
+    {
+      yylval.tok_val = new token (l, c);
+      token_stack.push (yylval.tok_val);
+      return UNWIND_PROTECT_CLEANUP;
+    }
+  else if (strcmp ("end_unwind_protect", s) == 0)
+    {
+      end_found = 1;
+      yylval.tok_val = new token (token::unwind_protect_end, l, c);
+      token_stack.push (yylval.tok_val);
+    }
 
   if (end_found)
     {
--- a/src/parse.y
+++ b/src/parse.y
@@ -223,6 +223,7 @@
 %token <tok_val> PLOT
 %token <tok_val> TEXT STYLE
 %token <tok_val> FOR WHILE IF ELSEIF ELSE BREAK CONTINUE FUNC_RET
+%token <tok_val> UNWIND_PROTECT UNWIND_PROTECT_CLEANUP
 %token <tok_val> GLOBAL
 %token <tok_val> TEXT_ID
 
@@ -601,6 +602,15 @@
 		    iffing--;
 		    $$ = $1;
 		  }
+
+		| UNWIND_PROTECT opt_list UNWIND_PROTECT_CLEANUP opt_list END
+		  {
+		    if (check_end ($5, token::unwind_protect_end))
+		      ABORT_PARSE;
+
+		    $$ = new tree_unwind_protect_command ($2, $4, $1->line (),
+							  $1->column ());
+		  }
 		| WHILE expression optsep opt_list END
 		  {
 		    maybe_warn_assign_as_truth_value ($2);
--- a/src/pt-cmd.cc
+++ b/src/pt-cmd.cc
@@ -47,6 +47,7 @@
 #include "tree-cmd.h"
 #include "tree-misc.h"
 #include "tree-const.h"
+#include "unwind-prot.h"
 
 // Decide if it's time to quit a for or while loop.
 static int
@@ -433,6 +434,85 @@
   os << "endif";
 }
 
+// Simple exception handling.
+
+tree_unwind_protect_command::~tree_unwind_protect_command (void)
+{
+  delete unwind_protect_code;
+  delete cleanup_code;
+}
+
+static void
+do_unwind_protect_cleanup_code (void *ptr)
+{
+  tree_statement_list *list = (tree_statement_list *) ptr;
+
+// We want to run the cleanup code without error_state being set, but
+// we need to restore its value, so that any errors encountered in
+// the first part of the unwind_protect are not completely ignored.
+
+  unwind_protect_int (error_state);
+
+  error_state = 0;
+
+  if (list)
+    list->eval (1);
+
+// We don't want to ignore errors that occur in the cleanup code, so
+// if an error is encountered there, leave error_state alone.
+// Otherwise, set it back to what it was before.
+
+  if (error_state)
+    discard_unwind_protect ();
+  else
+    run_unwind_protect ();
+}
+
+void
+tree_unwind_protect_command::eval (void)
+{
+  add_unwind_protect (do_unwind_protect_cleanup_code, cleanup_code);
+
+  if (unwind_protect_code)
+    unwind_protect_code->eval (1);
+
+  run_unwind_protect ();
+}
+
+void
+tree_unwind_protect_command::print_code (ostream& os)
+{
+  print_code_indent (os);
+
+  os << "unwind_protect";
+
+  print_code_new_line (os);
+
+  if (unwind_protect_code)
+    {
+      increment_indent_level ();
+      unwind_protect_code->print_code (os);
+      decrement_indent_level ();
+    }
+
+  print_code_indent (os);
+
+  os << "cleanup_code";
+
+  print_code_new_line (os);
+
+  if (cleanup_code)
+    {
+      increment_indent_level ();
+      cleanup_code->print_code (os);
+      decrement_indent_level ();
+    }
+
+  print_code_indent (os);
+
+  os << "end_unwind_protect";
+}
+
 // Break.
 
 void
--- a/src/pt-cmd.h
+++ b/src/pt-cmd.h
@@ -39,6 +39,7 @@
 class tree_while_command;
 class tree_for_command;
 class tree_if_command;
+class tree_unwind_protect_command;
 class tree_break_command;
 class tree_continue_command;
 class tree_return_command;
@@ -59,7 +60,7 @@
 class
 tree_global_command : public tree_command
 {
- public:
+public:
   tree_global_command (int l = -1, int c = -1) : tree_command (l, c)
     { init_list = 0; }
 
@@ -82,7 +83,7 @@
 class
 tree_while_command : public tree_command
 {
- public:
+public:
   tree_while_command (int l = -1, int c = -1) : tree_command (l, c)
     {
       expr = 0;
@@ -112,7 +113,7 @@
 
   void print_code (ostream& os);
 
- private:
+private:
   tree_expression *expr;	// Expression to test.
   tree_statement_list *list;	// List of commands to execute.
 };
@@ -122,7 +123,7 @@
 class
 tree_for_command : public tree_command
 {
- public:
+public:
   tree_for_command (int l = -1, int c = -1) : tree_command (l, c)
     {
       id = 0;
@@ -147,7 +148,7 @@
 
   void print_code (ostream& os);
 
- private:
+private:
   void do_for_loop_once (tree_constant *rhs, int& quit);
 
   tree_index_expression *id;	// Identifier to modify.
@@ -160,7 +161,7 @@
 class
 tree_if_command : public tree_command
 {
- public:
+public:
   tree_if_command (int l = -1, int c = -1) : tree_command (l, c)
     { list = 0; }
 
@@ -176,16 +177,48 @@
 
   void print_code (ostream& os);
 
- private:
+private:
   tree_if_command_list *list;
 };
 
+// Simple exception handling.
+
+class
+tree_unwind_protect_command : public tree_command
+{
+public:
+  tree_unwind_protect_command (int l = -1, int c = -1) : tree_command (l, c)
+    {
+      unwind_protect_code = 0;
+      cleanup_code = 0;
+    }
+
+  tree_unwind_protect_command (tree_statement_list *tc,
+			       tree_statement_list *cc,
+			       int l = -1, int c = -1)
+    : tree_command (l, c)
+      {
+	unwind_protect_code = tc;
+	cleanup_code = cc;
+      }
+
+  ~tree_unwind_protect_command (void);
+
+  void eval (void);
+
+  void print_code (ostream& os);
+
+private:
+  tree_statement_list *unwind_protect_code;
+  tree_statement_list *cleanup_code;
+};
+
 // Break.
 
 class
 tree_break_command : public tree_command
 {
- public:
+public:
   tree_break_command (int l = -1, int c = -1) : tree_command (l, c) { }
 
   ~tree_break_command (void) { }
@@ -200,7 +233,7 @@
 class
 tree_continue_command : public tree_command
 {
- public:
+public:
   tree_continue_command (int l = -1, int c = -1) : tree_command (l, c) { }
 
   ~tree_continue_command (void) { }