changeset 2846:52e7c4509983

[project @ 1997-03-26 23:27:35 by jwe]
author jwe
date Wed, 26 Mar 1997 23:29:12 +0000
parents b11fb5e85dc5
children 8b262e771614
files src/ChangeLog src/SLList-misc.cc src/lex.l src/octave.gperf src/parse.y src/pt-cmd.cc src/pt-cmd.h src/pt-fvc.cc src/pt-fvc.h src/pt-misc.cc src/pt-misc.h src/pt-pr-code.cc src/pt-pr-code.h src/pt-walk.h src/symtab.cc src/symtab.h src/variables.cc
diffstat 17 files changed, 493 insertions(+), 250 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Wed Mar 26 23:05:15 1997 +0000
+++ b/src/ChangeLog	Wed Mar 26 23:29:12 1997 +0000
@@ -1,3 +1,40 @@
+Wed Mar 26 17:08:27 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>
+
+	Implement static variable declaration:
+
+	* lex.l (is_keyword): Handle static.
+	* octave.gperf: Likewise.
+	* parse.y (Vwarn_comma_in_declaration): Rename from
+	Vwarn_comma_in_global_decl.
+	Handle new static command.
+	* pt-cmd.h, pt-cmd.cc (class tree_decl_command): New base class
+	for static and global declaration commands.
+	(class tree_global_command): Derive from tree_decl_command.
+	(class tree_static_command): New class, derived from tree_decl_command.
+	* pt-fvc.cc, pt-fvc.h (tree_identifier::mark_as_static): New function.
+	* pt-misc.h, pt-misc.h (class tree_decl_elt): Rename from tree_global.
+	(class tree_decl_init_list): Rename from tree_global_init_list.
+	* pt-pr-code.cc, pt-pr-code.h (tree_print_code::visit_decl_command):
+	Rename from visit_global_command.
+	(tree_print_code::visit_decl_elt): Rename from visit_global.
+	(tree_print_code::visit_decl_init_list): Rename from
+	visit_global_init_list.
+	* pt-walk.h (tree_walker::visit_decl_command): Rename from
+	visit_global_command.
+	(tree_walker::visit_decl_elt): Rename from visit_tree_global.
+	(tree_walker::visit_decl_init_list): Rename from
+	visit_global_init_list.
+	* variables.cc (link_to_global_variable): Trying to make a static
+	variable global is an error.
+	* SLList-misc.cc: Instantiate lists of pointers to tree_decl_elt
+	objects, not tree_global objects.
+	* symtab.h, symtab.cc (symbol_record::tagged_static): New field.
+	(symbol_record::mark_as_static, symbol_record::is_static):
+	New functions.
+	* symtab.cc (symbol_record::init_state): Initialize tagged_static.
+	(symbol_record::clear): Don't clear static variables.
+	* symtab.cc (push_context): Don't do anything for static variables.
+
 Tue Mar 25 17:17:17 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>
 
 	* ov-bool-mat.cc (octave_bool_matrix::is_true): Write guts.
--- a/src/SLList-misc.cc	Wed Mar 26 23:05:15 1997 +0000
+++ b/src/SLList-misc.cc	Wed Mar 26 23:29:12 1997 +0000
@@ -42,8 +42,8 @@
 template class SLList<tree_switch_case *>;
 template class SLNode<tree_switch_case *>;
 
-template class SLList<tree_global *>;
-template class SLNode<tree_global *>;
+template class SLList<tree_decl_elt *>;
+template class SLNode<tree_decl_elt *>;
 
 /*
 ;;; Local Variables: ***
--- a/src/lex.l	Wed Mar 26 23:05:15 1997 +0000
+++ b/src/lex.l	Wed Mar 26 23:29:12 1997 +0000
@@ -967,6 +967,7 @@
 	case global_kw:
 	case otherwise_kw:
 	case return_kw:
+	case static_kw:
 	case unwind_protect_cleanup_kw:
  	  break;
 
--- a/src/octave.gperf	Wed Mar 26 23:05:15 1997 +0000
+++ b/src/octave.gperf	Wed Mar 26 23:29:12 1997 +0000
@@ -26,6 +26,7 @@
   otherwise_kw,
   replot_kw,
   return_kw,
+  static_kw,
   switch_kw,
   try_kw,
   unwind_protect_kw,
@@ -60,6 +61,7 @@
 otherwise, OTHERWISE, otherwise_kw
 replot, PLOT, replot_kw
 return, FUNC_RET, return_kw
+static, STATIC, static_kw
 switch, SWITCH, switch_kw
 try, TRY, try_kw
 unwind_protect, UNWIND, unwind_protect_kw
--- a/src/parse.y	Wed Mar 26 23:05:15 1997 +0000
+++ b/src/parse.y	Wed Mar 26 23:29:12 1997 +0000
@@ -79,7 +79,7 @@
 //
 //   octave> global a, b = 2
 //
-static bool Vwarn_comma_in_global_decl;
+static bool Vwarn_comma_in_declaration;
 
 // If TRUE, generate warning if declared function name disagrees with
 // the name of the file in which it is defined.
@@ -239,12 +239,19 @@
 static tree_index_expression *make_index_expression
 	 (tree_indirect_ref *indir, tree_argument_list *args);
 
+// Make a declaration command.
+static tree_decl_command *make_decl_command
+	(int tok, token *tok_val, tree_decl_init_list *lst);
+
 // Finish building a matrix list.
 static tree_expression *finish_matrix (tree_matrix *m);
 
 // Maybe print a warning.  Duh.
 static void maybe_warn_missing_semi (tree_statement_list *);
 
+// Maybe print a warning.  Duh.
+static void maybe_warn_comma_in_decl (void);
+
 // Set the print flag for a statement based on the separator type.
 static void set_stmt_print_flag (tree_statement_list *, char, bool);
 
@@ -290,9 +297,9 @@
   tree_switch_command *tree_switch_command_type;
   tree_switch_case *tree_switch_case_type;
   tree_switch_case_list *tree_switch_case_list_type;
-  tree_global *tree_global_type;
-  tree_global_init_list *tree_global_init_list_type;
-  tree_global_command *tree_global_command_type;
+  tree_decl_elt *tree_decl_elt_type;
+  tree_decl_init_list *tree_decl_init_list_type;
+  tree_decl_command *tree_decl_command_type;
   tree_statement *tree_statement_type;
   tree_statement_list *tree_statement_list_type;
   tree_plot_command *tree_plot_command_type;
@@ -323,7 +330,7 @@
 %token <tok_val> BREAK CONTINUE FUNC_RET
 %token <tok_val> UNWIND CLEANUP
 %token <tok_val> TRY CATCH
-%token <tok_val> GLOBAL
+%token <tok_val> GLOBAL STATIC
 %token <tok_val> TEXT_ID
 
 // Other tokens.
@@ -356,9 +363,9 @@
 %type <tree_switch_command_type> switch_command
 %type <tree_switch_case_type> switch_case default_case
 %type <tree_switch_case_list_type> case_list1 case_list
-%type <tree_global_type> global_decl2
-%type <tree_global_init_list_type> global_decl1
-%type <tree_global_command_type> global_decl
+%type <tree_decl_elt_type> decl2
+%type <tree_decl_init_list_type> decl1
+%type <tree_decl_command_type> declaration
 %type <tree_statement_type> statement
 %type <tree_statement_list_type> simple_list simple_list1 list list1
 %type <tree_statement_list_type> opt_list input1
@@ -600,46 +607,43 @@
 		  { $$ = maybe_convert_to_ans_assign ($1); }
 		;
 
-global_decl	: GLOBAL global_decl1
+decl1		: decl2
+		  { $$ = new tree_decl_init_list ($1); }
+		| decl1 decl2
 		  {
-		    $$ = new tree_global_command ($2, $1->line (),
-						  $1->column ());
+		    $1->append ($2);
+		    $$ = $1;
 		  }
-		;
-
-global_decl1	: global_decl2
-		  { $$ = new tree_global_init_list ($1); }
-		| global_decl1 optcomma global_decl2
+		| decl1 ',' decl2
 		  {
+		    maybe_warn_comma_in_decl ();
 		    $1->append ($3);
 		    $$ = $1;
 		  }
-
-global_decl2	: identifier
-		  { $$ = new tree_global ($1); }
+		;
+
+decl2		: identifier
+		  { $$ = new tree_decl_elt ($1); }
 		| identifier '=' expression
 		  {
 		    tree_simple_assignment_expression *tmp_ass;
 		    tmp_ass = new tree_simple_assignment_expression
 		      ($1, $3, 0, 0, $2->line (), $2->column ());
-		    $$ = new tree_global (tmp_ass);
+		    $$ = new tree_decl_elt (tmp_ass);
 		  }
 		;
 
-optcomma	: // empty
-		| ','
-		  {
-		    if (Vwarn_comma_in_global_decl)
-		      warning ("comma in global declaration not\
- interpreted as a command separator");
-		  }
+declaration	: GLOBAL decl1
+		  { $$ = make_decl_command (GLOBAL, $1, $2); }
+		| STATIC decl1
+		  { $$ = make_decl_command (STATIC, $1, $2); }
 		;
 
 command		: plot_command
 		  { $$ = $1; }
 		| func_def
 		  { $$ = $1; }
-		| global_decl
+		| declaration
 		  { $$ = $1; }
 		| switch_command
 		  { $$ = $1; }
@@ -2246,6 +2250,8 @@
   return fcn->define_ret_list (ret_list);
 }
 
+// Make an index expression.
+
 static tree_index_expression *
 make_index_expression (tree_indirect_ref *indir, tree_argument_list *args)
 {
@@ -2266,6 +2272,43 @@
   return retval;
 }
 
+// Make a declaration command.
+
+static tree_decl_command *
+make_decl_command (int tok, token *tok_val, tree_decl_init_list *lst)
+{
+  tree_decl_command *retval = 0;
+
+  int l = tok_val->line ();
+  int c = tok_val->column ();
+
+  switch (tok)
+    {
+    case GLOBAL:
+      retval = new tree_global_command (lst, l, c);
+      break;
+
+    case STATIC:
+      if (lexer_flags.defining_func)
+	retval = new tree_static_command (lst, l, c);
+      else
+	{
+	  if (reading_script_file)
+	    warning ("ignoring static declaration near line %d of file `%s'",
+		     l, curr_fcn_file_full_name.c_str ());
+	  else
+	    warning ("ignoring static declaration near line %d", l);
+	}
+      break;
+
+    default:
+      panic_impossible ();
+      break;
+    }
+
+  return retval;
+}
+
 // Finish building a matrix list.
 
 static tree_expression *
@@ -2350,6 +2393,19 @@
     }
 }
 
+static void
+maybe_warn_comma_in_decl (void)
+{
+  if (Vwarn_comma_in_declaration)\
+    {
+      warning ("comma in declaration not interpreted as a command separator"); 
+
+      if (reading_fcn_file || reading_script_file)
+	warning ("near line %d of file `%s'", input_line_number,
+		 curr_fcn_file_full_name.c_str ());
+    }
+}
+
 static int
 warn_assign_as_truth_value (void)
 {
@@ -2360,9 +2416,9 @@
 }
 
 static int
-warn_comma_in_global_decl (void)
+warn_comma_in_declaration (void)
 {
-  Vwarn_comma_in_global_decl = check_preference ("warn_comma_in_global_decl");
+  Vwarn_comma_in_declaration = check_preference ("warn_comma_in_declaration");
 
   return 0;
 }
@@ -2398,8 +2454,8 @@
   DEFVAR (warn_assign_as_truth_value, 1.0, 0, warn_assign_as_truth_value,
     "produce warning for assignments used as truth values");
 
-  DEFVAR (warn_comma_in_global_decl, 1.0, 0, warn_comma_in_global_decl,
-    "produce warning for commas in global declarations");
+  DEFVAR (warn_comma_in_declaration, 1.0, 0, warn_comma_in_declaration,
+    "produce warning for commas in declaration statements");
 
   DEFVAR (warn_function_name_clash, 1.0, 0, warn_function_name_clash,
     "produce warning if function name conflicts with file name");
--- a/src/pt-cmd.cc	Wed Mar 26 23:05:15 1997 +0000
+++ b/src/pt-cmd.cc	Wed Mar 26 23:29:12 1997 +0000
@@ -71,28 +71,107 @@
   return quit;
 }
 
+// Base class for declaration commands (global, static).
+
+tree_decl_command::~tree_decl_command (void)
+{
+  delete init_list;
+}
+
+void
+tree_decl_command::accept (tree_walker& tw)
+{
+  tw.visit_decl_command (*this);
+}
+
 // Global.
 
-tree_global_command::~tree_global_command (void)
+static void
+do_global_init (tree_decl_elt& elt, bool skip_initializer)
 {
-  delete init_list;
+  tree_identifier *id = elt.ident ();
+
+  if (id)
+    id->link_to_global ();
+  else
+    {
+      tree_simple_assignment_expression *expr = elt.assign_expr ();
+
+      if (expr)
+	{
+	  if (expr->left_hand_side_is_identifier_only ()
+	      && (id = expr->left_hand_side_id ()))
+	    {
+	      id->link_to_global ();
+
+	      if (! (skip_initializer || error_state))
+		expr->eval (false);
+	    }
+	  else
+	    error ("global: unable to make structure elements global");
+	}
+    }
 }
 
 void
 tree_global_command::eval (void)
 {
   if (init_list)
-    init_list->eval ();
+    {
+      init_list->eval (do_global_init, initialized);
+
+      initialized = true;
+    }
 
   if (error_state > 0)
     ::error ("evaluating global command near line %d, column %d",
 	     line (), column ());
 }
 
+// Static.
+
+static void
+do_static_init (tree_decl_elt& elt, bool)
+{
+  tree_identifier *id = elt.ident ();
+
+  if (id)
+    id->mark_as_static ();
+  else
+    {
+      tree_simple_assignment_expression *expr = elt.assign_expr ();
+
+      if (expr)
+	{
+	  if (expr->left_hand_side_is_identifier_only ()
+	      && (id = expr->left_hand_side_id ()))
+	    {
+	      id->mark_as_static ();
+
+	      if (! error_state)
+		expr->eval (false);
+	    }
+	  else
+	    error ("global: unable to make structure elements global");
+	}
+    }
+}
+
 void
-tree_global_command::accept (tree_walker& tw)
+tree_static_command::eval (void)
 {
-  tw.visit_global_command (*this);
+  // Static variables only need to be marked and initialized once.
+
+  if (init_list && ! initialized)
+    {
+      init_list->eval (do_static_init, initialized);
+
+      initialized = true;
+
+      if (error_state > 0)
+	::error ("evaluating static command near line %d, column %d",
+		 line (), column ());
+    }
 }
 
 // While.
--- a/src/pt-cmd.h	Wed Mar 26 23:05:15 1997 +0000
+++ b/src/pt-cmd.h	Wed Mar 26 23:29:12 1997 +0000
@@ -32,7 +32,7 @@
 class octave_value_list;
 
 class tree_statement_list;
-class tree_global_init_list;
+class tree_decl_init_list;
 class tree_if_command_list;
 class tree_switch_case_list;
 class tree_expression;
@@ -43,7 +43,9 @@
 class symbol_record;
 
 class tree_command;
+class tree_decl_command;
 class tree_global_command;
+class tree_static_command;
 class tree_while_command;
 class tree_for_command;
 class tree_if_command;
@@ -75,30 +77,74 @@
   virtual void eval (void) = 0;
 };
 
+// Base class for declaration commands -- global, static, etc.
+
 class
-tree_global_command : public tree_command
+tree_decl_command : public tree_command
+{
+public:
+
+  tree_decl_command (const string& n, int l = -1, int c = -1)
+    : tree_command (l, c), cmd_name (n), initialized (false), init_list (0) { }
+
+  tree_decl_command (const string& n, tree_decl_init_list *t,
+		     int l = -1, int c = -1)
+    : tree_command (l, c), cmd_name (n), initialized (false), init_list (t) { }
+
+  ~tree_decl_command (void);
+
+  tree_decl_init_list *initializer_list (void) { return init_list; }
+
+  void accept (tree_walker& tw);
+
+  string name (void) { return cmd_name; }
+
+protected:
+
+  // The name of this command -- global, static, etc.
+  string cmd_name;
+
+  // TRUE if this command has been evaluated.
+  bool initialized;
+
+  // The list of variables or initializers in this declaration command.
+  tree_decl_init_list *init_list;
+};
+
+// Global.
+
+class
+tree_global_command : public tree_decl_command
 {
 public:
 
   tree_global_command (int l = -1, int c = -1)
-    : tree_command (l, c), init_list (0) { }
+    : tree_decl_command ("global", l, c) { }
 
-  tree_global_command (tree_global_init_list *t, int l = -1, int c = -1)
-    : tree_command (l, c), init_list (t) { }
+  tree_global_command (tree_decl_init_list *t, int l = -1, int c = -1)
+    : tree_decl_command ("global", t, l, c) { }
 
-  ~tree_global_command (void);
+  ~tree_global_command (void) { }
 
   void eval (void);
+};
 
-  tree_global_init_list *initializer_list (void) { return init_list; }
+// Static.
 
-  void accept (tree_walker& tw);
+class
+tree_static_command : public tree_decl_command
+{
+public:
 
-private:
+  tree_static_command (int l = -1, int c = -1)
+    : tree_decl_command ("static", l, c) { }
 
-  // The list of global variables or initializers in this global
-  // command.
-  tree_global_init_list *init_list;
+  tree_static_command (tree_decl_init_list *t, int l = -1, int c = -1)
+    : tree_decl_command ("static", t, l, c) { }
+
+  ~tree_static_command (void) { }
+
+  void eval (void);
 };
 
 // While.
--- a/src/pt-fvc.cc	Wed Mar 26 23:05:15 1997 +0000
+++ b/src/pt-fvc.cc	Wed Mar 26 23:29:12 1997 +0000
@@ -295,6 +295,13 @@
 }
 
 void
+tree_identifier::mark_as_static (void)
+{
+  if (sym)
+    sym->mark_as_static ();
+}
+
+void
 tree_identifier::mark_as_formal_parameter (void)
 {
   if (sym)
--- a/src/pt-fvc.h	Wed Mar 26 23:05:15 1997 +0000
+++ b/src/pt-fvc.h	Wed Mar 26 23:29:12 1997 +0000
@@ -81,6 +81,8 @@
 
   void link_to_global (void);
 
+  void mark_as_static (void);
+
   void mark_as_formal_parameter (void);
 
   void mark_for_possible_ans_assign (void)
--- a/src/pt-misc.cc	Wed Mar 26 23:05:15 1997 +0000
+++ b/src/pt-misc.cc	Wed Mar 26 23:29:12 1997 +0000
@@ -428,58 +428,38 @@
   tw.visit_return_list (*this);
 }
 
-// Global.
+// Declarations (global, static, etc.).
 
-tree_global::~tree_global (void)
+tree_decl_elt::~tree_decl_elt (void)
 {
   delete id;
   delete ass_expr;
 }
 
 void
-tree_global::eval (void)
+tree_decl_elt::accept (tree_walker& tw)
 {
-  if (id)
-    {
-      id->link_to_global ();
-    }
-  else if (ass_expr)
+  tw.visit_decl_elt (*this);
+}
+
+// Initializer lists for declaration statements.
+
+void
+tree_decl_init_list::eval (tree_decl_elt::eval_fcn f, bool skip_init)
+{
+  for (Pix p = first (); p != 0; next (p))
     {
-      tree_identifier *idnt = 0;
+      f (*(this->operator () (p)), skip_init);
 
-      if (ass_expr->left_hand_side_is_identifier_only ()
-	  && (idnt = ass_expr->left_hand_side_id ()))
-	{
-	  idnt->link_to_global ();
-	  ass_expr->eval (false);
-	}
-      else
-	error ("global: unable to make individual structure elements global");
+      if (error_state)
+	break;
     }
 }
 
 void
-tree_global::accept (tree_walker& tw)
-{
-  tw.visit_global (*this);
-}
-
-// Global initializer lists.
-
-void
-tree_global_init_list::eval (void)
+tree_decl_init_list::accept (tree_walker& tw)
 {
-  for (Pix p = first (); p != 0; next (p))
-    {
-      tree_global *t = this->operator () (p);
-      t->eval ();
-    }
-}
-
-void
-tree_global_init_list::accept (tree_walker& tw)
-{
-  tw.visit_global_init_list (*this);
+  tw.visit_decl_init_list (*this);
 }
 
 // If.
--- a/src/pt-misc.h	Wed Mar 26 23:05:15 1997 +0000
+++ b/src/pt-misc.h	Wed Mar 26 23:29:12 1997 +0000
@@ -45,8 +45,8 @@
 class tree_parameter_list;
 class tree_return_list;
 class tree_va_return_list;
-class tree_global;
-class tree_global_init_list;
+class tree_decl_elt;
+class tree_decl_init_list;
 class tree_if_clause;
 class tree_if_command_list;
 class tree_switch_case;
@@ -254,23 +254,25 @@
   ~tree_va_return_list (void) { }
 };
 
-// List of expressions that make up a global statement.
+// List of expressions that make up a declaration statement.
 
 class
-tree_global
+tree_decl_elt
 {
 public:
 
-  tree_global (void)
+  typedef void (*eval_fcn) (tree_decl_elt &, bool);
+
+  tree_decl_elt (void)
     : id (0), ass_expr (0) { }
 
-  tree_global (tree_identifier *i)
+  tree_decl_elt (tree_identifier *i)
     : id (i), ass_expr (0) { }
 
-  tree_global (tree_simple_assignment_expression *ass)
+  tree_decl_elt (tree_simple_assignment_expression *ass)
     : id (0), ass_expr (ass) { }
 
-  ~tree_global (void);
+  ~tree_decl_elt (void);
 
   void eval (void);
 
@@ -284,7 +286,7 @@
 
   // Only one of id or ass_expr can be valid at once.
 
-  // An identifier to make global.
+  // An identifier to tag with the declared property.
   tree_identifier *id;
 
   // An assignemnt expression.  Valid only if the left hand side of
@@ -293,26 +295,26 @@
 };
 
 class
-tree_global_init_list : public SLList<tree_global *>
+tree_decl_init_list : public SLList<tree_decl_elt *>
 {
 public:
 
-  tree_global_init_list (void)
-    : SLList<tree_global *> () { }
+  tree_decl_init_list (void)
+    : SLList<tree_decl_elt *> () { }
 
-  tree_global_init_list (tree_global *t)
-    : SLList<tree_global *> () { append (t); }
+  tree_decl_init_list (tree_decl_elt *t)
+    : SLList<tree_decl_elt *> () { append (t); }
 
-  ~tree_global_init_list (void)
+  ~tree_decl_init_list (void)
     {
       while (! empty ())
 	{
-	  tree_global *t = remove_front ();
+	  tree_decl_elt *t = remove_front ();
 	  delete t;
 	}
     }
 
-  void eval (void);
+  void eval (tree_decl_elt::eval_fcn, bool);
 
   void accept (tree_walker& tw);
 };
--- a/src/pt-pr-code.cc	Wed Mar 26 23:05:15 1997 +0000
+++ b/src/pt-pr-code.cc	Wed Mar 26 23:29:12 1997 +0000
@@ -142,6 +142,54 @@
 }
 
 void
+tree_print_code::visit_decl_command (tree_decl_command& cmd)
+{
+  indent ();
+
+  os << cmd.name () << " ";
+
+  tree_decl_init_list *init_list = cmd.initializer_list ();
+
+  if (init_list)
+    init_list->accept (*this);
+}
+
+void
+tree_print_code::visit_decl_elt (tree_decl_elt& cmd)
+{
+  tree_identifier *id = cmd.ident ();
+
+  if (id)
+    id->accept (*this);
+
+  tree_simple_assignment_expression *ass_expr = cmd.assign_expr ();
+
+  if (ass_expr)
+    ass_expr->accept (*this);
+}
+
+void
+tree_print_code::visit_decl_init_list (tree_decl_init_list& lst)
+{
+  Pix p = lst.first ();
+
+  while (p)
+    {
+      tree_decl_elt *elt = lst (p);
+
+      lst.next (p);
+
+      if (elt)
+	{
+	  elt->accept (*this);
+
+	  if (p)
+	    os << ", ";
+	}
+    }
+}
+
+void
 tree_print_code::visit_for_command (tree_for_command& cmd)
 {
   indent ();
@@ -278,54 +326,6 @@
 }
 
 void
-tree_print_code::visit_global (tree_global& cmd)
-{
-  tree_identifier *id = cmd.ident ();
-
-  if (id)
-    id->accept (*this);
-
-  tree_simple_assignment_expression *ass_expr = cmd.assign_expr ();
-
-  if (ass_expr)
-    ass_expr->accept (*this);
-}
-
-void
-tree_print_code::visit_global_command (tree_global_command& cmd)
-{
-  indent ();
-
-  os << "global ";
-
-  tree_global_init_list *init_list = cmd.initializer_list ();
-
-  if (init_list)
-    init_list->accept (*this);
-}
-
-void
-tree_print_code::visit_global_init_list (tree_global_init_list& lst)
-{
-  Pix p = lst.first ();
-
-  while (p)
-    {
-      tree_global *elt = lst (p);
-
-      lst.next (p);
-
-      if (elt)
-	{
-	  elt->accept (*this);
-
-	  if (p)
-	    os << ", ";
-	}
-    }
-}
-
-void
 tree_print_code::visit_identifier (tree_identifier& id)
 {
   indent ();
@@ -413,77 +413,6 @@
 }
 
 void
-tree_print_code::visit_switch_case (tree_switch_case& cs)
-{
-  indent ();
-
-  if (cs.is_default_case ())
-    os << "otherwise";
-  else
-    os << "case ";
-
-  tree_expression *label = cs.case_label ();
-
-  if (label)
-    label->accept (*this);
-
-  newline ();
-
-  increment_indent_level ();
-
-  tree_statement_list *list = cs.commands ();
-
-  if (list)
-    {
-      list->accept (*this);
-
-      decrement_indent_level ();
-    }
-}
-
-void
-tree_print_code::visit_switch_case_list (tree_switch_case_list& lst)
-{
-  Pix p = lst.first ();
-
-  while (p)
-    {
-      tree_switch_case *elt = lst (p);
-
-      if (elt)
-	elt->accept (*this);
-
-      lst.next (p);
-    }
-}
-
-void
-tree_print_code::visit_switch_command (tree_switch_command& cmd)
-{
-  indent ();
-
-  os << "switch ";
-
-  tree_expression *expr = cmd.switch_value ();
-
-  if (expr)
-    expr->accept (*this);
-
-  newline ();
-
-  increment_indent_level ();
-
-  tree_switch_case_list *list = cmd.case_list ();
-
-  if (list)
-    list->accept (*this);
-
-  indent ();
-
-  os << "endswitch";
-}
-
-void
 tree_print_code::visit_index_expression (tree_index_expression& expr)
 {
   indent ();
@@ -1005,6 +934,77 @@
 }
 
 void
+tree_print_code::visit_switch_case (tree_switch_case& cs)
+{
+  indent ();
+
+  if (cs.is_default_case ())
+    os << "otherwise";
+  else
+    os << "case ";
+
+  tree_expression *label = cs.case_label ();
+
+  if (label)
+    label->accept (*this);
+
+  newline ();
+
+  increment_indent_level ();
+
+  tree_statement_list *list = cs.commands ();
+
+  if (list)
+    {
+      list->accept (*this);
+
+      decrement_indent_level ();
+    }
+}
+
+void
+tree_print_code::visit_switch_case_list (tree_switch_case_list& lst)
+{
+  Pix p = lst.first ();
+
+  while (p)
+    {
+      tree_switch_case *elt = lst (p);
+
+      if (elt)
+	elt->accept (*this);
+
+      lst.next (p);
+    }
+}
+
+void
+tree_print_code::visit_switch_command (tree_switch_command& cmd)
+{
+  indent ();
+
+  os << "switch ";
+
+  tree_expression *expr = cmd.switch_value ();
+
+  if (expr)
+    expr->accept (*this);
+
+  newline ();
+
+  increment_indent_level ();
+
+  tree_switch_case_list *list = cmd.case_list ();
+
+  if (list)
+    list->accept (*this);
+
+  indent ();
+
+  os << "endswitch";
+}
+
+void
 tree_print_code::visit_try_catch_command (tree_try_catch_command& cmd)
 {
   indent ();
--- a/src/pt-pr-code.h	Wed Mar 26 23:05:15 1997 +0000
+++ b/src/pt-pr-code.h	Wed Mar 26 23:29:12 1997 +0000
@@ -56,6 +56,12 @@
 
   void visit_continue_command (tree_continue_command&);
 
+  void visit_decl_command (tree_decl_command&);
+
+  void visit_decl_elt (tree_decl_elt&);
+
+  void visit_decl_init_list (tree_decl_init_list&);
+
   void visit_for_command (tree_for_command&);
 
   void visit_function (tree_function&);
@@ -64,12 +70,6 @@
 
   void visit_function_trailer (tree_function&);
 
-  void visit_global (tree_global&);
-
-  void visit_global_command (tree_global_command&);
-
-  void visit_global_init_list (tree_global_init_list&);
-
   void visit_identifier (tree_identifier&);
 
   void visit_if_clause (tree_if_clause&);
@@ -78,12 +78,6 @@
 
   void visit_if_command_list (tree_if_command_list&);
 
-  void visit_switch_case (tree_switch_case&);
-
-  void visit_switch_case_list (tree_switch_case_list&);
-
-  void visit_switch_command (tree_switch_command&);
-
   void visit_index_expression (tree_index_expression&);
 
   void visit_indirect_ref (tree_indirect_ref&);
@@ -130,6 +124,12 @@
 
   void visit_subplot_using (subplot_using&);
 
+  void visit_switch_case (tree_switch_case&);
+
+  void visit_switch_case_list (tree_switch_case_list&);
+
+  void visit_switch_command (tree_switch_command&);
+
   void visit_try_catch_command (tree_try_catch_command&);
 
   void visit_unary_expression (tree_unary_expression&);
--- a/src/pt-walk.h	Wed Mar 26 23:05:15 1997 +0000
+++ b/src/pt-walk.h	Wed Mar 26 23:29:12 1997 +0000
@@ -57,21 +57,21 @@
   visit_continue_command (tree_continue_command&) = 0;
 
   virtual void
+  visit_decl_command (tree_decl_command&) = 0;
+
+  virtual void
+  visit_decl_elt (tree_decl_elt&) = 0;
+
+  virtual void
+  visit_decl_init_list (tree_decl_init_list&) = 0;
+
+  virtual void
   visit_for_command (tree_for_command&) = 0;
 
   virtual void
   visit_function (tree_function&) = 0;
 
   virtual void
-  visit_global (tree_global&) = 0;
-
-  virtual void
-  visit_global_command (tree_global_command&) = 0;
-
-  virtual void
-  visit_global_init_list (tree_global_init_list&) = 0;
-
-  virtual void
   visit_identifier (tree_identifier&) = 0;
 
   virtual void
--- a/src/symtab.cc	Wed Mar 26 23:05:15 1997 +0000
+++ b/src/symtab.cc	Wed Mar 26 23:29:12 1997 +0000
@@ -237,6 +237,7 @@
 {
   formal_param = 0;
   linked_to_global = 0;
+  tagged_static = 0;
   sv_fcn = 0;
   definition = 0;
   next_elem = 0;
@@ -547,7 +548,7 @@
       definition = 0;
       linked_to_global = 0;
     }
-  else
+  else if (! tagged_static)
     {
       symbol_def *old_def = pop_def ();
       count = maybe_delete (old_def);
@@ -597,6 +598,23 @@
   return linked_to_global;
 }
 
+void
+symbol_record::mark_as_static (void)
+{
+  if (is_linked_to_global ())
+    error ("can't make global variable static");
+  else if (is_formal_parameter ())
+    error ("can't make formal parameter static");
+  else
+    tagged_static = 1;
+}
+
+int
+symbol_record::is_static (void) const
+{
+  return tagged_static;
+}
+
 octave_value
 symbol_record::variable_value (void) const
 {
@@ -649,11 +667,14 @@
 void
 symbol_record::push_context (void)
 {
-  context.push (definition);
-  definition = 0;
+  if (! is_static ())
+    {
+      context.push (definition);
+      definition = 0;
 
-  global_link_context.push (static_cast<unsigned> (linked_to_global));
-  linked_to_global = 0;
+      global_link_context.push (static_cast<unsigned> (linked_to_global));
+      linked_to_global = 0;
+    }
 }
 
 void
--- a/src/symtab.h	Wed Mar 26 23:05:15 1997 +0000
+++ b/src/symtab.h	Wed Mar 26 23:29:12 1997 +0000
@@ -180,6 +180,9 @@
   void mark_as_linked_to_global (void);
   int is_linked_to_global (void) const;
 
+  void mark_as_static (void);
+  int is_static (void) const;
+
   octave_value variable_value (void) const;
   octave_value& variable_reference (void);
 
@@ -194,6 +197,7 @@
 
   unsigned formal_param : 1;
   unsigned linked_to_global : 1;
+  unsigned tagged_static : 1;
 
   string nm;
   sv_Function sv_fcn;
--- a/src/variables.cc	Wed Mar 26 23:05:15 1997 +0000
+++ b/src/variables.cc	Wed Mar 26 23:29:12 1997 +0000
@@ -956,6 +956,12 @@
       return;
     }
 
+  if (sr->is_static ())
+    {
+      error ("can't make static variable `%s' global", nm.c_str ());
+      return;
+    }
+
   // There must be a better way to do this.   XXX FIXME XXX
 
   if (sr->is_variable ())