changeset 16205:a8f9eb92fa6e classdef

maint: periodic merge of default to classdef
author John W. Eaton <jwe@octave.org>
date Wed, 06 Mar 2013 16:43:33 -0500
parents 0259254a3ccc (current diff) 127cccb037bf (diff)
children 3449bf257514
files libinterp/Makefile.am libinterp/octave.cc libinterp/parse-tree/lex.h libinterp/parse-tree/lex.ll libinterp/parse-tree/module.mk libinterp/parse-tree/oct-parse.in.yy libinterp/parse-tree/oct-parse.yy libinterp/parse-tree/parse.h libinterp/parse-tree/pt-check.cc libinterp/parse-tree/pt-check.h src/Makefile.am test/classes/classes.tst
diffstat 59 files changed, 6725 insertions(+), 5817 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Thu Feb 28 02:04:24 2013 -0500
+++ b/.hgtags	Wed Mar 06 16:43:33 2013 -0500
@@ -75,3 +75,4 @@
 0000000000000000000000000000000000000000 ss-3-7-2
 23a7661e529ae9bfc91693618f8c314c31f695ca ss-3-7-2
 cc5a7d1233f3acea85648baeb754fc0e8f225225 rc-3-6-4-2
+b29b10fbb7448cdfe29322446e1a589e7fe1a40a release-3-6-4
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CITATION	Wed Mar 06 16:43:33 2013 -0500
@@ -0,0 +1,20 @@
+To cite GNU Octave in publications use:
+
+  John W. Eaton, David Bateman, and Søren Hauberg (2009).  GNU Octave version
+  3.0.1 manual: a high-level interactive language for numerical computations.
+  CreateSpace Independent Publishing Platform.  ISBN 1441413006,
+  URL http://www.gnu.org/software/octave/doc/interpreter/
+
+A BibTeX entry for LaTeX users is:
+
+  @book{,
+    author    = {John W. Eaton and David Bateman and S\oren Hauberg},
+    title     = {{GNU Octave} version 3.0.1 manual: a high-level interactive language for numerical computations},
+    publisher = {CreateSpace Independent Publishing Platform},
+    year      = {2009},
+    note      = {{ISBN} 1441413006},
+    url       = {http://www.gnu.org/software/octave/doc/interpreter},
+  }
+
+We have invested a lot of time and effort in creating GNU Octave, please cite it
+when using it.  See also `citation pkgname' for citing Octave packages.
--- a/Makefile.am	Thu Feb 28 02:04:24 2013 -0500
+++ b/Makefile.am	Wed Mar 06 16:43:33 2013 -0500
@@ -37,6 +37,7 @@
   INSTALL.OCTAVE \
   NEWS \
   README \
+  CITATION \
   bootstrap \
   bootstrap.conf \
   build-aux/find-files-with-tests.sh \
@@ -132,7 +133,9 @@
 	mv $@.t $@
 .PHONY: ChangeLog
 
-octetc_DATA = NEWS
+octetc_DATA = \
+  NEWS \
+  CITATION
 
 DIRS_TO_MAKE = \
   $(localfcnfiledir) \
--- a/NEWS	Thu Feb 28 02:04:24 2013 -0500
+++ b/NEWS	Wed Mar 06 16:43:33 2013 -0500
@@ -177,6 +177,9 @@
       CC_VERSION  (now GCC_VERSION)
       CXX_VERSION (now GXX_VERSION)
 
+ ** A citation command has been added to display information on how to
+    cite Octave and packages in publications.  The package system will
+    look for and install CITATION files from packages.
 
 Summary of important user-visible changes for version 3.6:
 ---------------------------------------------------------
--- a/bootstrap.conf	Thu Feb 28 02:04:24 2013 -0500
+++ b/bootstrap.conf	Wed Mar 06 16:43:33 2013 -0500
@@ -156,7 +156,7 @@
   ## with building the rest of Octave, and INSTALL, which is linked from
   ## gnulib/doc/INSTALL by the bootstrap script.
 
-  for f in NEWS README COPYING; do
+  for f in NEWS README COPYING CITATION; do
     if ! test -f $f; then
       echo "required file $f is missing" 2>&1
       exit 1
--- a/build-aux/common.mk	Thu Feb 28 02:04:24 2013 -0500
+++ b/build-aux/common.mk	Wed Mar 06 16:43:33 2013 -0500
@@ -44,6 +44,7 @@
 
 YACC = @YACC@
 AM_YFLAGS = -dv
+BISON_PUSH_PULL_DECL_STYLE = @BISON_PUSH_PULL_DECL_STYLE@
 
 GPERF = @GPERF@
 
@@ -121,7 +122,6 @@
 # endif
 
 DEFS = @DEFS@
-UGLY_DEFS = @UGLY_DEFS@
 
 # C++ compiler flags.
 
@@ -475,9 +475,8 @@
 fi
 endef
 
-# Yes, the second sed command near the end is needed, to avoid limits
-# in command lengths for some versions of sed.  UGLY_DEFS is often
-# quite large, so it makes sense to split this command there.
+## To avoid shell command line limits, break the replacement patterns
+## into two roughly equal sized parts.
 
 define do_subst_config_vals
 echo "making $@ from $<"
@@ -529,6 +528,7 @@
   -e "s|%OCTAVE_CONF_CXXPICFLAG%|\"${CXXPICFLAG}\"|" \
   -e "s|%OCTAVE_CONF_CXX_VERSION%|\"${CXX_VERSION}\"|" \
   -e "s|%OCTAVE_CONF_DEFAULT_PAGER%|\"${DEFAULT_PAGER}\"|" \
+  -e "s|%OCTAVE_CONF_DEFS%|\"${DEFS}\"|" \
   -e "s|%OCTAVE_CONF_DEPEND_FLAGS%|\"${DEPEND_FLAGS}\"|" \
   -e "s|%OCTAVE_CONF_DEPEND_EXTRA_SED_PATTERN%|\"${DEPEND_EXTRA_SED_PATTERN}\"|" \
   -e "s|%OCTAVE_CONF_DL_LD%|\"${DL_LD}\"|" \
@@ -559,8 +559,8 @@
   -e "s|%OCTAVE_CONF_GNUPLOT%|\"${GNUPLOT}\"|" \
   -e "s|%OCTAVE_CONF_GRAPHICS_CFLAGS%|\"${GRAPHICS_CFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_GRAPHICS_LIBS%|\"${GRAPHICS_LIBS}\"|" \
-  -e "s|%OCTAVE_CONF_HDF5_CPPFLAGS%|\"${HDF5_CPPFLAGS}\"|" \
-  -e "s|%OCTAVE_CONF_HDF5_LDFLAGS%|\"${HDF5_LDFLAGS}\"|" \
+  -e "s|%OCTAVE_CONF_HDF5_CPPFLAGS%|\"${HDF5_CPPFLAGS}\"|" | \
+  $(SED) -e "s|%OCTAVE_CONF_HDF5_LDFLAGS%|\"${HDF5_LDFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_HDF5_LIBS%|\"${HDF5_LIBS}\"|" \
   -e "s|%OCTAVE_CONF_INCLUDEDIR%|\"${includedir}\"|" \
   -e "s|%OCTAVE_CONF_LAPACK_LIBS%|\"${LAPACK_LIBS}\"|" \
@@ -624,7 +624,6 @@
   -e "s|%OCTAVE_CONF_SONAME_FLAGS%|\"${SONAME_FLAGS}\"|" \
   -e "s|%OCTAVE_CONF_STATIC_LIBS%|\"${STATIC_LIBS}\"|" \
   -e "s|%OCTAVE_CONF_TERM_LIBS%|\"${TERM_LIBS}\"|" \
-  -e "s|%OCTAVE_CONF_UGLY_DEFS%|\"${UGLY_DEFS}\"|" \
   -e "s|%OCTAVE_CONF_UMFPACK_CPPFLAGS%|\"${UMFPACK_CPPFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_UMFPACK_LDFLAGS%|\"${UMFPACK_LDFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_UMFPACK_LIBS%|\"${UMFPACK_LIBS}\"|" \
@@ -641,8 +640,7 @@
   -e "s|%OCTAVE_CONF_Z_CPPFLAGS%|\"${Z_CPPFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_Z_LDFLAGS%|\"${Z_LDFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_Z_LIBS%|\"${Z_LIBS}\"|" \
-  -e "s|%OCTAVE_CONF_config_opts%|\"${config_opts}\"|" | \
-  $(SED)  -e "s|%OCTAVE_CONF_DEFS%|\"${UGLY_DEFS}\"|" > $@-t
+  -e "s|%OCTAVE_CONF_config_opts%|\"${config_opts}\"|" > $@-t
 $(simple_move_if_change_rule)
 endef
 
--- a/configure.ac	Thu Feb 28 02:04:24 2013 -0500
+++ b/configure.ac	Wed Mar 06 16:43:33 2013 -0500
@@ -190,6 +190,17 @@
   AC_DEFINE(BOUNDS_CHECKING, 1, [Define to 1 to use internal bounds checking.])
 fi
 
+### Enable experimental push parser.
+
+OCTAVE_USE_PUSH_PARSER=no
+AC_ARG_ENABLE([push-parser],
+  [AS_HELP_STRING([--enable-push-parser],
+    [enable experimental push parser])],
+  [if test "$enableval" = yes; then OCTAVE_USE_PUSH_PARSER=yes; fi], [])
+if test $OCTAVE_USE_PUSH_PARSER = yes; then
+  AC_DEFINE(OCTAVE_USE_PUSH_PARSER, 1, [Define to 1 to use experimental push parser.])
+fi
+
 ### Use Octave's built-in memory allocator rather than straightforward malloc.
 ### Disabled by default.
 
@@ -2834,18 +2845,9 @@
 ### Make all AC_DEFINES available to testif feature of test.m function.
 ### This must reside at the bottom of configure.ac after all AC_DEFINES
 ### have been made.
-### Use UGLY_DEFS to hold all the -D options.  These are ultimately placed
-### in the DEFS field of the struct returned by octave_config_info, which
-### is used by test.m.
 
 AC_OUTPUT_MAKE_DEFS
 
-## We have to insert extra levels of backslash quoting here so that
-## the right thing ends up in oct-conf.h.
-UGLY_DEFS=`echo $DEFS | $SED 's,\\",\\\\\\\\\\\\\\\\\\",g'`
-AC_MSG_NOTICE([defining UGLY_DEFS to be $UGLY_DEFS])
-AC_SUBST(UGLY_DEFS)
-
 ### Do the substitutions in all the Makefiles.
 
 AC_SUBST(ac_config_files)
@@ -2974,6 +2976,7 @@
   Build Java interface:               $build_java
   Do internal array bounds checking:  $BOUNDS_CHECKING
   Use octave_allocator:               $USE_OCTAVE_ALLOCATOR
+  Use push parser:                    $OCTAVE_USE_PUSH_PARSER
   Build static libraries:             $STATIC_LIBS
   Build shared libraries:             $SHARED_LIBS
   Dynamic Linking:                    $ENABLE_DYNAMIC_LINKING $DL_API_MSG
--- a/doc/interpreter/find-docstring-files.sh	Thu Feb 28 02:04:24 2013 -0500
+++ b/doc/interpreter/find-docstring-files.sh	Wed Mar 06 16:43:33 2013 -0500
@@ -5,7 +5,7 @@
   exit 1
 fi
 
-## if there is a file in teh build directory tree, assume it is
+## if there is a file in the build directory tree, assume it is
 ## the file we are looking for.  Otherwise, get the one from the
 ## source tree.
 
--- a/doc/interpreter/geometryimages.m	Thu Feb 28 02:04:24 2013 -0500
+++ b/doc/interpreter/geometryimages.m	Wed Mar 06 16:43:33 2013 -0500
@@ -29,7 +29,7 @@
     d_typ = cstrcat ("-d", typ);
   endif
 
-  if (isempty (findstr (octave_config_info ("DEFS"), "HAVE_QHULL"))
+  if (! __have_feature__ ("QHULL")
       && (strcmp (nm, "voronoi") || strcmp (nm, "griddata")
           || strcmp (nm, "convhull") || strcmp (nm, "delaunay")
           || strcmp (nm, "triplot")))
--- a/doc/interpreter/package.txi	Thu Feb 28 02:04:24 2013 -0500
+++ b/doc/interpreter/package.txi	Wed Mar 06 16:43:33 2013 -0500
@@ -182,6 +182,11 @@
 following files:
 
 @table @code
+@item package/CITATION
+This is am optional file describing instructions on how to cite
+the package for publication.  It will be displayed verbatim by the
+function @code{citation}.
+
 @item package/COPYING
 This is a required file containing the license of the package.  No
 restrictions is made on the license in general.  If however the
--- a/doc/interpreter/sparseimages.m	Thu Feb 28 02:04:24 2013 -0500
+++ b/doc/interpreter/sparseimages.m	Wed Mar 06 16:43:33 2013 -0500
@@ -23,9 +23,9 @@
     set (0, "defaulttextfontname", "*");
   endif
 
-  if (! isempty (findstr (octave_config_info ("DEFS"), "HAVE_COLAMD"))
-      && ! isempty (findstr (octave_config_info ("DEFS"), "HAVE_CHOLMOD"))
-      && ! isempty (findstr (octave_config_info ("DEFS"), "HAVE_UMFPACK")))
+  if (__have_feature__ ("COLAMD")
+      && __have_feature__ ("CHOLMOD")
+      && __have_feature__ ("UMFPACK"))
     if (strcmp(typ,"txt"))
       txtimages (nm, 15, typ);
     else
@@ -86,8 +86,8 @@
   elseif (strcmp (nm, "spmatrix"))
     printsparse(a,cstrcat("spmatrix.",typ));
   else
-    if (!isempty(findstr(octave_config_info ("DEFS"),"HAVE_COLAMD")) &&
-        !isempty(findstr(octave_config_info ("DEFS"),"HAVE_CHOLMOD")))
+    if (__have_feature__ ("COLAMD")
+        && __have_feature__ ("CHOLMOD"))
       if (strcmp (nm, "spchol"))
         r1 = chol(a);
         printsparse(r1,cstrcat("spchol.",typ));
@@ -116,8 +116,8 @@
     print(cstrcat("spmatrix.",typ), d_typ)
     hide_output ();
   else
-    if (!isempty(findstr(octave_config_info ("DEFS"),"HAVE_COLAMD")) &&
-        !isempty(findstr(octave_config_info ("DEFS"),"HAVE_CHOLMOD")))
+    if (__have_feature__ ("COLAMD")
+        && __have_feature__ ("CHOLMOD"))
       if (strcmp (nm, "spchol"))
         r1 = chol(a);
         spy(r1);
@@ -182,9 +182,9 @@
     d_typ = cstrcat ("-d", typ);
   endif
 
-  if (!isempty(findstr(octave_config_info ("DEFS"),"HAVE_COLAMD")) &&
-      !isempty(findstr(octave_config_info ("DEFS"),"HAVE_CHOLMOD")) &&
-      !isempty(findstr(octave_config_info ("DEFS"),"HAVE_UMFPACK")))
+  if (__have_feature__ ("COLAMD")
+      && __have_feature__ ("CHOLMOD")
+      && __have_feature__ ("UMFPACK"))
     ## build a rectangle
     node_y = [1;1.2;1.5;1.8;2]*ones(1,11);
     node_x = ones(5,1)*[1,1.05,1.1,1.2,1.3,1.5,1.7,1.8,1.9,1.95,2];
--- a/libgui/src/files-dockwidget.cc	Thu Feb 28 02:04:24 2013 -0500
+++ b/libgui/src/files-dockwidget.cc	Wed Mar 06 16:43:33 2013 -0500
@@ -124,7 +124,8 @@
   Qt::SortOrder sort_order = _file_tree_view->header ()->sortIndicatorOrder ();
   settings->setValue ("filesdockwidget/sort_files_by_column", sort_column);
   settings->setValue ("filesdockwidget/sort_files_by_order", sort_order);
-  settings->setValue ("filesdockwidget/column_state", _file_tree_view->header ()->saveState ()); 
+  settings->setValue ("filesdockwidget/column_state", _file_tree_view->header ()->saveState ());
+  settings->sync ();
 }
 
 void
--- a/libgui/src/m-editor/file-editor.cc	Thu Feb 28 02:04:24 2013 -0500
+++ b/libgui/src/m-editor/file-editor.cc	Wed Mar 06 16:43:33 2013 -0500
@@ -427,6 +427,7 @@
     QSettings *settings = resource_manager::get_settings ();
     // FIXME -- what should happen if settings is 0?
     settings->setValue ("editor/mru_file_list",_mru_files);
+    settings->sync ();
 }
 
 void
@@ -600,6 +601,10 @@
   _cut_action->setEnabled(false);
   _run_action->setShortcut                      (Qt::ControlModifier+ Qt::Key_R);
   _run_action->setShortcutContext               (Qt::WindowShortcut);
+  save_action->setShortcut                      (QKeySequence::Save);
+  save_action->setShortcutContext               (Qt::WindowShortcut);
+  save_as_action->setShortcut                   (QKeySequence::SaveAs);
+  save_as_action->setShortcutContext            (Qt::WindowShortcut);
   next_bookmark_action->setShortcut             (Qt::Key_F2);
   next_bookmark_action->setShortcutContext      (Qt::WindowShortcut);
   previous_bookmark_action->setShortcut         (Qt::SHIFT + Qt::Key_F2);
@@ -610,7 +615,7 @@
   comment_selection_action->setShortcutContext  (Qt::WindowShortcut);
   uncomment_selection_action->setShortcut       (Qt::ControlModifier + Qt::Key_8);
   uncomment_selection_action->setShortcutContext(Qt::WindowShortcut);
-  find_action->setShortcut                      (Qt::ControlModifier+Qt::Key_F);
+  find_action->setShortcut                      (QKeySequence::Find);
   find_action->setShortcutContext               (Qt::WindowShortcut);
 
   // toolbar
--- a/libgui/src/main-window.cc	Thu Feb 28 02:04:24 2013 -0500
+++ b/libgui/src/main-window.cc	Wed Mar 06 16:43:33 2013 -0500
@@ -129,7 +129,7 @@
 main_window::handle_save_workspace_request ()
 {
   QString selectedFile =
-    QFileDialog::getSaveFileName (this, tr ("Save Workspace"),
+    QFileDialog::getSaveFileName (this, tr ("Save Workspace As"),
                                   resource_manager::get_home_path ());
   if (!selectedFile.isEmpty ())
     octave_link::post_event (this, &main_window::save_workspace_callback,
@@ -698,7 +698,8 @@
 
   QAction *new_script_action
     = new_menu->addAction (QIcon(":/actions/icons/filenew.png"), tr ("Script"));
-  new_script_action->setShortcut (Qt::ControlModifier + Qt::Key_N);
+  new_script_action->setShortcut (QKeySequence::New);
+  new_script_action->setShortcutContext (Qt::ApplicationShortcut);
 
   QAction *new_function_action = new_menu->addAction (tr ("Function"));
   new_function_action->setEnabled (false); // TODO: Make this work.
@@ -717,24 +718,24 @@
 
   QAction *open_action
     = file_menu->addAction (QIcon(":/actions/icons/fileopen.png"), tr ("Open..."));
-  open_action->setShortcut (Qt::ControlModifier + Qt::Key_O);
+  open_action->setShortcut (QKeySequence::Open);
+  open_action->setShortcutContext (Qt::ApplicationShortcut);
 
   file_menu->addMenu(_file_editor->get_mru_menu ());
 
   QAction *close_command_window_action
     = file_menu->addAction (tr ("Close Command Window"));
-  close_command_window_action->setShortcut (Qt::ControlModifier + Qt::Key_W);
+  close_command_window_action->setShortcut (QKeySequence::Close);
   close_command_window_action->setEnabled (false); // TODO: Make this work.
 
   file_menu->addSeparator (); /////
 
   QAction *import_data_action
-    = file_menu->addAction (tr ("Import Data..."));
+    = file_menu->addAction (tr ("Import Data"));
   import_data_action->setEnabled (false); // TODO: Make this work.
 
   QAction *save_workspace_action
-    = file_menu->addAction (tr ("Save Workspace..."));
-  save_workspace_action->setShortcut (Qt::ControlModifier + Qt::Key_S);
+    = file_menu->addAction (tr ("Save Workspace As"));
 
   file_menu->addSeparator (); /////
 
@@ -749,7 +750,7 @@
   page_setup_action->setEnabled (false); // TODO: Make this work.
   QAction *print_action
     = file_menu->addAction (tr ("Print"));
-  print_action->setShortcut (Qt::ControlModifier + Qt::Key_P);
+  print_action->setShortcut (QKeySequence::Print);
   print_action->setEnabled (false); // TODO: Make this work.
   QAction *print_selection_action
     = file_menu->addAction (tr ("Print Selection..."));
@@ -758,7 +759,7 @@
   file_menu->addSeparator (); /////
 
   QAction *exit_action = file_menu->addAction (tr ("Exit"));
-  exit_action->setShortcut (Qt::ControlModifier + Qt::Key_Q);
+  exit_action->setShortcut (QKeySequence::Quit);
 
 
   QMenu *edit_menu = menuBar ()->addMenu (tr ("&Edit"));
@@ -879,58 +880,61 @@
   show_command_window_action->setCheckable (true);
   show_command_window_action->setShortcut (Qt::ControlModifier
                                            + Qt::ShiftModifier + Qt::Key_0);
-
+  show_command_window_action->setShortcutContext (Qt::ApplicationShortcut);
   QAction * show_history_action
     = window_menu->addAction (tr ("Show Command History"));
   show_history_action->setCheckable (true);
   show_history_action->setShortcut (Qt::ControlModifier
                                     + Qt::ShiftModifier + Qt::Key_1);
+  show_history_action->setShortcutContext (Qt::ApplicationShortcut);
   QAction * show_file_browser_action
     = window_menu->addAction (tr ("Show Current Directory"));
   show_file_browser_action->setCheckable (true);
   show_file_browser_action->setShortcut (Qt::ControlModifier
                                          + Qt::ShiftModifier + Qt::Key_2);
-
+  show_file_browser_action->setShortcutContext (Qt::ApplicationShortcut);
   QAction * show_workspace_action
     = window_menu->addAction (tr ("Show Workspace"));
   show_workspace_action->setCheckable (true);
   show_workspace_action->setShortcut (Qt::ControlModifier
                                       + Qt::ShiftModifier + Qt::Key_3);
-
+  show_workspace_action->setShortcutContext (Qt::ApplicationShortcut);
   QAction * show_editor_action = window_menu->addAction (tr ("Show Editor"));
   show_editor_action->setCheckable (true);
   show_editor_action->setShortcut (Qt::ControlModifier + Qt::ShiftModifier
                                    + Qt::Key_4);
-
+  show_editor_action->setShortcutContext (Qt::ApplicationShortcut);
   QAction * show_documentation_action = window_menu->addAction (tr ("Show Documentation"));
   show_documentation_action->setCheckable (true);
   show_documentation_action->setShortcut (Qt::ControlModifier + Qt::ShiftModifier
                                           + Qt::Key_5);
+  show_documentation_action->setShortcutContext (Qt::ApplicationShortcut);
   window_menu->addSeparator (); /////
 
   QAction * command_window_action
     = window_menu->addAction (tr ("Command Window"));
   command_window_action->setShortcut (Qt::ControlModifier + Qt::Key_0);
-
+  command_window_action->setShortcutContext (Qt::ApplicationShortcut);
   QAction * history_action
     = window_menu->addAction (tr ("Command History"));
   history_action->setShortcut (Qt::ControlModifier + Qt::Key_1);
-
+  history_action->setShortcutContext (Qt::ApplicationShortcut);
   QAction * file_browser_action
     = window_menu->addAction (tr ("Current Directory"));
   file_browser_action->setShortcut (Qt::ControlModifier + Qt::Key_2);
-
+  file_browser_action->setShortcutContext (Qt::ApplicationShortcut);
   QAction * workspace_action
     = window_menu->addAction (tr ("Workspace"));
   workspace_action->setShortcut (Qt::ControlModifier + Qt::Key_3);
-
+  workspace_action->setShortcutContext (Qt::ApplicationShortcut);
   QAction * editor_action
     = window_menu->addAction (tr ("Editor"));
   editor_action->setShortcut (Qt::ControlModifier + Qt::Key_4);
-
+  editor_action->setShortcutContext (Qt::ApplicationShortcut);
   QAction * documentation_action
     = window_menu->addAction (tr ("Documentation"));
   documentation_action->setShortcut (Qt::ControlModifier + Qt::Key_5);
+  documentation_action->setShortcutContext (Qt::ApplicationShortcut);
 
   window_menu->addSeparator (); /////
 
--- a/libgui/src/octave-adapter/octave-main-thread.cc	Thu Feb 28 02:04:24 2013 -0500
+++ b/libgui/src/octave-adapter/octave-main-thread.cc	Wed Mar 06 16:43:33 2013 -0500
@@ -40,6 +40,8 @@
 octave_main_thread::run ()
 {
   setlocale (LC_ALL, "en_US.UTF-8");
+  // Matlab uses "C" locale for LC_NUMERIC class regardless of local setting
+  setlocale (LC_NUMERIC, "C");
 
   emit ready ();
 
--- a/libgui/src/workspace-view.cc	Thu Feb 28 02:04:24 2013 -0500
+++ b/libgui/src/workspace-view.cc	Wed Mar 06 16:43:33 2013 -0500
@@ -97,13 +97,11 @@
 workspace_view::~workspace_view ()
 {
   QSettings *settings = resource_manager::get_settings ();
-
-  // FIXME -- what should happen if settings is 0?
-
   settings->setValue("workspaceview/local_collapsed", _explicit_collapse.local);
   settings->setValue("workspaceview/global_collapsed", _explicit_collapse.global);
   settings->setValue("workspaceview/persistent_collapsed", _explicit_collapse.persistent);
   settings->setValue("workspaceview/column_state", _workspace_tree_view->header ()->saveState ());
+  settings->sync ();
 }
 
 void
--- a/libinterp/Makefile.am	Thu Feb 28 02:04:24 2013 -0500
+++ b/libinterp/Makefile.am	Wed Mar 06 16:43:33 2013 -0500
@@ -58,13 +58,15 @@
   parse-tree/oct-gperf.h \
   parse-tree/oct-parse.cc \
   oct-conf.h \
+  oct-conf-features.h \
   version.h \
   builtin-defun-decls.h \
   builtins.cc
 
 BUILT_DISTFILES = \
   parse-tree/oct-gperf.h \
-  parse-tree/oct-parse.h
+  parse-tree/oct-parse.h \
+  parse-tree/oct-parse.yy
 
 ## Files that are created during build process and installed,
 ## BUT not distributed in tarball.
@@ -76,6 +78,7 @@
   builtin-defun-decls.h \
   operators/ops.cc \
   oct-conf.h \
+  oct-conf-features.h \
   version.h \
   $(OPT_HANDLERS) \
   $(OPT_INC) \
@@ -85,6 +88,7 @@
 EXTRA_DIST = \
   Makefile.in \
   DOCSTRINGS \
+  config-features.sh \
   find-defun-files.sh \
   gendoc.pl \
   genprops.awk \
@@ -94,6 +98,7 @@
   mkdefs \
   mkops \
   oct-conf.in.h \
+  parse-tree/oct-parse.in.yy \
   version.in.h \
   $(BUILT_DISTFILES)
 
@@ -162,6 +167,7 @@
   builtin-defun-decls.h \
   builtins.cc \
   oct-conf.h \
+  oct-conf-features.h \
   version.h \
   $(OPT_INC)
 
@@ -192,7 +198,11 @@
   $(LIBOCTINTERP_LINK_OPTS)
 
 ## Section for defining and creating DEF_FILES
-SRC_DEF_FILES := $(shell $(srcdir)/find-defun-files.sh "$(srcdir)" $(DIST_SRC))
+
+ULT_DIST_SRC := \
+  $(filter-out parse-tree/oct-parse.yy, $(DIST_SRC)) parse-tree/oct-parse.in.yy
+
+SRC_DEF_FILES := $(shell $(srcdir)/find-defun-files.sh "$(srcdir)" $(ULT_DIST_SRC))
 
 DLDFCN_DEF_FILES = $(DLDFCN_SRC:.cc=.df)
 
@@ -232,7 +242,7 @@
 
 ## Rules to build test files
 
-TST_FILES_SRC := $(shell $(top_srcdir)/build-aux/find-files-with-tests.sh "$(srcdir)" $(DIST_SRC) $(DLDFCN_SRC))
+TST_FILES_SRC := $(shell $(top_srcdir)/build-aux/find-files-with-tests.sh "$(srcdir)" $(ULT_DIST_SRC) $(DLDFCN_SRC))
 
 TST_FILES := $(addsuffix -tst,$(TST_FILES_SRC))
 
@@ -256,6 +266,10 @@
 oct-conf.h: oct-conf.in.h Makefile
 	@$(do_subst_config_vals)
 
+oct-conf-features.h: $(top_builddir)/config.h config-features.sh
+	$(srcdir)/config-features.sh $< > $@-t
+	mv $@-t $@
+
 version.h: version.in.h Makefile
 	$(SED) < $< \
 	  -e "s|%NO_EDIT_WARNING%|DO NOT EDIT!  Generated automatically from $(<F) by Make.|" \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/config-features.sh	Wed Mar 06 16:43:33 2013 -0500
@@ -0,0 +1,36 @@
+#! /bin/sh
+
+set -e
+AWK=${AWK:-awk}
+
+conffile=$1
+
+cat << EOF
+// DO NOT EDIT!  Generated automatically from $conffile by Make."
+
+#include "oct-map.h"
+#include "ov.h"
+
+octave_scalar_map
+octave_config_features (void)
+{
+  octave_scalar_map m;
+
+EOF
+
+$AWK \
+  '/#define HAVE_/ {
+     sub (/HAVE_/, "", $2);
+     printf ("  m.assign (\"%s\", octave_value (true));\n", $2);
+   }
+   /\/\* #undef HAVE_/ {
+     sub (/HAVE_/, "", $3);
+     printf ("  m.assign (\"%s\", octave_value (false));\n", $3);
+   } {
+   }' $conffile
+
+cat << EOF
+
+  return m;
+}
+EOF
--- a/libinterp/find-defun-files.sh	Thu Feb 28 02:04:24 2013 -0500
+++ b/libinterp/find-defun-files.sh	Wed Mar 06 16:43:33 2013 -0500
@@ -21,6 +21,6 @@
     file="$srcdir/$arg"
   fi
   if [ "`$EGREP -l "$DEFUN_PATTERN" $file`" ]; then
-    echo "$file" | $SED "s,\\$srcdir/,," | $SED 's/\.cc$/.df/; s/\.ll$/.df/; s/\.yy$/.df/';
+    echo "$file" | $SED "s,\\$srcdir/,," | $SED 's/\.cc$/.df/; s/\.ll$/.df/; s/\.in.yy$/.df/';
   fi
 done
--- a/libinterp/interp-core/txt-eng-ft.cc	Thu Feb 28 02:04:24 2013 -0500
+++ b/libinterp/interp-core/txt-eng-ft.cc	Wed Mar 06 16:43:33 2013 -0500
@@ -564,6 +564,11 @@
   return pixels;
 }
 
+// Note:
+// x-extent accurately measures width of glyphs.
+// y-extent is overly large because it is measured from baseline-to-baseline.
+// Calling routines, such as ylabel, may need to account for this mismatch.
+
 Matrix
 ft_render::get_extent (text_element *elt, double rotation)
 {
--- a/libinterp/interpfcn/graphics.cc	Thu Feb 28 02:04:24 2013 -0500
+++ b/libinterp/interpfcn/graphics.cc	Wed Mar 06 16:43:33 2013 -0500
@@ -5194,11 +5194,20 @@
       graphics_xform xform = get_transform ();
 
       Matrix ext (1, 2, 0.0);
+
+      // The underlying get_extents() from FreeType produces mismatched values.
+      // x-extent accurately measures the width of the glyphs.
+      // y-extent instead measures from baseline-to-baseline.
+      // Pad x-extent (+4) so that it approximately matches y-extent.
+      // This keeps ylabels about the same distance from y-axis as
+      // xlabels are from x-axis.
+      // ALWAYS use an even number for padding or horizontal alignment
+      // will be off.
       ext = get_ticklabel_extents (get_ytick ().matrix_value (),
                                    get_yticklabel ().all_strings (),
                                    get_ylim ().matrix_value ());
 
-      double wmax = ext(0), hmax = ext(1), angle = 0;
+      double wmax = ext(0)+4, hmax = ext(1), angle = 0;
       ColumnVector p =
         graphics_xform::xform_vector (xpTick, (ypTickN+ypTick)/2, zpTick);
 
--- a/libinterp/interpfcn/help.cc	Thu Feb 28 02:04:24 2013 -0500
+++ b/libinterp/interpfcn/help.cc	Wed Mar 06 16:43:33 2013 -0500
@@ -902,11 +902,6 @@
 {
   bool retval = false;
 
-  // FIXME -- this is a bit of a kluge...
-  unwind_protect frame;
-  frame.protect_var (reading_script_file);
-  reading_script_file = true;
-
   h = get_help_from_file (nm, symbol_found, file);
 
   if (h.length () > 0)
--- a/libinterp/interpfcn/input.cc	Thu Feb 28 02:04:24 2013 -0500
+++ b/libinterp/interpfcn/input.cc	Wed Mar 06 16:43:33 2013 -0500
@@ -94,37 +94,9 @@
 // Character to append after successful command-line completion attempts.
 static char Vcompletion_append_char = ' ';
 
-// Global pointer for eval().
-std::string current_eval_string;
-
-// TRUE means get input from current_eval_string.
-bool get_input_from_eval_string = false;
-
-// TRUE means that input is coming from a file that was named on
-// the command line.
-bool input_from_command_line_file = false;
-
 // TRUE means that stdin is a terminal, not a pipe or redirected file.
 bool stdin_is_tty = false;
 
-// TRUE means we're parsing a function file.
-bool reading_fcn_file = false;
-
-// TRUE means we're parsing a classdef file.
-bool reading_classdef_file = false;
-
-// Simple name of function file we are reading.
-std::string curr_fcn_file_name;
-
-// Full name of file we are reading.
-std::string curr_fcn_file_full_name;
-
-// TRUE means we're parsing a script file.
-bool reading_script_file = false;
-
-// If we are reading from an M-file, this is it.
-FILE *ff_instream = 0;
-
 // TRUE means this is an interactive shell.
 bool interactive = false;
 
@@ -160,7 +132,7 @@
 static void
 do_input_echo (const std::string& input_string)
 {
-  int do_echo = reading_script_file ?
+  int do_echo = CURR_LEXER->reading_script_file ?
     (Vecho_executing_commands & ECHO_SCRIPTS)
       : (Vecho_executing_commands & ECHO_CMD_LINE) && ! forced_interactive;
 
@@ -186,53 +158,25 @@
     }
 }
 
-std::string
-gnu_readline (const std::string& s, bool& eof, bool force_readline)
+static std::string
+gnu_readline (const std::string& s, bool& eof)
 {
   octave_quit ();
 
   eof = false;
 
-  std::string retval;
-
-  if (line_editing || force_readline)
-    {
-      retval = command_editor::readline (s, eof);
+  assert (line_editing);
 
-      if (! eof && retval.empty ())
-        retval = "\n";
-    }
-  else
-    {
-      if (! s.empty () && (interactive || forced_interactive))
-        {
-          FILE *stream = command_editor::get_output_stream ();
+  std::string retval = command_editor::readline (s, eof);
 
-          gnulib::fputs (s.c_str (), stream);
-          gnulib::fflush (stream);
-        }
-
-      FILE *curr_stream = command_editor::get_input_stream ();
-
-      if (reading_fcn_file || reading_script_file || reading_classdef_file)
-        curr_stream = ff_instream;
-
-      retval = octave_fgets (curr_stream, eof);
-    }
+  if (! eof && retval.empty ())
+    retval = "\n";
 
   return retval;
 }
 
-extern std::string
-gnu_readline (const std::string& s, bool force_readline)
-{
-  bool eof = false;
-
-  return gnu_readline (s, eof, force_readline);
-}
-
 static inline std::string
-interactive_input (const std::string& s, bool& eof, bool force_readline)
+interactive_input (const std::string& s, bool& eof)
 {
   Vlast_prompt_time.stamp ();
 
@@ -251,19 +195,11 @@
         return "\n";
     }
 
-  return gnu_readline (s, eof, force_readline);
+  return gnu_readline (s, eof);
 }
 
-static inline std::string
-interactive_input (const std::string& s, bool force_readline = false)
-{
-  bool eof = false;
-
-  return interactive_input (s, eof, force_readline);
-}
-
-static std::string
-octave_gets (bool& eof)
+std::string
+octave_base_reader::octave_gets (bool& eof)
 {
   octave_quit ();
 
@@ -273,127 +209,59 @@
 
   bool history_skip_auto_repeated_debugging_command = false;
 
-  if ((interactive || forced_interactive)
-      && (! (reading_fcn_file
-             || reading_classdef_file
-             || reading_script_file
-             || get_input_from_eval_string
-             || input_from_startup_file
-             || input_from_command_line_file)))
-    {
-      std::string ps = (promptflag > 0) ? VPS1 : VPS2;
+  std::string ps = (promptflag > 0) ? VPS1 : VPS2;
+
+  std::string prompt = command_editor::decode_prompt_string (ps);
+
+  pipe_handler_error_count = 0;
 
-      std::string prompt = command_editor::decode_prompt_string (ps);
-
-      pipe_handler_error_count = 0;
+  flush_octave_stdout ();
 
-      flush_octave_stdout ();
+  octave_pager_stream::reset ();
+  octave_diary_stream::reset ();
 
-      octave_pager_stream::reset ();
-      octave_diary_stream::reset ();
+  octave_diary << prompt;
 
-      octave_diary << prompt;
+  retval = interactive_input (prompt, eof);
 
-      retval = interactive_input (prompt, eof, false);
-
-      // There is no need to update the load_path cache if there is no
-      // user input.
-      if (! retval.empty ()
-          && retval.find_first_not_of (" \t\n\r") != std::string::npos)
-        {
-          load_path::update ();
+  // There is no need to update the load_path cache if there is no
+  // user input.
+  if (! retval.empty ()
+      && retval.find_first_not_of (" \t\n\r") != std::string::npos)
+    {
+      load_path::update ();
 
-          if (Vdebugging)
-            last_debugging_command = retval;
-          else
-            last_debugging_command = std::string ();
-        }
-      else if (Vdebugging)
-        {
-          retval = last_debugging_command;
-          history_skip_auto_repeated_debugging_command = true;
-        }
+      if (Vdebugging)
+        last_debugging_command = retval;
+      else
+        last_debugging_command = std::string ();
     }
-  else
-    retval = gnu_readline ("", eof, false);
+  else if (Vdebugging)
+    {
+      retval = last_debugging_command;
+      history_skip_auto_repeated_debugging_command = true;
+    }
 
   current_input_line = retval;
 
   if (! current_input_line.empty ())
     {
-      if (! (input_from_startup_file || input_from_command_line_file
-             || history_skip_auto_repeated_debugging_command))
+      if (! history_skip_auto_repeated_debugging_command)
         command_history::add (current_input_line);
 
-      if (! (reading_fcn_file || reading_script_file || reading_classdef_file))
-        {
-          octave_diary << current_input_line;
+      octave_diary << current_input_line;
 
-          if (current_input_line[current_input_line.length () - 1] != '\n')
-            octave_diary << "\n";
-        }
+      if (current_input_line[current_input_line.length () - 1] != '\n')
+        octave_diary << "\n";
 
       do_input_echo (current_input_line);
     }
-  else if (! (reading_fcn_file || reading_script_file || reading_classdef_file))
+  else
     octave_diary << "\n";
 
   return retval;
 }
 
-// Read a line from the input stream.
-
-std::string
-get_user_input (bool& eof)
-{
-  octave_quit ();
-
-  eof = false;
-
-  std::string retval;
-
-  if (get_input_from_eval_string)
-    {
-      retval = current_eval_string;
-
-      size_t len = retval.length ();
-
-      // Clear the global eval string so that the next call will return
-      // an empty character string with EOF = true.
-      current_eval_string = "";
-
-      eof = true;
-    }
-  else
-    retval = octave_gets (eof);
-
-  current_input_line = retval;
-
-  return retval;
-}
-
-// Fix things up so that input can come from file 'name', printing a
-// warning if the file doesn't exist.
-
-FILE *
-get_input_from_file (const std::string& name, int warn)
-{
-  FILE *instream = 0;
-
-  if (name.length () > 0)
-    instream = gnulib::fopen (name.c_str (), "rb");
-
-  if (! instream && warn)
-    warning ("%s: no such file or directory", name.c_str ());
-
-  if (reading_fcn_file || reading_script_file || reading_classdef_file)
-    ff_instream = instream;
-  else
-    command_editor::set_input_stream (instream);
-
-  return instream;
-}
-
 // Fix things up so that input can come from the standard input.  This
 // may need to become much more complicated, which is why it's in a
 // separate function.
@@ -640,40 +508,19 @@
   VPS1 = prompt;
 
   if (! (interactive || forced_interactive)
-      || (reading_fcn_file
-          || reading_classdef_file
-          || reading_script_file
-          || get_input_from_eval_string
-          || input_from_startup_file
-          || input_from_command_line_file))
+      || CURR_LEXER->reading_fcn_file
+      || CURR_LEXER->reading_classdef_file
+      || CURR_LEXER->reading_script_file
+      || CURR_LEXER->input_from_eval_string ())
     {
       frame.protect_var (forced_interactive);
       forced_interactive = true;
-
-      frame.protect_var (reading_fcn_file);
-      reading_fcn_file = false;
-
-      frame.protect_var (reading_classdef_file);
-      reading_classdef_file = false;
-
-      frame.protect_var (reading_script_file);
-      reading_script_file = false;
-
-      frame.protect_var (input_from_startup_file);
-      input_from_startup_file = false;
-
-      frame.protect_var (input_from_command_line_file);
-      input_from_command_line_file = false;
-
-      frame.protect_var (get_input_from_eval_string);
-      get_input_from_eval_string = false;
     }
 
   // octave_parser constructor sets this for us.
   frame.protect_var (CURR_LEXER);
 
-  octave_parser *curr_parser = new octave_parser ();
-  frame.add_fcn (octave_parser::cleanup, curr_parser);
+  octave_parser curr_parser;
 
   while (Vdebugging)
     {
@@ -681,31 +528,18 @@
 
       reset_error_handler ();
 
-      curr_parser->reset ();
-
-      // Save current value of global_command.
-      middle_frame.protect_var (global_command);
-
-      global_command = 0;
+      curr_parser.reset ();
 
       // Do this with an unwind-protect cleanup function so that the
       // forced variables will be unmarked in the event of an interrupt.
       symbol_table::scope_id scope = symbol_table::top_scope ();
       middle_frame.add_fcn (symbol_table::unmark_forced_variables, scope);
 
-      int retval = curr_parser->run ();
-
-      if (retval == 0 && global_command)
-        {
-          unwind_protect inner_frame;
+      int retval = curr_parser.run ();
 
-          // Use an unwind-protect cleanup function so that the
-          // global_command list will be deleted in the event of an
-          // interrupt.
-
-          inner_frame.add_fcn (cleanup_statement_list, &global_command);
-
-          global_command->accept (*current_evaluator);
+      if (retval == 0 && curr_parser.stmt_list)
+        {
+          curr_parser.stmt_list->accept (*current_evaluator);
 
           if (octave_completion_matches_called)
             octave_completion_matches_called = false;
@@ -715,6 +549,65 @@
     }
 }
 
+const std::string octave_base_reader::in_src ("invalid");
+
+const std::string octave_terminal_reader::in_src ("terminal");
+
+std::string
+octave_terminal_reader::get_input (bool& eof)
+{
+  octave_quit ();
+
+  eof = false;
+
+  std::string retval = octave_gets (eof);
+
+  current_input_line = retval;
+
+  return retval;
+}
+
+const std::string octave_file_reader::in_src ("file");
+
+std::string
+octave_file_reader::get_input (bool& eof)
+{
+  octave_quit ();
+
+  eof = false;
+
+  std::string retval = octave_fgets (file, eof);
+
+  current_input_line = retval;
+
+  return retval;
+}
+
+const std::string octave_eval_string_reader::in_src ("eval_string");
+
+std::string
+octave_eval_string_reader::get_input (bool& eof)
+{
+  octave_quit ();
+
+  eof = false;
+
+  std::string retval;
+
+  retval = eval_string;
+
+  // Clear the eval string so that the next call will return
+  // an empty character string with EOF = true.
+  eval_string = "";
+
+  if (retval.empty ())
+    eof = true;
+
+  current_input_line = retval;
+
+  return retval;
+}
+
 // If the user simply hits return, this will produce an empty matrix.
 
 static octave_value_list
@@ -744,13 +637,12 @@
 
   octave_diary << prompt;
 
-  std::string input_buf = interactive_input (prompt.c_str (), true);
+  bool eof = false;
+
+  std::string input_buf = interactive_input (prompt.c_str (), eof);
 
   if (! (error_state || input_buf.empty ()))
     {
-      if (! input_from_startup_file)
-        command_history::add (input_buf);
-
       size_t len = input_buf.length ();
 
       octave_diary << input_buf;
@@ -841,7 +733,9 @@
 
   while (1)
     {
-      std::string input_buf = interactive_input (prompt_string, true);
+      bool eof = false;
+
+      std::string input_buf = interactive_input (prompt_string, eof);
 
       if (input_buf == "yes")
         return true;
--- a/libinterp/interpfcn/input.h	Thu Feb 28 02:04:24 2013 -0500
+++ b/libinterp/interpfcn/input.h	Wed Mar 06 16:43:33 2013 -0500
@@ -35,44 +35,11 @@
 
 class octave_value;
 
-extern OCTINTERP_API std::string get_user_input (bool& eof);
-
-extern OCTINTERP_API FILE *get_input_from_file (const std::string& name,
-                                                int warn = 1);
-
 extern OCTINTERP_API FILE *get_input_from_stdin (void);
 
-// Global pointer for eval().
-extern std::string current_eval_string;
-
-// TRUE means get input from current_eval_string.
-extern bool get_input_from_eval_string;
-
-// TRUE means that input is coming from a file that was named on
-// the command line.
-extern bool input_from_command_line_file;
-
 // TRUE means that stdin is a terminal, not a pipe or redirected file.
 extern bool stdin_is_tty;
 
-// TRUE means we're parsing a function file.
-extern bool reading_fcn_file;
-
-// Simple name of function file we are reading.
-extern std::string curr_fcn_file_name;
-
-// Full name of file we are reading.
-extern std::string curr_fcn_file_full_name;
-
-// TRUE means we're parsing a script file.
-extern bool reading_script_file;
-
-// TRUE means we're parsing a classdef file.
-extern bool reading_classdef_file;
-
-// If we are reading from an M-file, this is it.
-extern FILE *ff_instream;
-
 // TRUE means this is an interactive shell.
 extern bool interactive;
 
@@ -95,8 +62,6 @@
 // TRUE if we are in debugging mode.
 extern OCTINTERP_API bool Vdebugging;
 
-extern std::string gnu_readline (const std::string& s, bool force_readline = false);
-
 extern void initialize_command_input (void);
 
 extern bool octave_yes_or_no (const std::string& prompt);
@@ -119,4 +84,139 @@
 
 extern octave_time Vlast_prompt_time;
 
+class
+octave_base_reader
+{
+public:
+
+  friend class octave_input_reader;
+
+  octave_base_reader (void) : count (1) { }
+
+  octave_base_reader (const octave_base_reader&) : count (1) { }
+
+  virtual ~octave_base_reader (void) { }
+
+  virtual std::string get_input (bool& eof) = 0;
+
+  virtual std::string input_source (void) const { return in_src; }
+
+  std::string octave_gets (bool& eof);
+
+private:
+
+  int count;
+
+  static const std::string in_src;
+};
+
+class
+octave_terminal_reader : public octave_base_reader
+{
+public:
+
+  octave_terminal_reader (void) : octave_base_reader () { }
+
+  std::string get_input (bool& eof);
+
+  std::string input_source (void) const { return in_src; }
+
+private:
+
+  static const std::string in_src;
+};
+
+class
+octave_file_reader : public octave_base_reader
+{
+public:
+
+  octave_file_reader (FILE *f_arg)
+    : octave_base_reader (), file (f_arg) { }
+
+  std::string get_input (bool& eof);
+
+  std::string input_source (void) const { return in_src; }
+
+private:
+
+  FILE *file;
+
+  static const std::string in_src;
+};
+
+class
+octave_eval_string_reader : public octave_base_reader
+{
+public:
+
+  octave_eval_string_reader (const std::string& str)
+    : octave_base_reader (), eval_string (str)
+  { }
+
+  std::string get_input (bool& eof);
+
+  std::string input_source (void) const { return in_src; }
+
+private:
+
+  std::string eval_string;
+
+  static const std::string in_src;
+};
+
+class
+octave_input_reader
+{
+public:
+  octave_input_reader (void)
+    : rep (new octave_terminal_reader ())
+  { }
+
+  octave_input_reader (FILE *file)
+    : rep (new octave_file_reader (file))
+  { }
+
+  octave_input_reader (const std::string& str)
+    : rep (new octave_eval_string_reader (str))
+  { }
+
+  octave_input_reader (const octave_input_reader& ir)
+  {
+    rep = ir.rep;
+    rep->count++;
+  }
+
+  octave_input_reader& operator = (const octave_input_reader& ir)
+  {
+    if (&ir != this)
+      {
+        rep = ir.rep;
+        rep->count++;
+      }
+
+    return *this;
+  }
+
+  ~octave_input_reader (void)
+  {
+    if (--rep->count == 0)
+      delete rep;
+  }
+
+  std::string get_input (bool& eof)
+  {
+    return rep->get_input (eof);
+  }
+
+  std::string input_source (void) const
+  {
+    return rep->input_source ();
+  }
+
+private:
+
+  octave_base_reader *rep;
+};
+
 #endif
--- a/libinterp/interpfcn/load-path.cc	Thu Feb 28 02:04:24 2013 -0500
+++ b/libinterp/interpfcn/load-path.cc	Wed Mar 06 16:43:33 2013 -0500
@@ -1956,10 +1956,6 @@
 
   unwind_protect frame;
 
-  frame.protect_var (input_from_startup_file);
-
-  input_from_startup_file = true;
-
   std::string file = file_ops::concat (dir, script_file);
 
   file_stat fs (file);
--- a/libinterp/interpfcn/oct-hist.cc	Thu Feb 28 02:04:24 2013 -0500
+++ b/libinterp/interpfcn/oct-hist.cc	Wed Mar 06 16:43:33 2013 -0500
@@ -299,6 +299,11 @@
 // appear in the history list.  This way you can do 'run_history' to
 // your heart's content.
 
+// FIXME: Don't delete this block of code until memory
+//        leak in edit_history has been plugged and
+//        it is clear that this code can be removed.
+//        See additional FIXME in do_edit_history.
+/*
 static void
 edit_history_repl_hist (const std::string& command)
 {
@@ -329,6 +334,7 @@
         }
     }
 }
+*/
 
 static void
 edit_history_add_hist (const std::string& line)
@@ -404,8 +410,14 @@
       if (get_int_arg (args(0), hist_beg)
           && get_int_arg (args(1), hist_end))
         {
-          hist_beg--;
-          hist_end--;
+          if (hist_beg < 0)
+            hist_beg += (hist_count + 1);
+          else
+            hist_beg--;
+          if (hist_end < 0)
+            hist_end += (hist_count + 1);
+          else
+            hist_end--;
         }
       else
         usage_error = true;
@@ -414,23 +426,25 @@
     {
       if (get_int_arg (args(0), hist_beg))
         {
-          hist_beg--;
+          if (hist_beg < 0)
+            hist_beg += (hist_count + 1);
+          else
+            hist_beg--;
           hist_end = hist_beg;
         }
       else
         usage_error = true;
     }
 
-  if (hist_beg < 0 || hist_end < 0 || hist_beg > hist_count
-      || hist_end > hist_count)
+  if (usage_error)
     {
-      error ("%s: history specification out of range", warn_for);
+      usage ("%s [first] [last]", warn_for);
       return retval;
     }
 
-  if (usage_error)
+  if (hist_beg > hist_count || hist_end > hist_count)
     {
-      usage ("%s [first] [last]", warn_for);
+      error ("%s: history specification out of range", warn_for);
       return retval;
     }
 
@@ -484,9 +498,7 @@
   // Call up our favorite editor on the file of commands.
 
   std::string cmd = VEDITOR;
-  cmd.append (" \"");
-  cmd.append (name);
-  cmd.append ("\"");
+  cmd.append (" \"" + name + "\"");
 
   // Ignore interrupts while we are off editing commands.  Should we
   // maybe avoid using system()?
@@ -512,7 +524,7 @@
   std::fstream file (name.c_str (), std::ios::in);
 
   char *line;
-  int first = 1;
+  //int first = 1;
   while ((line = edit_history_readline (file)) != 0)
     {
       // Skip blank lines.
@@ -523,8 +535,10 @@
           continue;
         }
 
-      // Command 'edit history' has already been removed in
-      // mk_tmp_hist_file ()
+      // FIXME: Don't delete this block of code until memory
+      //        leak in edit_history has been plugged and
+      //        it is clear that this code can be removed.
+      // Command 'edit history' has already been removed in mk_tmp_hist_file ()
       //if (first)
       //  {
       //    first = 0;
@@ -561,8 +575,7 @@
   if (name.empty ())
     return;
 
-  // Turn on command echo so the output from this will make better
-  // sense.
+  // Turn on command echo so the output from this will make better sense.
 
   unwind_protect frame;
 
@@ -598,38 +611,37 @@
 
 DEFUN (edit_history, args, ,
   "-*- texinfo -*-\n\
-@deftypefn {Command} {} edit_history [@var{first}] [@var{last}]\n\
-If invoked with no arguments, @code{edit_history} allows you to edit the\n\
-history list using the editor named by the variable @w{@env{EDITOR}}.  The\n\
-commands to be edited are first copied to a temporary file.  When you\n\
-exit the editor, Octave executes the commands that remain in the file.\n\
-It is often more convenient to use @code{edit_history} to define functions\n\
+@deftypefn  {Command} {} edit_history\n\
+@deftypefnx {Command} {} edit_history @var{cmd_number}\n\
+@deftypefnx {Command} {} edit_history @var{first} @var{last}\n\
+Edit the history list using the editor named by the variable\n\
+@w{@env{EDITOR}}.\n\
+\n\
+The commands to be edited are first copied to a temporary file.  When you\n\
+exit the editor, Octave executes the commands that remain in the file.  It\n\
+is often more convenient to use @code{edit_history} to define functions\n\
 rather than attempting to enter them directly on the command line.\n\
-By default, the block of commands is executed as soon as you exit the\n\
-editor.  To avoid executing any commands, simply delete all the lines\n\
-from the buffer before exiting the editor.\n\
+The block of commands is executed as soon as you exit the editor.\n\
+To avoid executing any commands, simply delete all the lines from the buffer\n\
+before leaving the editor.\n\
 \n\
-The @code{edit_history} command takes two optional arguments specifying\n\
-the history numbers of first and last commands to edit.  For example,\n\
-the command\n\
+When invoked with no arguments, edit the previously executed command;\n\
+With one argument, edit the specified command @var{cmd_number};\n\
+With two arguments, edit the list of commands between @var{first} and\n\
+@var{last}.  Command number specifiers may also be negative where -1\n\
+refers to the most recently executed command.\n\
+The following are equivalent and edit the most recently executed command.\n\
 \n\
 @example\n\
-edit_history 13\n\
+@group\n\
+edit_history\n\
+edit_history -1\n\
+@end group\n\
 @end example\n\
 \n\
-@noindent\n\
-extracts all the commands from the 13th through the last in the history\n\
-list.  The command\n\
-\n\
-@example\n\
-edit_history 13 169\n\
-@end example\n\
-\n\
-@noindent\n\
-only extracts commands 13 through 169.  Specifying a larger number for\n\
-the first command than the last command reverses the list of commands\n\
-before placing them in the buffer to be edited.  If both arguments are\n\
-omitted, the previous command in the history list is used.\n\
+When using ranges, specifying a larger number for the first command than the\n\
+last command reverses the list of commands before they are placed in the\n\
+buffer to be edited.\n\
 @seealso{run_history}\n\
 @end deftypefn")
 {
@@ -688,9 +700,52 @@
 
 DEFUN (run_history, args, ,
   "-*- texinfo -*-\n\
-@deftypefn {Command} {} run_history [@var{first}] [@var{last}]\n\
-Similar to @code{edit_history}, except that the editor is not invoked,\n\
-and the commands are simply executed as they appear in the history list.\n\
+@deftypefn  {Command} {} run_history\n\
+@deftypefnx {Command} {} run_history @var{cmd_number}\n\
+@deftypefnx {Command} {} run_history @var{first} @var{last}\n\
+Run commands from the history list.\n\
+\n\
+When invoked with no arguments, run the previously executed command;\n\
+With one argument, run the specified command @var{cmd_number};\n\
+With two arguments, run the list of commands between @var{first} and\n\
+@var{last}.  Command number specifiers may also be negative where -1\n\
+refers to the most recently executed command.\n\
+For example, the command\n\
+\n\
+@example\n\
+@group\n\
+run_history\n\
+     OR\n\
+run_history -1\n\
+@end group\n\
+@end example\n\
+\n\
+@noindent\n\
+executes the most recent command again.\n\
+The command\n\
+\n\
+@example\n\
+run_history 13 169\n\
+@end example\n\
+\n\
+@noindent\n\
+executes commands 13 through 169.\n\
+\n\
+Specifying a larger number for the first command than the last command\n\
+reverses the list of commands before executing them.\n\
+For example:\n\
+\n\
+@example\n\
+@group\n\
+disp (1)\n\
+disp (2)\n\
+run_history -1 -2\n\
+@result{}\n\
+ 2\n\
+ 1\n\
+@end group\n\
+@end example\n\
+\n\
 @seealso{edit_history}\n\
 @end deftypefn")
 {
--- a/libinterp/interpfcn/pr-output.cc	Thu Feb 28 02:04:24 2013 -0500
+++ b/libinterp/interpfcn/pr-output.cc	Wed Mar 06 16:43:33 2013 -0500
@@ -2724,14 +2724,17 @@
                 {
                   octave_quit ();
 
-                  double val = base + i * increment;
+                  double val;
+                  if (i == 0)
+                    val = base;
+                  else
+                    val = base + i * increment;
 
                   if (i == num_elem - 1)
                     {
                       // See the comments in Range::matrix_value.
-
-                      if ((increment > 0 && val > limit)
-                          || (increment < 0 && val < limit))
+                      if ((increment > 0 && val >= limit)
+                          || (increment < 0 && val <= limit))
                         val = limit;
                     }
 
--- a/libinterp/interpfcn/toplev.cc	Thu Feb 28 02:04:24 2013 -0500
+++ b/libinterp/interpfcn/toplev.cc	Wed Mar 06 16:43:33 2013 -0500
@@ -57,6 +57,7 @@
 #include "input.h"
 #include "lex.h"
 #include "oct-conf.h"
+#include "oct-conf-features.h"
 #include "oct-hist.h"
 #include "oct-map.h"
 #include "oct-obj.h"
@@ -98,9 +99,6 @@
 // TRUE means we've processed all the init code and we are good to go.
 bool octave_initialized = false;
 
-// Current command to execute.
-tree_statement_list *global_command = 0;
-
 octave_call_stack *octave_call_stack::instance = 0;
 
 void
@@ -564,8 +562,7 @@
   // octave_parser constructor sets this for us.
   frame.protect_var (CURR_LEXER);
 
-  octave_parser *curr_parser = new octave_parser ();
-  frame.add_fcn (octave_parser::cleanup, curr_parser);
+  octave_parser curr_parser;
 
   int retval = 0;
   do
@@ -576,7 +573,7 @@
 
           reset_error_handler ();
 
-          curr_parser->reset ();
+          curr_parser.reset ();
 
           if (symbol_table::at_top_level ())
             tree_evaluator::reset_debug_state ();
@@ -587,23 +584,13 @@
           symbol_table::scope_id scope = symbol_table::top_scope ();
           inner_frame.add_fcn (symbol_table::unmark_forced_variables, scope);
 
-          inner_frame.protect_var (global_command);
-
-          global_command = 0;
-
-          retval = curr_parser->run ();
+          retval = curr_parser.run ();
 
           if (retval == 0)
             {
-              if (global_command)
+              if (curr_parser.stmt_list)
                 {
-                  // Use an unwind-protect cleanup function so that the
-                  // global_command list will be deleted in the event of
-                  // an interrupt.
-
-                  frame.add_fcn (cleanup_statement_list, &global_command);
-
-                  global_command->accept (*current_evaluator);
+                  curr_parser.stmt_list->accept (*current_evaluator);
 
                   octave_quit ();
 
@@ -639,7 +626,7 @@
                         command_editor::increment_current_command_number ();
                     }
                 }
-              else if (curr_parser->end_of_input)
+              else if (curr_parser.curr_lexer->end_of_input)
                 break;
             }
         }
@@ -1373,7 +1360,6 @@
       { false, "SONAME_FLAGS", OCTAVE_CONF_SONAME_FLAGS },
       { false, "STATIC_LIBS", OCTAVE_CONF_STATIC_LIBS },
       { false, "TERM_LIBS", OCTAVE_CONF_TERM_LIBS },
-      { false, "UGLY_DEFS", OCTAVE_CONF_UGLY_DEFS },
       { false, "UMFPACK_CPPFLAGS", OCTAVE_CONF_UMFPACK_CPPFLAGS },
       { false, "UMFPACK_LDFLAGS", OCTAVE_CONF_UMFPACK_LDFLAGS },
       { false, "UMFPACK_LIBS", OCTAVE_CONF_UMFPACK_LIBS },
@@ -1442,6 +1428,8 @@
       m.assign ("words_little_endian",
                 octave_value (oct_mach_info::words_little_endian ()));
 
+      m.assign ("features", octave_value (octave_config_features ()));
+
       int i = 0;
 
       while (true)
--- a/libinterp/interpfcn/toplev.h	Thu Feb 28 02:04:24 2013 -0500
+++ b/libinterp/interpfcn/toplev.h	Wed Mar 06 16:43:33 2013 -0500
@@ -67,9 +67,6 @@
 extern OCTINTERP_API bool
 octave_remove_atexit_function (const std::string& fname);
 
-// Current command to execute.
-extern OCTINTERP_API tree_statement_list *global_command;
-
 // TRUE means we are ready to interpret commands, but not everything
 // is ready for interactive use.
 extern OCTINTERP_API bool octave_interpreter_ready;
--- a/libinterp/oct-conf.in.h	Thu Feb 28 02:04:24 2013 -0500
+++ b/libinterp/oct-conf.in.h	Wed Mar 06 16:43:33 2013 -0500
@@ -546,10 +546,6 @@
 #define OCTAVE_CONF_TERM_LIBS %OCTAVE_CONF_TERM_LIBS%
 #endif
 
-#ifndef OCTAVE_CONF_UGLY_DEFS
-#define OCTAVE_CONF_UGLY_DEFS %OCTAVE_CONF_UGLY_DEFS%
-#endif
-
 #ifndef OCTAVE_CONF_UMFPACK_CPPFLAGS
 #define OCTAVE_CONF_UMFPACK_CPPFLAGS %OCTAVE_CONF_UMFPACK_CPPFLAGS%
 #endif
--- a/libinterp/octave-value/ov-fcn-handle.cc	Thu Feb 28 02:04:24 2013 -0500
+++ b/libinterp/octave-value/ov-fcn-handle.cc	Wed Mar 06 16:43:33 2013 -0500
@@ -1304,7 +1304,8 @@
 %! hdld2 = hdld;
 %! hbi2 = hbi;
 %! modes = {"-text", "-binary"};
-%! if (!isempty (findstr (octave_config_info ("DEFS"), "HAVE_HDF5")))
+%! if (isfield (octave_config_info, "HAVE_HDF5")
+%!     && octave_config_info ("HAVE_HDF5"))
 %!   modes(end+1) = "-hdf5";
 %! endif
 %! for i = 1:numel (modes)
@@ -1356,7 +1357,8 @@
 %! hdld2 = hdld;
 %! hbi2 = hbi;
 %! modes = {"-text", "-binary"};
-%! if (!isempty (findstr (octave_config_info ("DEFS"), "HAVE_HDF5")))
+%! if (isfield (octave_config_info, "HAVE_HDF5")
+%!     && octave_config_info ("HAVE_HDF5"))
 %!   modes(end+1) = "-hdf5";
 %! endif
 %! for i = 1:numel (modes)
--- a/libinterp/octave.cc	Thu Feb 28 02:04:24 2013 -0500
+++ b/libinterp/octave.cc	Wed Mar 06 16:43:33 2013 -0500
@@ -356,10 +356,6 @@
 {
   unwind_protect frame;
 
-  frame.protect_var (input_from_startup_file);
-
-  input_from_startup_file = true;
-
   std::string context;
 
   bool verbose = (verbose_flag && ! inhibit_startup_message);
@@ -489,30 +485,18 @@
   octave_initialized = true;
 
   frame.protect_var (interactive);
-  frame.protect_var (reading_script_file);
-  frame.protect_var (input_from_command_line_file);
-
-  frame.protect_var (curr_fcn_file_name);
-  frame.protect_var (curr_fcn_file_full_name);
 
   frame.protect_var (octave_program_invocation_name);
   frame.protect_var (octave_program_name);
 
   interactive = false;
-  reading_script_file = true;
-  input_from_command_line_file = true;
 
-  curr_fcn_file_name = fname;
-  curr_fcn_file_full_name = curr_fcn_file_name;
+  octave_program_invocation_name = fname;
 
-  octave_program_invocation_name = curr_fcn_file_name;
-
-  size_t pos = curr_fcn_file_name.find_last_of (file_ops::dir_sep_chars ());
+  size_t pos = fname.find_last_of (file_ops::dir_sep_chars ());
 
-  std::string tmp = (pos != std::string::npos)
-    ? curr_fcn_file_name.substr (pos+1) : curr_fcn_file_name;
-
-  octave_program_name = tmp;
+  octave_program_name
+    = (pos != std::string::npos) ? fname.substr (pos+1) : fname;
 
   std::string context;
   bool verbose = false;
--- a/libinterp/parse-tree/lex.h	Thu Feb 28 02:04:24 2013 -0500
+++ b/libinterp/parse-tree/lex.h	Wed Mar 06 16:43:33 2013 -0500
@@ -27,6 +27,8 @@
 #include <set>
 #include <stack>
 
+#include "input.h"
+
 extern OCTINTERP_API void cleanup_parser (void);
 
 // Is the given string a keyword?
@@ -50,7 +52,7 @@
   stream_reader& operator = (const stream_reader&);
 };
 
-// Forward decl for lexical_feedback::token_stack.
+// Forward decl for octave_lexer::token_stack.
 class token;
 
 // For communication between the lexer and parser.
@@ -106,6 +108,12 @@
 
     ~bbp_nesting_level (void) { }
 
+    void reset (void)
+    {
+      while (! context.empty ())
+        context.pop ();
+    }
+
     void bracket (void) { context.push (BRACKET); }
 
     bool is_bracket (void)
@@ -151,9 +159,9 @@
 
     std::stack<int> context;
   };
-
+  
   lexical_feedback (void)
-    : scanner (0), convert_spaces_to_comma (true),
+    : end_of_input (false), convert_spaces_to_comma (true),
       do_comma_insert (false), at_beginning_of_statement (true),
       looking_at_anon_fcn_args (false), looking_at_return_list (false),
       looking_at_parameter_list (false), looking_at_decl_list (false),
@@ -162,13 +170,16 @@
       looking_for_object_index (false), 
       looking_at_indirect_ref (false), parsing_class_method (false),
       maybe_classdef_get_set_method (false), parsing_classdef (false),
-      quote_is_transpose (false),
+      quote_is_transpose (false), force_script (false),
+      reading_fcn_file (false), reading_script_file (false),
+      reading_classdef_file (false),
       input_line_number (1), current_input_column (1),
       bracketflag (0), braceflag (0),
       looping (0), defining_func (0), looking_at_function_handle (0),
-      block_comment_nesting_level (0),
+      block_comment_nesting_level (0), token_count (0),
+      help_text (), fcn_file_name (), fcn_file_full_name (),
       looking_at_object_index (), parsed_function_name (),
-      pending_local_variables (), nesting_level ()
+      pending_local_variables (), nesting_level (), token_stack ()
   {
     init ();
   }
@@ -179,13 +190,220 @@
 
   void reset (void);
 
-  void prep_for_script_file (void);
+  // true means that we have encountered eof on the input stream.
+  bool end_of_input;
+
+  // true means that we should convert spaces to a comma inside a
+  // matrix definition.
+  bool convert_spaces_to_comma;
+
+<<<<<<< local
+  void prep_for_classdef_file (void);
+=======
+  // gag.  stupid kludge so that [[1,2][3,4]] will work.
+  bool do_comma_insert;
+>>>>>>> other
+
+<<<<<<< local
+  int octave_read (char *buf, unsigned int max_size);
+=======
+  // true means we are at the beginning of a statement, where a
+  // command name is possible.
+  bool at_beginning_of_statement;
+
+  // true means we are parsing an anonymous function argument list.
+  bool looking_at_anon_fcn_args;
+
+  // true means we're parsing the return list for a function.
+  bool looking_at_return_list;
+
+  // true means we're parsing the parameter list for a function.
+  bool looking_at_parameter_list;
+
+  // true means we're parsing a declaration list (global or
+  // persistent).
+  bool looking_at_decl_list;
+
+  // true means we are looking at the initializer expression for a
+  // parameter list element.
+  bool looking_at_initializer_expression;
+
+  // true means we're parsing a matrix or the left hand side of
+  // multi-value assignment statement.
+  bool looking_at_matrix_or_assign_lhs;
+
+  // object index not possible until we've seen something.
+  bool looking_for_object_index;
+
+  // true means we're looking at an indirect reference to a
+  // structure element.
+  bool looking_at_indirect_ref;
+
+  // true means we are parsing a class method in function or classdef file.
+  bool parsing_class_method;
 
-  void prep_for_function_file (void);
+  // true means we are parsing a class method declaration line in a
+  // classdef file and can accept a property get or set method name.
+  // for example, "get.propertyname" is recognized as a function name.
+  bool maybe_classdef_get_set_method;
+
+  // true means we are parsing a classdef file
+  bool parsing_classdef;
+
+  // return transpose or start a string?
+  bool quote_is_transpose;
+
+  // TRUE means treat the current file as a script even if the first
+  // token is "function" or "classdef".
+  bool force_script;
+
+  // TRUE means we're parsing a function file.
+  bool reading_fcn_file;
+
+  // TRUE means we're parsing a script file.
+  bool reading_script_file;
+
+  // TRUE means we're parsing a classdef file.
+  bool reading_classdef_file;
+
+  // the current input line number.
+  int input_line_number;
+
+  // the column of the current token.
+  int current_input_column;
+
+  // square bracket level count.
+  int bracketflag;
+
+  // curly brace level count.
+  int braceflag;
+
+  // true means we're in the middle of defining a loop.
+  int looping;
+
+  // nonzero means we're in the middle of defining a function.
+  int defining_func;
+
+  // nonzero means we are parsing a function handle.
+  int looking_at_function_handle;
+
+  // nestng level for blcok comments.
+  int block_comment_nesting_level;
+
+  // Count of tokens recognized by this lexer since initialized or
+  // since the last reset.
+  size_t token_count;
+
+  // The current help text.
+  std::string help_text;
 
-  void prep_for_classdef_file (void);
+  // Simple name of function file we are reading.
+  std::string fcn_file_name;
+
+  // Full name of file we are reading.
+  std::string fcn_file_full_name;
+
+  // if the front of the list is true, the closest paren, brace, or
+  // bracket nesting is an index for an object.
+  std::list<bool> looking_at_object_index;
+
+  // if the top of the stack is true, then we've already seen the name
+  // of the current function.  should only matter if
+  // current_function_level > 0
+  std::stack<bool> parsed_function_name;
+
+  // set of identifiers that might be local variable names.
+  std::set<std::string> pending_local_variables;
+
+  // is the closest nesting level a square bracket, squiggly brace or
+  // a paren?
+  bbp_nesting_level nesting_level;
+
+  // Stack to hold tokens so that we can delete them when the parser is
+  // reset and avoid growing forever just because we are stashing some
+  // information.
+  std::stack <token*> token_stack;
+
+private:
+
+  void reset_token_stack (void);
+
+  // No copying!
+
+  lexical_feedback (const lexical_feedback&);
+
+  lexical_feedback& operator = (const lexical_feedback&);
+};
+
+// octave_lexer inherits from lexical_feedback because we will
+// eventually have several different constructors and it is easier to
+// intialize if everything is grouped in a parent class rather than
+// listing all the members in the octave_lexer class.
+
+class
+octave_lexer : public lexical_feedback
+{
+public:
+
+  // Handle buffering of input for lexer.
+
+  class input_buffer
+  {
+  public:
 
-  int octave_read (char *buf, unsigned int max_size);
+    input_buffer (void)
+      : buffer (), pos (0), chars_left (0), eof (false)
+    { }
+
+    void fill (const std::string& input, bool eof_arg);
+
+    // Copy at most max_size characters to buf.
+    int copy_chunk (char *buf, size_t max_size);
+
+    bool empty (void) const { return chars_left == 0; }
+
+    bool at_eof (void) const { return eof; }
+
+  private:
+
+    std::string buffer;
+    const char *pos;
+    size_t chars_left;
+    bool eof;
+  };
+
+  octave_lexer (void)
+    : lexical_feedback (), scanner (0), input_buf (), input_reader ()
+  {
+    init ();
+  }
+
+  octave_lexer (FILE *file)
+    : lexical_feedback (), scanner (0), input_buf (),
+      input_reader (file)
+  {
+    init ();
+  }
+
+  octave_lexer (const std::string& eval_string)
+    : lexical_feedback (), scanner (0), input_buf (),
+      input_reader (eval_string)
+  {
+    init ();
+  }
+
+  ~octave_lexer (void);
+
+  void init (void);
+
+  void reset (void);
+
+  void prep_for_file (void);
+
+  int read (char *buf, unsigned int max_size);
+
+  int handle_end_of_input (void);
+>>>>>>> other
 
   char *flex_yytext (void);
 
@@ -277,23 +495,27 @@
   // Internal state of the flex-generated lexer.
   void *scanner;
 
-  // TRUE means that we should convert spaces to a comma inside a
-  // matrix definition.
-  bool convert_spaces_to_comma;
+  // Object that reads and buffers input.
+  input_buffer input_buf;
+
+  octave_input_reader input_reader;
 
-  // GAG.  Stupid kludge so that [[1,2][3,4]] will work.
-  bool do_comma_insert;
+  std::string input_source (void) const
+  {
+    return input_reader.input_source ();
+  }
 
-  // TRUE means we are at the beginning of a statement, where a
-  // command name is possible.
-  bool at_beginning_of_statement;
+  bool input_from_terminal (void) const
+  {
+    return input_source () == "terminal";
+  }
 
-  // TRUE means we are parsing an anonymous function argument list.
-  bool looking_at_anon_fcn_args;
+  bool input_from_file (void) const
+  {
+    return input_source () == "file";
+  }
 
-  // TRUE means we're parsing the return list for a function.
-  bool looking_at_return_list;
-
+<<<<<<< local
   // TRUE means we're parsing the parameter list for a function.
   bool looking_at_parameter_list;
 
@@ -375,22 +597,23 @@
   // Is the closest nesting level a square bracket, squiggly brace or
   // a paren?
   bbp_nesting_level nesting_level;
+=======
+  bool input_from_eval_string (void) const
+  {
+    return input_source () == "eval_string";
+  }
+>>>>>>> other
 
   // For unwind protect.
-  static void cleanup (lexical_feedback *lexer) { delete lexer; }
+  static void cleanup (octave_lexer *lexer) { delete lexer; }
 
 private:
 
-  // Stack to hold tokens so that we can delete them when the parser is
-  // reset and avoid growing forever just because we are stashing some
-  // information.
-  std::stack <token*> token_stack;
-
   // No copying!
 
-  lexical_feedback (const lexical_feedback&);
+  octave_lexer (const octave_lexer&);
 
-  lexical_feedback& operator = (const lexical_feedback&);
+  octave_lexer& operator = (const octave_lexer&);
 };
 
 #endif
--- a/libinterp/parse-tree/lex.ll	Thu Feb 28 02:04:24 2013 -0500
+++ b/libinterp/parse-tree/lex.ll	Wed Mar 06 16:43:33 2013 -0500
@@ -46,9 +46,13 @@
 %s COMMAND_START
 %s MATRIX_START
 
+<<<<<<< local
 %x SCRIPT_FILE_BEGIN
 %x FUNCTION_FILE_BEGIN
 %x CLASSDEF_FILE_BEGIN
+=======
+%x INPUT_FILE_BEGIN
+>>>>>>> other
 
 %{
 
@@ -110,7 +114,7 @@
 #error lex.l requires flex version 2.5.4 or later
 #endif
 
-#define YY_EXTRA_TYPE lexical_feedback *
+#define YY_EXTRA_TYPE octave_lexer *
 #define curr_lexer yyextra
 
 // Arrange to get input via readline.
@@ -119,7 +123,7 @@
 #undef YY_INPUT
 #endif
 #define YY_INPUT(buf, result, max_size) \
-  result = curr_lexer->octave_read (buf, max_size)
+  result = curr_lexer->read (buf, max_size)
 
 // Try to avoid crashing out completely on fatal scanner errors.
 
@@ -148,7 +152,11 @@
 #define COUNT_TOK_AND_RETURN(tok) \
   do \
     { \
-      Vtoken_count++; \
+      if (tok != '\n') \
+        { \
+          Vtoken_count++; \
+          curr_lexer->token_count++; \
+        } \
       DISPLAY_TOK_AND_RETURN (tok); \
     } \
   while (0)
@@ -257,20 +265,17 @@
 // the parser go down a special path.
 %}
 
-<SCRIPT_FILE_BEGIN>. {
-    LEXER_DEBUG ("<SCRIPT_FILE_BEGIN>.");
+<INPUT_FILE_BEGIN>. {
+    LEXER_DEBUG ("<INPUT_FILE_BEGIN>.");
 
     BEGIN (INITIAL);
     curr_lexer->xunput (yytext[0]);
-    COUNT_TOK_AND_RETURN (SCRIPT_FILE);
-  }
-
-<FUNCTION_FILE_BEGIN>. {
-    LEXER_DEBUG ("<FUNCTION_FILE_BEGIN>.");
-
-    BEGIN (INITIAL);
-    curr_lexer->xunput (yytext[0]);
-    COUNT_TOK_AND_RETURN (FUNCTION_FILE);
+
+    // May be reset later if we see "function" or "classdef" appears
+    // as the first token.
+    curr_lexer->reading_script_file = true;
+
+    DISPLAY_TOK_AND_RETURN (INPUT_FILE);
   }
 
 <CLASSDEF_FILE_BEGIN>. {
@@ -362,7 +367,7 @@
     curr_lexer->at_beginning_of_statement = false;
 
     int c = yytext[yyleng-1];
-    bool cont_is_spc = (curr_lexer->eat_continuation () != lexical_feedback::NO_WHITESPACE);
+    bool cont_is_spc = (curr_lexer->eat_continuation () != octave_lexer::NO_WHITESPACE);
     bool spc_gobbled = (cont_is_spc || c == ' ' || c == '\t');
     int tok_to_return = curr_lexer->handle_close_bracket (spc_gobbled, ']');
 
@@ -388,7 +393,7 @@
     curr_lexer->at_beginning_of_statement = false;
 
     int c = yytext[yyleng-1];
-    bool cont_is_spc = (curr_lexer->eat_continuation () != lexical_feedback::NO_WHITESPACE);
+    bool cont_is_spc = (curr_lexer->eat_continuation () != octave_lexer::NO_WHITESPACE);
     bool spc_gobbled = (cont_is_spc || c == ' ' || c == '\t');
     int tok_to_return = curr_lexer->handle_close_bracket (spc_gobbled, '}');
 
@@ -418,7 +423,7 @@
 
     if (! curr_lexer->looking_at_object_index.front ())
       {
-        if ((tmp & lexical_feedback::NEWLINE) == lexical_feedback::NEWLINE)
+        if ((tmp & octave_lexer::NEWLINE) == octave_lexer::NEWLINE)
           {
             curr_lexer->maybe_warn_separator_insert (';');
 
@@ -455,7 +460,7 @@
             && curr_lexer->nesting_level.is_bracket_or_brace ()
             && curr_lexer->convert_spaces_to_comma)
           {
-            if ((tmp & lexical_feedback::NEWLINE) == lexical_feedback::NEWLINE)
+            if ((tmp & octave_lexer::NEWLINE) == octave_lexer::NEWLINE)
               {
                 curr_lexer->maybe_warn_separator_insert (';');
 
@@ -621,19 +626,7 @@
 %}
 
 <<EOF>> {
-    LEXER_DEBUG ("<<EOF>>");
-
-    if (curr_lexer->block_comment_nesting_level != 0)
-      {
-        warning ("block comment open at end of input");
-
-        if ((reading_fcn_file || reading_script_file || reading_classdef_file)
-            && ! curr_fcn_file_name.empty ())
-          warning ("near line %d of file '%s.m'",
-                   curr_lexer->input_line_number, curr_fcn_file_name.c_str ());
-      }
-
-    TOK_RETURN (END_OF_INPUT);
+   return curr_lexer->handle_end_of_input ();
   }
 
 %{
@@ -785,7 +778,7 @@
     int tok = curr_lexer->process_comment (false, eof);
 
     if (eof)
-      TOK_RETURN (END_OF_INPUT);
+      return curr_lexer->handle_end_of_input ();
     else if (tok > 0)
       COUNT_TOK_AND_RETURN (tok);
   }
@@ -984,7 +977,7 @@
         return LEXICAL_ERROR;
       }
     else
-      TOK_RETURN (END_OF_INPUT);
+      return curr_lexer->handle_end_of_input ();
   }
 
 %%
@@ -1293,7 +1286,7 @@
 flex_stream_reader : public stream_reader
 {
 public:
-  flex_stream_reader (lexical_feedback *l, char *buf_arg)
+  flex_stream_reader (octave_lexer *l, char *buf_arg)
     : stream_reader (), lexer (l), buf (buf_arg)
   { }
 
@@ -1308,13 +1301,75 @@
 
   flex_stream_reader& operator = (const flex_stream_reader&);
 
-  lexical_feedback *lexer;
+  octave_lexer *lexer;
 
   char *buf;
 };
 
 lexical_feedback::~lexical_feedback (void)
 {
+  reset_token_stack ();
+}
+
+void
+lexical_feedback::init (void)
+{
+  // The closest paren, brace, or bracket nesting is not an object
+  // index.
+  looking_at_object_index.push_front (false);
+}
+
+void
+lexical_feedback::reset (void)
+{
+  end_of_input = false;
+  convert_spaces_to_comma = true;
+  do_comma_insert = false;
+  at_beginning_of_statement = true;
+  looking_at_anon_fcn_args = false;
+  looking_at_return_list = false;
+  looking_at_parameter_list = false;
+  looking_at_decl_list = false;
+  looking_at_initializer_expression = false;
+  looking_at_matrix_or_assign_lhs = false;
+  looking_for_object_index = false; 
+  looking_at_indirect_ref = false;
+  parsing_class_method = false;
+  maybe_classdef_get_set_method = false;
+  parsing_classdef = false;
+  quote_is_transpose = false;
+  force_script = false;
+  reading_fcn_file = false;
+  reading_script_file = false;
+  reading_classdef_file = false;
+  input_line_number = 1;
+  current_input_column = 1;
+  bracketflag = 0;
+  braceflag = 0;
+  looping = 0;
+  defining_func = 0;
+  looking_at_function_handle = 0;
+  block_comment_nesting_level = 0;
+  token_count = 0;
+  help_text = "";
+  fcn_file_name = "";
+  fcn_file_full_name = "";
+  looking_at_object_index.clear ();
+  looking_at_object_index.push_front (false);
+
+  while (! parsed_function_name.empty ())
+    parsed_function_name.pop ();
+
+  pending_local_variables.clear ();
+
+  nesting_level.reset ();
+
+  reset_token_stack ();
+}
+
+void
+lexical_feedback::reset_token_stack (void)
+{
   // Clear out the stack of token info used to track line and
   // column numbers.
 
@@ -1323,27 +1378,70 @@
       delete token_stack.top ();
       token_stack.pop ();
     }
-
+}
+
+void
+octave_lexer::input_buffer::fill (const std::string& input, bool eof_arg)
+{
+  buffer = input;
+  chars_left = buffer.length ();
+  pos = buffer.c_str ();
+  eof = eof_arg;
+}
+
+int
+octave_lexer::input_buffer::copy_chunk (char *buf, size_t max_size)
+{
+  static const char * const eol = "\n";
+
+  size_t len = max_size > chars_left ? chars_left : max_size;
+  assert (len > 0);
+
+  memcpy (buf, pos, len);
+
+  chars_left -= len;
+  pos += len;
+
+  // Make sure input ends with a new line character.
+  if (chars_left == 0 && buf[len-1] != '\n')
+    {
+      if (len < max_size)
+        {
+          // There is enough room to plug the newline character in
+          // the buffer.
+          buf[len++] = '\n';
+        }
+      else
+        {
+          // There isn't enough room to plug the newline character
+          // in the buffer so arrange to have it returned on the next
+          // call to octave_lexer::read.
+          pos = eol;
+          chars_left = 1;
+        }
+    }
+
+  return len;
+}
+
+octave_lexer::~octave_lexer (void)
+{
   yylex_destroy (scanner);
 }
 
 void
-lexical_feedback::init (void)
+octave_lexer::init (void)
 {
-  // The closest paren, brace, or bracket nesting is not an object
-  // index.
-  looking_at_object_index.push_front (false);
-
   yylex_init (&scanner);
 
-  // Make lexical_feedback object available through yyextra in
+  // Make octave_lexer object available through yyextra in
   // flex-generated lexer.
   yyset_extra (this, scanner);
 }
 
 // Inside Flex-generated functions, yyg is the scanner cast to its real
 // type.  The BEGIN macro uses yyg and we want to use that in
-// lexical_feedback member functions.  If we could set the start state
+// octave_lexer member functions.  If we could set the start state
 // by calling a function instead of using the BEGIN macro, we could
 // eliminate the OCTAVE_YYG macro.
 
@@ -1351,7 +1449,7 @@
   struct yyguts_t *yyg = static_cast<struct yyguts_t*> (scanner)
 
 void
-lexical_feedback::reset (void)
+octave_lexer::reset (void)
 {
   OCTAVE_YYG;
 
@@ -1371,26 +1469,26 @@
       && ! (reading_fcn_file
             || reading_classdef_file
             || reading_script_file
-            || get_input_from_eval_string
-            || input_from_startup_file))
+            || input_from_eval_string ()))
     yyrestart (stdin, scanner);
 
-  // Clear the buffer for help text.
-  while (! help_buf.empty ())
-    help_buf.pop ();
+  lexical_feedback::reset ();
 }
 
 void
-lexical_feedback::prep_for_script_file (void)
+octave_lexer::prep_for_file (void)
 {
   OCTAVE_YYG;
 
-  BEGIN (SCRIPT_FILE_BEGIN);
+  reading_script_file = true;
+
+  BEGIN (INPUT_FILE_BEGIN);
 }
 
-void
-lexical_feedback::prep_for_function_file (void)
+int
+octave_lexer::read (char *buf, unsigned max_size)
 {
+<<<<<<< local
   OCTAVE_YYG;
 
   BEGIN (FUNCTION_FILE_BEGIN);
@@ -1413,69 +1511,60 @@
   static size_t chars_left = 0;
   static bool eof = false;
 
+=======
+>>>>>>> other
   int status = 0;
 
-  if (chars_left == 0)
-    {
-      pos = 0;
-
-      input_buf = get_user_input (eof);
-
-      chars_left = input_buf.length ();
-
-      pos = input_buf.c_str ();
-    }
-
-  if (chars_left > 0)
+  if (input_buf.empty ())
     {
-      size_t len = max_size > chars_left ? chars_left : max_size;
-      assert (len > 0);
-
-      memcpy (buf, pos, len);
-
-      chars_left -= len;
-      pos += len;
-
-      // Make sure input ends with a new line character.
-      if (chars_left == 0 && buf[len-1] != '\n')
-        {
-          if (len < max_size)
-            {
-              // There is enough room to plug the newline character in
-              // the buffer.
-              buf[len++] = '\n';
-            }
-          else
-            {
-              // There isn't enough room to plug the newline character
-              // in the buffer so make sure it is returned on the next
-              // octave_read call.
-              pos = eol;
-              chars_left = 1;
-            }
-        }
-
-      status = len;
+      bool eof = false;
+      std::string input = input_reader.get_input (eof);
+      input_buf.fill (input, eof);
     }
+
+  if (! input_buf.empty ())
+    status = input_buf.copy_chunk (buf, max_size);
   else
     {
       status = YY_NULL;
 
-      if (! eof)
-        fatal_error ("octave_read () in flex scanner failed");
+      if (! input_buf.at_eof ())
+        fatal_error ("octave_lexer::read () in flex scanner failed");
     }
 
   return status;
 }
 
+int
+octave_lexer::handle_end_of_input (void)
+{
+  // FIXME -- we need this because of the way TOK_RETURN is defined.  DO
+  // something better than that...
+  OCTAVE_YYG;
+
+  LEXER_DEBUG ("<<EOF>>");
+
+  if (block_comment_nesting_level != 0)
+    {
+      warning ("block comment open at end of input");
+
+      if ((reading_fcn_file || reading_script_file || reading_classdef_file)
+          && ! fcn_file_name.empty ())
+        warning ("near line %d of file '%s.m'",
+                 input_line_number, fcn_file_name.c_str ());
+    }
+
+  TOK_RETURN (END_OF_INPUT);
+}
+
 char *
-lexical_feedback::flex_yytext (void)
+octave_lexer::flex_yytext (void)
 {
   return yyget_text (scanner);
 }
 
 int
-lexical_feedback::flex_yyleng (void)
+octave_lexer::flex_yyleng (void)
 {
   return yyget_leng (scanner);
 }
@@ -1486,9 +1575,9 @@
 // that we insert a comma ahead of it.
 
 void
-lexical_feedback::do_comma_insert_check (void)
+octave_lexer::do_comma_insert_check (void)
 {
-  bool spc_gobbled = (eat_continuation () != lexical_feedback::NO_WHITESPACE);
+  bool spc_gobbled = (eat_continuation () != octave_lexer::NO_WHITESPACE);
 
   int c = text_yyinput ();
 
@@ -1502,7 +1591,7 @@
 }
 
 int
-lexical_feedback::text_yyinput (void)
+octave_lexer::text_yyinput (void)
 {
   int c = yyinput (scanner);
 
@@ -1540,23 +1629,26 @@
 }
 
 void
-lexical_feedback::xunput (char c, char *buf)
+octave_lexer::xunput (char c, char *buf)
 {
-  if (lexer_debug_flag)
+  if (c != EOF)
     {
-      std::cerr << "U: ";
-      display_character (c);
-      std::cerr << std::endl;
+      if (lexer_debug_flag)
+        {
+          std::cerr << "U: ";
+          display_character (c);
+          std::cerr << std::endl;
+        }
+
+      if (c == '\n')
+        input_line_number--;
+
+      yyunput (c, buf, scanner);
     }
-
-  if (c == '\n')
-    input_line_number--;
-
-  yyunput (c, buf, scanner);
 }
 
 void
-lexical_feedback::xunput (char c)
+octave_lexer::xunput (char c)
 {
   char *yytxt = flex_yytext ();
 
@@ -1567,7 +1659,7 @@
 // really looking at.
 
 void
-lexical_feedback::fixup_column_count (char *s)
+octave_lexer::fixup_column_count (char *s)
 {
   char c;
   while ((c = *s++) != '\0')
@@ -1583,7 +1675,7 @@
 }
 
 bool
-lexical_feedback::inside_any_object_index (void)
+octave_lexer::inside_any_object_index (void)
 {
   bool retval = false;
 
@@ -1603,7 +1695,7 @@
 // Handle keywords.  Return -1 if the keyword should be ignored.
 
 int
-lexical_feedback::is_keyword_token (const std::string& s)
+octave_lexer::is_keyword_token (const std::string& s)
 {
   int l = input_line_number;
   int c = current_input_column;
@@ -1631,11 +1723,11 @@
         case static_kw:
           if ((reading_fcn_file || reading_script_file
                || reading_classdef_file)
-              && ! curr_fcn_file_full_name.empty ())
+              && ! fcn_file_full_name.empty ())
             warning_with_id ("Octave:deprecated-keyword",
                              "the 'static' keyword is obsolete and will be removed from a future version of Octave; please use 'persistent' instead; near line %d of file '%s'",
                              input_line_number,
-                             curr_fcn_file_full_name.c_str ());
+                             fcn_file_full_name.c_str ());
           else
             warning_with_id ("Octave:deprecated-keyword",
                              "the 'static' keyword is obsolete and will be removed from a future version of Octave; please use 'persistent' instead; near line %d",
@@ -1774,6 +1866,12 @@
         case classdef_kw:
           // 'classdef' is always a keyword.
           promptflag--;
+
+          if (! force_script && token_count == 0 && input_from_file ())
+            {
+              reading_classdef_file = true;
+              reading_script_file = false;
+            }
           break;
 
         case function_kw:
@@ -1782,6 +1880,12 @@
           defining_func++;
           parsed_function_name.push (false);
 
+          if (! force_script && token_count == 0 && input_from_file ())
+            {
+              reading_fcn_file = true;
+              reading_script_file = false;
+            }
+
           if (! (reading_fcn_file || reading_script_file
                  || reading_classdef_file))
             input_line_number = 1;
@@ -1791,8 +1895,8 @@
           {
             if ((reading_fcn_file || reading_script_file
                  || reading_classdef_file)
-                && ! curr_fcn_file_full_name.empty ())
-              tok_val = new token (curr_fcn_file_full_name, l, c);
+                && ! fcn_file_full_name.empty ())
+              tok_val = new token (fcn_file_full_name, l, c);
             else
               tok_val = new token ("stdin", l, c);
           }
@@ -1818,7 +1922,7 @@
 }
 
 bool
-lexical_feedback::is_variable (const std::string& name)
+octave_lexer::is_variable (const std::string& name)
 {
   return (symbol_table::is_variable (name)
           || (pending_local_variables.find (name)
@@ -1826,7 +1930,7 @@
 }
 
 std::string
-lexical_feedback::grab_block_comment (stream_reader& reader, bool& eof)
+octave_lexer::grab_block_comment (stream_reader& reader, bool& eof)
 {
   std::string buf;
 
@@ -1932,8 +2036,8 @@
 }
 
 std::string
-lexical_feedback::grab_comment_block (stream_reader& reader, bool at_bol,
-                                      bool& eof)
+octave_lexer::grab_comment_block (stream_reader& reader, bool at_bol,
+                                  bool& eof)
 {
   std::string buf;
 
@@ -2071,18 +2175,28 @@
   return buf;
 }
 
+static bool
+looks_like_copyright (const std::string& s)
+{
+  bool retval = false;
+
+  if (! s.empty ())
+    {
+      size_t offset = s.find_first_not_of (" \t");
+
+      retval = (s.substr (offset, 9) == "Copyright" || s.substr (offset, 6) == "Author");
+    }
+
+  return retval;
+}
+
 int
-lexical_feedback::process_comment (bool start_in_block, bool& eof)
+octave_lexer::process_comment (bool start_in_block, bool& eof)
 {
   OCTAVE_YYG;
 
   eof = false;
 
-  std::string help_txt;
-
-  if (! help_buf.empty ())
-    help_txt = help_buf.top ();
-
   char *yytxt = flex_yytext ();
   flex_stream_reader flex_reader (this, yytxt);
 
@@ -2096,13 +2210,9 @@
   if (lexer_debug_flag)
     std::cerr << "C: " << txt << std::endl;
 
-  if (help_txt.empty () && nesting_level.none ())
-    {
-      if (! help_buf.empty ())
-        help_buf.pop ();
-
-      help_buf.push (txt);
-    }
+  if (nesting_level.none () && help_text.empty () && ! txt.empty ()
+      && ! looks_like_copyright (txt))
+    help_text = txt;
 
   octave_comment_buffer::append (txt);
 
@@ -2126,7 +2236,7 @@
 // replaced by a single LF.
 
 bool
-lexical_feedback::next_token_is_sep_op (void)
+octave_lexer::next_token_is_sep_op (void)
 {
   bool retval = false;
 
@@ -2143,7 +2253,7 @@
 // unary operator.  This is ugly, but it seems to do the right thing.
 
 bool
-lexical_feedback::next_token_is_postfix_unary_op (bool spc_prev)
+octave_lexer::next_token_is_postfix_unary_op (bool spc_prev)
 {
   bool un_op = false;
 
@@ -2190,7 +2300,7 @@
 // parsed as a binary operator.
 
 bool
-lexical_feedback::next_token_is_bin_op (bool spc_prev)
+octave_lexer::next_token_is_bin_op (bool spc_prev)
 {
   bool bin_op = false;
 
@@ -2291,7 +2401,7 @@
 // FIXME -- we need to handle block comments here.
 
 void
-lexical_feedback::scan_for_comments (const char *text)
+octave_lexer::scan_for_comments (const char *text)
 {
   std::string comment_buf;
 
@@ -2352,9 +2462,9 @@
 // FIXME -- we need to handle block comments here.
 
 int
-lexical_feedback::eat_whitespace (void)
+octave_lexer::eat_whitespace (void)
 {
-  int retval = lexical_feedback::NO_WHITESPACE;
+  int retval = octave_lexer::NO_WHITESPACE;
 
   std::string comment_buf;
 
@@ -2376,11 +2486,11 @@
               comment_buf += static_cast<char> (c);
               beginning_of_comment = false;
             }
-          retval |= lexical_feedback::SPACE_OR_TAB;
+          retval |= octave_lexer::SPACE_OR_TAB;
           break;
 
         case '\n':
-          retval |= lexical_feedback::NEWLINE;
+          retval |= octave_lexer::NEWLINE;
           if (in_comment)
             {
               comment_buf += static_cast<char> (c);
@@ -2465,7 +2575,7 @@
 }
 
 void
-lexical_feedback::handle_number (void)
+octave_lexer::handle_number (void)
 {
   double value = 0.0;
   int nread = 0;
@@ -2523,7 +2633,7 @@
 // FIXME -- we need to handle block comments here.
 
 bool
-lexical_feedback::have_continuation (bool trailing_comments_ok)
+octave_lexer::have_continuation (bool trailing_comments_ok)
 {
   std::ostringstream buf;
 
@@ -2611,7 +2721,7 @@
 // line character.
 
 bool
-lexical_feedback::have_ellipsis_continuation (bool trailing_comments_ok)
+octave_lexer::have_ellipsis_continuation (bool trailing_comments_ok)
 {
   char c1 = text_yyinput ();
   if (c1 == '.')
@@ -2635,9 +2745,9 @@
 // whitespace on the next line.
 
 int
-lexical_feedback::eat_continuation (void)
+octave_lexer::eat_continuation (void)
 {
-  int retval = lexical_feedback::NO_WHITESPACE;
+  int retval = octave_lexer::NO_WHITESPACE;
 
   int c = text_yyinput ();
 
@@ -2651,7 +2761,7 @@
 }
 
 int
-lexical_feedback::handle_string (char delim)
+octave_lexer::handle_string (char delim)
 {
   std::ostringstream buf;
 
@@ -2744,7 +2854,7 @@
 }
 
 bool
-lexical_feedback::next_token_is_assign_op (void)
+octave_lexer::next_token_is_assign_op (void)
 {
   bool retval = false;
 
@@ -2828,7 +2938,7 @@
 }
 
 bool
-lexical_feedback::next_token_is_index_op (void)
+octave_lexer::next_token_is_index_op (void)
 {
   int c = text_yyinput ();
   xunput (c);
@@ -2836,7 +2946,7 @@
 }
 
 int
-lexical_feedback::handle_close_bracket (bool spc_gobbled, int bracket_type)
+octave_lexer::handle_close_bracket (bool spc_gobbled, int bracket_type)
 {
   OCTAVE_YYG;
 
@@ -2904,7 +3014,7 @@
 }
 
 void
-lexical_feedback::maybe_unput_comma (int spc_gobbled)
+octave_lexer::maybe_unput_comma (int spc_gobbled)
 {
   if (nesting_level.is_bracket ()
       || (nesting_level.is_brace ()
@@ -2943,7 +3053,7 @@
 }
 
 bool
-lexical_feedback::next_token_can_follow_bin_op (void)
+octave_lexer::next_token_can_follow_bin_op (void)
 {
   std::stack<char> buf;
 
@@ -2985,7 +3095,7 @@
 }
 
 bool
-lexical_feedback::looks_like_command_arg (void)
+octave_lexer::looks_like_command_arg (void)
 {
   bool retval = true;
 
@@ -3207,7 +3317,7 @@
 }
 
 int
-lexical_feedback::handle_superclass_identifier (void)
+octave_lexer::handle_superclass_identifier (void)
 {
   char *yytxt = flex_yytext ();
   int c = yytxt[flex_yyleng()-1];
@@ -3249,7 +3359,7 @@
 }
 
 int
-lexical_feedback::handle_meta_identifier (void)
+octave_lexer::handle_meta_identifier (void)
 {
   char *yytxt = flex_yytext ();
   int c = yytxt[flex_yyleng()-1];
@@ -3290,7 +3400,7 @@
 // should be ignored.
 
 int
-lexical_feedback::handle_identifier (void)
+octave_lexer::handle_identifier (void)
 {
   OCTAVE_YYG;
 
@@ -3302,7 +3412,7 @@
 
   int c = yytxt[flex_yyleng()-1];
 
-  bool cont_is_spc = (eat_continuation () != lexical_feedback::NO_WHITESPACE);
+  bool cont_is_spc = (eat_continuation () != octave_lexer::NO_WHITESPACE);
 
   int spc_gobbled = (cont_is_spc || c == ' ' || c == '\t');
 
@@ -3459,9 +3569,9 @@
 }
 
 void
-lexical_feedback::maybe_warn_separator_insert (char sep)
+octave_lexer::maybe_warn_separator_insert (char sep)
 {
-  std::string nm = curr_fcn_file_full_name;
+  std::string nm = fcn_file_full_name;
 
   if (nm.empty ())
     warning_with_id ("Octave:separator-insert",
@@ -3474,9 +3584,9 @@
 }
 
 void
-lexical_feedback::gripe_single_quote_string (void)
+octave_lexer::gripe_single_quote_string (void)
 {
-  std::string nm = curr_fcn_file_full_name;
+  std::string nm = fcn_file_full_name;
 
   if (nm.empty ())
     warning_with_id ("Octave:single-quote-string",
@@ -3489,9 +3599,9 @@
 }
 
 void
-lexical_feedback::gripe_matlab_incompatible (const std::string& msg)
+octave_lexer::gripe_matlab_incompatible (const std::string& msg)
 {
-  std::string nm = curr_fcn_file_full_name;
+  std::string nm = fcn_file_full_name;
 
   if (nm.empty ())
     warning_with_id ("Octave:matlab-incompatible",
@@ -3504,20 +3614,20 @@
 }
 
 void
-lexical_feedback::maybe_gripe_matlab_incompatible_comment (char c)
+octave_lexer::maybe_gripe_matlab_incompatible_comment (char c)
 {
   if (c == '#')
     gripe_matlab_incompatible ("# used as comment character");
 }
 
 void
-lexical_feedback::gripe_matlab_incompatible_continuation (void)
+octave_lexer::gripe_matlab_incompatible_continuation (void)
 {
   gripe_matlab_incompatible ("\\ used as line continuation marker");
 }
 
 void
-lexical_feedback::gripe_matlab_incompatible_operator (const std::string& op)
+octave_lexer::gripe_matlab_incompatible_operator (const std::string& op)
 {
   std::string t = op;
   int n = t.length ();
@@ -3527,7 +3637,7 @@
 }
 
 void
-lexical_feedback::push_token (token *tok)
+octave_lexer::push_token (token *tok)
 {
   YYSTYPE *lval = yyget_lval (scanner);
   lval->tok_val = tok;
@@ -3535,14 +3645,14 @@
 }
 
 token *
-lexical_feedback::current_token (void)
+octave_lexer::current_token (void)
 {
   YYSTYPE *lval = yyget_lval (scanner);
   return lval->tok_val;
 }
 
 void
-lexical_feedback::display_token (int tok)
+octave_lexer::display_token (int tok)
 {
   switch (tok)
     {
@@ -3655,9 +3765,13 @@
     case LEXICAL_ERROR: std::cerr << "LEXICAL_ERROR\n\n"; break;
     case FCN: std::cerr << "FCN\n"; break;
     case CLOSE_BRACE: std::cerr << "CLOSE_BRACE\n"; break;
+<<<<<<< local
     case SCRIPT_FILE: std::cerr << "SCRIPT_FILE\n"; break;
     case FUNCTION_FILE: std::cerr << "FUNCTION_FILE\n"; break;
     case CLASSDEF_FILE: std::cerr << "CLASSDEF_FILE\n"; break;
+=======
+    case INPUT_FILE: std::cerr << "INPUT_FILE\n"; break;
+>>>>>>> other
     case SUPERCLASSREF: std::cerr << "SUPERCLASSREF\n"; break;
     case METAQUERY: std::cerr << "METAQUERY\n"; break;
     case GET: std::cerr << "GET\n"; break;
@@ -3671,7 +3785,7 @@
     case '\t': std::cerr << "TAB\n"; break;
     default:
       {
-        if (tok < 256)
+        if (tok < 256 && tok > 31)
           std::cerr << static_cast<char> (tok) << "\n";
         else
           std::cerr << "UNKNOWN(" << tok << ")\n";
@@ -3699,12 +3813,8 @@
       std::cerr << "MATRIX_START" << std::endl;
       break;
 
-    case SCRIPT_FILE_BEGIN:
-      std::cerr << "SCRIPT_FILE_BEGIN" << std::endl;
-      break;
-
-    case FUNCTION_FILE_BEGIN:
-      std::cerr << "FUNCTION_FILE_BEGIN" << std::endl;
+    case INPUT_FILE_BEGIN:
+      std::cerr << "INPUT_FILE_BEGIN" << std::endl;
       break;
 
     case CLASSDEF_FILE_BEGIN:
@@ -3718,7 +3828,7 @@
 }
 
 void
-lexical_feedback::fatal_error (const char *msg)
+octave_lexer::fatal_error (const char *msg)
 {
   error (msg);
 
@@ -3728,7 +3838,7 @@
 }
 
 void
-lexical_feedback::lexer_debug (const char *pattern, const char *text)
+octave_lexer::lexer_debug (const char *pattern, const char *text)
 {
   OCTAVE_YYG;
 
--- a/libinterp/parse-tree/module.mk	Thu Feb 28 02:04:24 2013 -0500
+++ b/libinterp/parse-tree/module.mk	Wed Mar 06 16:43:33 2013 -0500
@@ -96,6 +96,18 @@
 	mv $@-t $@
 	rm -f $@-t1
 
+parse-tree/oct-parse.yy: parse-tree/oct-parse.in.yy
+	case "$(BISON_PUSH_PULL_DECL_STYLE)" in \
+          *quote*) quote='"' ;; \
+	  *) quote="" ;; \
+        esac; \
+        case "$(BISON_PUSH_PULL_DECL_STYLE)" in \
+          *dash*) decl="%define api.push-pull $${quote}both$${quote}"; ;; \
+          *underscore*) decl="%define api.push_pull $${quote}both$${quote}"; ;; \
+        esac; \
+	$(SED) "s/%PUSH_PULL_DECL%/$$decl/" $< > $@-t
+	mv $@-t $@
+
 noinst_LTLIBRARIES += parse-tree/libparse-tree.la
 
 parse_tree_libparse_tree_la_SOURCES = $(PARSE_TREE_SRC)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/parse-tree/oct-parse.in.yy	Wed Mar 06 16:43:33 2013 -0500
@@ -0,0 +1,4696 @@
+/*
+
+Copyright (C) 1993-2012 John W. Eaton
+Copyright (C) 2009 David Grundberg
+Copyright (C) 2009-2010 VZLU Prague
+
+This file is part of Octave.
+
+Octave 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 3 of the License, or (at your
+option) any later version.
+
+Octave 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 Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+// Parser for Octave.
+
+// C decarations.
+
+%{
+#define YYDEBUG 1
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <cassert>
+#include <cstdio>
+#include <cstdlib>
+
+#include <iostream>
+#include <map>
+#include <sstream>
+
+#include "Cell.h"
+#include "Matrix.h"
+#include "cmd-edit.h"
+#include "cmd-hist.h"
+#include "file-ops.h"
+#include "file-stat.h"
+#include "oct-env.h"
+#include "oct-time.h"
+#include "quit.h"
+
+#include "comment-list.h"
+#include "defaults.h"
+#include "defun.h"
+#include "dirfns.h"
+#include "dynamic-ld.h"
+#include "error.h"
+#include "input.h"
+#include "lex.h"
+#include "load-path.h"
+#include "oct-hist.h"
+#include "oct-map.h"
+#include "ov-classdef.h"
+#include "ov-fcn-handle.h"
+#include "ov-usr-fcn.h"
+#include "ov-null-mat.h"
+#include "toplev.h"
+#include "pager.h"
+#include "parse.h"
+#include "parse-private.h"
+#include "pt-all.h"
+#include "pt-eval.h"
+#include "pt-funcall.h"
+#include "symtab.h"
+#include "token.h"
+#include "unwind-prot.h"
+#include "utils.h"
+#include "variables.h"
+
+// oct-parse.h must be included after pt-all.h
+#include <oct-parse.h>
+
+extern int octave_lex (YYSTYPE *, void *);
+
+// Global access to currently active lexer.
+// FIXME -- to be removed after more parser+lexer refactoring.
+octave_lexer *CURR_LEXER = 0;
+
+#if defined (GNULIB_NAMESPACE)
+// Calls to the following functions appear in the generated output from
+// Bison without the namespace tag.  Redefine them so we will use them
+// via the gnulib namespace.
+#define fclose GNULIB_NAMESPACE::fclose
+#define fprintf GNULIB_NAMESPACE::fprintf
+#define malloc GNULIB_NAMESPACE::malloc
+#endif
+
+// TRUE means we are using readline.
+// (--no-line-editing)
+bool line_editing = true;
+
+// TRUE means we printed messages about reading startup files.
+bool reading_startup_message_printed = false;
+
+// Keep track of symbol table information when parsing functions.
+symtab_context parser_symtab_context;
+
+// List of autoloads (function -> file mapping).
+static std::map<std::string, std::string> autoload_map;
+
+// Forward declarations for some functions defined at the bottom of
+// the file.
+
+static void yyerror (octave_parser& curr_parser, const char *s);
+
+// Finish building a statement.
+template <class T>
+static tree_statement *
+make_statement (T *arg)
+{
+  octave_comment_list *comment = octave_comment_buffer::get_comment ();
+
+  return new tree_statement (arg, comment);
+}
+
+#define ABORT_PARSE \
+  do \
+    { \
+      yyerrok; \
+      if (! parser_symtab_context.empty ()) \
+        parser_symtab_context.pop (); \
+      if ((interactive || forced_interactive)   \
+          && ! (curr_lexer)->input_from_eval_string ()) \
+        YYACCEPT; \
+      else \
+        YYABORT; \
+    } \
+  while (0)
+
+#define curr_lexer curr_parser.curr_lexer
+#define scanner curr_lexer->scanner
+
+%}
+
+// Bison declarations.
+
+// Don't add spaces around the = here; it causes some versions of
+// bison to fail to properly recognize the directive.
+
+%name-prefix="octave_"
+
+// We are using the pure parser interface and the reentrant lexer
+// interface but the Octave parser and lexer are NOT properly
+// reentrant because both still use many global variables.  It should be
+// safe to create a parser object and call it while anotehr parser
+// object is active (to parse a callback function while the main
+// interactive parser is waiting for input, for example) if you take
+// care to properly save and restore (typically with an unwind_protect
+// object) relevant global values before and after the nested call.
+
+%define api.pure
+%PUSH_PULL_DECL%
+%parse-param { octave_parser& curr_parser }
+%lex-param { void *scanner }
+
+%union
+{
+  // The type of the basic tokens returned by the lexer.
+  token *tok_val;
+
+  // Comment strings that we need to deal with mid-rule.
+  octave_comment_list *comment_type;
+
+  // Types for the nonterminals we generate.
+  char sep_type;
+  token *tok_type;
+  tree *tree_type;
+  tree_matrix *tree_matrix_type;
+  tree_cell *tree_cell_type;
+  tree_expression *tree_expression_type;
+  tree_constant *tree_constant_type;
+  tree_fcn_handle *tree_fcn_handle_type;
+  tree_funcall *tree_funcall_type;
+  tree_function_def *tree_function_def_type;
+  tree_anon_fcn_handle *tree_anon_fcn_handle_type;
+  tree_identifier *tree_identifier_type;
+  tree_index_expression *tree_index_expression_type;
+  tree_colon_expression *tree_colon_expression_type;
+  tree_argument_list *tree_argument_list_type;
+  tree_parameter_list *tree_parameter_list_type;
+  tree_command *tree_command_type;
+  tree_if_command *tree_if_command_type;
+  tree_if_clause *tree_if_clause_type;
+  tree_if_command_list *tree_if_command_list_type;
+  tree_switch_command *tree_switch_command_type;
+  tree_switch_case *tree_switch_case_type;
+  tree_switch_case_list *tree_switch_case_list_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;
+  octave_user_function *octave_user_function_type;
+
+  tree_classdef *tree_classdef_type;
+  tree_classdef_attribute* tree_classdef_attribute_type;
+  tree_classdef_attribute_list* tree_classdef_attribute_list_type;
+  tree_classdef_superclass* tree_classdef_superclass_type;
+  tree_classdef_superclass_list* tree_classdef_superclass_list_type;
+  tree_classdef_body* tree_classdef_body_type;
+  tree_classdef_property* tree_classdef_property_type;
+  tree_classdef_property_list* tree_classdef_property_list_type;
+  tree_classdef_properties_block* tree_classdef_properties_block_type;
+  tree_classdef_methods_list* tree_classdef_methods_list_type;
+  tree_classdef_methods_block* tree_classdef_methods_block_type;
+  tree_classdef_event* tree_classdef_event_type;
+  tree_classdef_events_list* tree_classdef_events_list_type;
+  tree_classdef_events_block* tree_classdef_events_block_type;
+  tree_classdef_enum* tree_classdef_enum_type;
+  tree_classdef_enum_list* tree_classdef_enum_list_type;
+  tree_classdef_enum_block* tree_classdef_enum_block_type;
+}
+
+// Tokens with line and column information.
+%token <tok_val> '=' ':' '-' '+' '*' '/'
+%token <tok_val> ADD_EQ SUB_EQ MUL_EQ DIV_EQ LEFTDIV_EQ POW_EQ
+%token <tok_val> EMUL_EQ EDIV_EQ ELEFTDIV_EQ EPOW_EQ AND_EQ OR_EQ
+%token <tok_val> LSHIFT_EQ RSHIFT_EQ LSHIFT RSHIFT
+%token <tok_val> EXPR_AND_AND EXPR_OR_OR
+%token <tok_val> EXPR_AND EXPR_OR EXPR_NOT
+%token <tok_val> EXPR_LT EXPR_LE EXPR_EQ EXPR_NE EXPR_GE EXPR_GT
+%token <tok_val> LEFTDIV EMUL EDIV ELEFTDIV EPLUS EMINUS
+%token <tok_val> QUOTE TRANSPOSE
+%token <tok_val> PLUS_PLUS MINUS_MINUS POW EPOW
+%token <tok_val> NUM IMAG_NUM
+%token <tok_val> STRUCT_ELT
+%token <tok_val> NAME
+%token <tok_val> END
+%token <tok_val> DQ_STRING SQ_STRING
+%token <tok_val> FOR PARFOR WHILE DO UNTIL
+%token <tok_val> IF ELSEIF ELSE
+%token <tok_val> SWITCH CASE OTHERWISE
+%token <tok_val> BREAK CONTINUE FUNC_RET
+%token <tok_val> UNWIND CLEANUP
+%token <tok_val> TRY CATCH
+%token <tok_val> GLOBAL PERSISTENT
+%token <tok_val> FCN_HANDLE
+%token <tok_val> CLASSDEF
+%token <tok_val> PROPERTIES METHODS EVENTS ENUMERATION
+%token <tok_val> METAQUERY
+%token <tok_val> SUPERCLASSREF
+%token <tok_val> GET SET
+
+// Other tokens.
+%token END_OF_INPUT LEXICAL_ERROR
+<<<<<<< local
+%token FCN SCRIPT_FILE CLASSDEF_FILE FUNCTION_FILE
+=======
+%token FCN INPUT_FILE CLASSDEF
+>>>>>>> other
+// %token VARARGIN VARARGOUT
+%token CLOSE_BRACE
+
+// Nonterminals we construct.
+<<<<<<< local
+%type <comment_type> stash_comment function_beg
+%type <tok_type> classdef_beg
+%type <sep_type> sep_no_nl opt_sep_no_nl sep opt_sep opt_comma
+=======
+%type <comment_type> stash_comment function_beg classdef_beg
+%type <comment_type> properties_beg methods_beg events_beg enum_beg
+%type <sep_type> sep_no_nl opt_sep_no_nl nl opt_nl sep opt_sep opt_comma
+>>>>>>> other
+%type <tree_type> input
+%type <tree_constant_type> string constant magic_colon
+%type <tree_anon_fcn_handle_type> anon_fcn_handle
+%type <tree_fcn_handle_type> fcn_handle
+%type <tree_matrix_type> matrix_rows matrix_rows1
+%type <tree_cell_type> cell_rows cell_rows1
+%type <tree_expression_type> matrix cell
+%type <tree_expression_type> primary_expr oper_expr
+%type <tree_expression_type> simple_expr colon_expr assign_expr expression
+%type <tree_identifier_type> identifier fcn_name magic_tilde
+%type <tree_funcall_type> superclass_identifier meta_identifier
+%type <octave_user_function_type> function1 function2
+%type <tree_index_expression_type> word_list_cmd
+%type <tree_colon_expression_type> colon_expr1
+%type <tree_argument_list_type> arg_list word_list assign_lhs
+%type <tree_argument_list_type> cell_or_matrix_row
+%type <tree_parameter_list_type> param_list param_list1 param_list2
+%type <tree_parameter_list_type> return_list return_list1
+%type <tree_command_type> command select_command loop_command
+<<<<<<< local
+%type <tree_command_type> jump_command except_command
+%type <tree_function_def_type> function
+%type <tree_classdef_type> classdef
+%type <tree_command_type> script_file classdef_file
+%type <tree_command_type> function_file function_list
+=======
+%type <tree_command_type> jump_command except_command function
+%type <tree_command_type> file classdef
+>>>>>>> other
+%type <tree_if_command_type> if_command
+%type <tree_if_clause_type> elseif_clause else_clause
+%type <tree_if_command_list_type> if_cmd_list1 if_cmd_list
+%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_decl_elt_type> decl2
+%type <tree_decl_init_list_type> decl1
+%type <tree_decl_command_type> declaration
+%type <tree_statement_type> statement function_end
+%type <tree_statement_list_type> simple_list simple_list1 list list1
+%type <tree_statement_list_type> opt_list input1
+
+%type <tree_classdef_attribute_type> attr
+%type <tree_classdef_attribute_list_type> attr_list opt_attr_list
+%type <tree_classdef_superclass_type> superclass
+%type <tree_classdef_superclass_list_type> superclass_list opt_superclass_list
+%type <tree_classdef_body_type> class_body
+%type <tree_classdef_property_type> class_property
+%type <tree_classdef_property_list_type> property_list
+%type <tree_classdef_properties_block_type> properties_block
+%type <tree_classdef_methods_list_type> methods_list
+%type <tree_classdef_methods_block_type> methods_block
+%type <tree_classdef_event_type> class_event
+%type <tree_classdef_events_list_type> events_list
+%type <tree_classdef_events_block_type> events_block
+%type <tree_classdef_enum_type> class_enum
+%type <tree_classdef_enum_list_type> enum_list
+%type <tree_classdef_enum_block_type> enum_block
+
+// Precedence and associativity.
+%right '=' ADD_EQ SUB_EQ MUL_EQ DIV_EQ LEFTDIV_EQ POW_EQ EMUL_EQ EDIV_EQ ELEFTDIV_EQ EPOW_EQ OR_EQ AND_EQ LSHIFT_EQ RSHIFT_EQ
+%left EXPR_OR_OR
+%left EXPR_AND_AND
+%left EXPR_OR
+%left EXPR_AND
+%left EXPR_LT EXPR_LE EXPR_EQ EXPR_NE EXPR_GE EXPR_GT
+%left LSHIFT RSHIFT
+%left ':'
+%left '-' '+' EPLUS EMINUS
+%left '*' '/' LEFTDIV EMUL EDIV ELEFTDIV
+%right UNARY EXPR_NOT
+%left POW EPOW QUOTE TRANSPOSE
+%right PLUS_PLUS MINUS_MINUS
+%left '(' '.' '{'
+
+// Where to start.
+%start input
+
+%%
+
+// ==============================
+// Statements and statement lists
+// ==============================
+
+input           : input1
+                  {
+                    curr_parser.stmt_list = $1;
+                    promptflag = 1;
+                    YYACCEPT;
+                  }
+<<<<<<< local
+                | function_file
+                  { YYACCEPT; }
+                | classdef_file
+                  { YYACCEPT; }
+=======
+>>>>>>> other
+                | simple_list parse_error
+                  { ABORT_PARSE; }
+                | parse_error
+                  { ABORT_PARSE; }
+                ;
+
+input1          : '\n'
+                  { $$ = 0; }
+                | END_OF_INPUT
+                  {
+                    curr_lexer->end_of_input = true;
+                    $$ = 0;
+                  }
+                | simple_list
+                  { $$ = $1; }
+                | simple_list '\n'
+                  { $$ = $1; }
+                | simple_list END_OF_INPUT
+                  { $$ = $1; }
+                ;
+
+simple_list     : simple_list1 opt_sep_no_nl
+                  { $$ = curr_parser.set_stmt_print_flag ($1, $2, false); }
+                ;
+
+simple_list1    : statement
+                  { $$ = curr_parser.make_statement_list ($1); }
+                | simple_list1 sep_no_nl statement
+                  { $$ = curr_parser.append_statement_list ($1, $2, $3, false); }
+                ;
+
+opt_list        : // empty
+                  { $$ = new tree_statement_list (); }
+                | list
+                  { $$ = $1; }
+                ;
+
+list            : list1 opt_sep
+                  { $$ = curr_parser.set_stmt_print_flag ($1, $2, true); }
+                ;
+
+list1           : statement
+                  { $$ = curr_parser.make_statement_list ($1); }
+                | list1 sep statement
+                  { $$ = curr_parser.append_statement_list ($1, $2, $3, true); }
+                ;
+
+statement       : expression
+                  { $$ = make_statement ($1); }
+                | command
+                  { $$ = make_statement ($1); }
+                | word_list_cmd
+                  { $$ = make_statement ($1); }
+                ;
+
+// =================
+// Word-list command
+// =================
+
+// These are not really like expressions since they can't appear on
+// the RHS of an assignment.  But they are also not like commands (IF,
+// WHILE, etc.
+
+word_list_cmd   : identifier word_list
+                  { $$ = curr_parser.make_index_expression ($1, $2, '('); }
+                ;
+
+word_list       : string
+                  { $$ = new tree_argument_list ($1); }
+                | word_list string
+                  {
+                    $1->append ($2);
+                    $$ = $1;
+                  }
+                ;
+
+// ===========
+// Expressions
+// ===========
+
+identifier      : NAME
+                  {
+                    symbol_table::symbol_record *sr = $1->sym_rec ();
+                    $$ = new tree_identifier (*sr, $1->line (), $1->column ());
+                  }
+                ;
+
+superclass_identifier
+                : SUPERCLASSREF
+                  {
+                    std::string method_nm = $1->superclass_method_name ();
+                    std::string package_nm = $1->superclass_package_name ();
+                    std::string class_nm = $1->superclass_class_name ();
+
+                    $$ = curr_parser->make_superclass_ref
+                                        (method_nm, package_nm, class_nm,
+                                         $1->line (), $1->column ());
+                  }
+                ;
+
+meta_identifier : METAQUERY
+                  {
+                    std::string package_nm = $1->meta_package_name ();
+                    std::string class_nm = $1->meta_class_name ();
+
+                    $$ = curr_parser->make_meta_class_query
+                                        (package_nm, class_nm,
+                                         $1->line (), $1->column ());
+                  }
+                ;
+
+string          : DQ_STRING
+                  { $$ = curr_parser.make_constant (DQ_STRING, $1); }
+                | SQ_STRING
+                  { $$ = curr_parser.make_constant (SQ_STRING, $1); }
+                ;
+
+constant        : NUM
+                  { $$ = curr_parser.make_constant (NUM, $1); }
+                | IMAG_NUM
+                  { $$ = curr_parser.make_constant (IMAG_NUM, $1); }
+                | string
+                  { $$ = $1; }
+                ;
+
+matrix          : '[' ']'
+                  {
+                    $$ = new tree_constant (octave_null_matrix::instance);
+                    curr_lexer->looking_at_matrix_or_assign_lhs = false;
+                    curr_lexer->pending_local_variables.clear ();
+                  }
+                | '[' ';' ']'
+                  {
+                    $$ = new tree_constant (octave_null_matrix::instance);
+                    curr_lexer->looking_at_matrix_or_assign_lhs = false;
+                    curr_lexer->pending_local_variables.clear ();
+                  }
+                | '[' ',' ']'
+                  {
+                    $$ = new tree_constant (octave_null_matrix::instance);
+                    curr_lexer->looking_at_matrix_or_assign_lhs = false;
+                    curr_lexer->pending_local_variables.clear ();
+                  }
+                | '[' matrix_rows ']'
+                  {
+                    $$ = curr_parser.finish_matrix ($2);
+                    curr_lexer->looking_at_matrix_or_assign_lhs = false;
+                    curr_lexer->pending_local_variables.clear ();
+                  }
+                ;
+
+matrix_rows     : matrix_rows1
+                  { $$ = $1; }
+                | matrix_rows1 ';'      // Ignore trailing semicolon.
+                  { $$ = $1; }
+                ;
+
+matrix_rows1    : cell_or_matrix_row
+                  { $$ = new tree_matrix ($1); }
+                | matrix_rows1 ';' cell_or_matrix_row
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
+                ;
+
+cell            : '{' '}'
+                  { $$ = new tree_constant (octave_value (Cell ())); }
+                | '{' ';' '}'
+                  { $$ = new tree_constant (octave_value (Cell ())); }
+                | '{' cell_rows '}'
+                  { $$ = curr_parser.finish_cell ($2); }
+                ;
+
+cell_rows       : cell_rows1
+                  { $$ = $1; }
+                | cell_rows1 ';'        // Ignore trailing semicolon.
+                  { $$ = $1; }
+                ;
+
+cell_rows1      : cell_or_matrix_row
+                  { $$ = new tree_cell ($1); }
+                | cell_rows1 ';' cell_or_matrix_row
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
+                ;
+
+cell_or_matrix_row
+                : arg_list
+                  { $$ = curr_parser.validate_matrix_row ($1); }
+                | arg_list ','  // Ignore trailing comma.
+                  { $$ = curr_parser.validate_matrix_row ($1); }
+                ;
+
+fcn_handle      : '@' FCN_HANDLE
+                  {
+                    $$ = curr_parser.make_fcn_handle ($2);
+                    curr_lexer->looking_at_function_handle--;
+                  }
+                ;
+
+anon_fcn_handle : '@' param_list statement
+                  {
+                    curr_lexer->quote_is_transpose = false;
+                    $$ = curr_parser.make_anon_fcn_handle ($2, $3);
+                  }
+                ;
+
+primary_expr    : identifier
+                  { $$ = $1; }
+                | constant
+                  { $$ = $1; }
+                | fcn_handle
+                  { $$ = $1; }
+                | matrix
+                  { $$ = $1; }
+                | cell
+                  { $$ = $1; }
+                | meta_identifier
+                  { $$ = $1; }
+                | superclass_identifier
+                  { $$ = $1; }
+                | '(' expression ')'
+                  { $$ = $2->mark_in_parens (); }
+                ;
+
+magic_colon     : ':'
+                  {
+                    octave_value tmp (octave_value::magic_colon_t);
+                    $$ = new tree_constant (tmp);
+                  }
+                ;
+
+magic_tilde     : EXPR_NOT
+                  {
+                    $$ = new tree_black_hole ();
+                  }
+                ;
+
+arg_list        : expression
+                  { $$ = new tree_argument_list ($1); }
+                | magic_colon
+                  { $$ = new tree_argument_list ($1); }
+                | magic_tilde
+                  { $$ = new tree_argument_list ($1); }
+                | arg_list ',' magic_colon
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
+                | arg_list ',' magic_tilde
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
+                | arg_list ',' expression
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
+                ;
+
+indirect_ref_op : '.'
+                  { curr_lexer->looking_at_indirect_ref = true; }
+                ;
+
+oper_expr       : primary_expr
+                  { $$ = $1; }
+                | oper_expr PLUS_PLUS
+                  { $$ = curr_parser.make_postfix_op (PLUS_PLUS, $1, $2); }
+                | oper_expr MINUS_MINUS
+                  { $$ = curr_parser.make_postfix_op (MINUS_MINUS, $1, $2); }
+                | oper_expr '(' ')'
+                  { $$ = curr_parser.make_index_expression ($1, 0, '('); }
+                | oper_expr '(' arg_list ')'
+                  { $$ = curr_parser.make_index_expression ($1, $3, '('); }
+                | oper_expr '{' '}'
+                  { $$ = curr_parser.make_index_expression ($1, 0, '{'); }
+                | oper_expr '{' arg_list '}'
+                  { $$ = curr_parser.make_index_expression ($1, $3, '{'); }
+                | oper_expr QUOTE
+                  { $$ = curr_parser.make_postfix_op (QUOTE, $1, $2); }
+                | oper_expr TRANSPOSE
+                  { $$ = curr_parser.make_postfix_op (TRANSPOSE, $1, $2); }
+                | oper_expr indirect_ref_op STRUCT_ELT
+                  { $$ = curr_parser.make_indirect_ref ($1, $3->text ()); }
+                | oper_expr indirect_ref_op '(' expression ')'
+                  { $$ = curr_parser.make_indirect_ref ($1, $4); }
+                | PLUS_PLUS oper_expr %prec UNARY
+                  { $$ = curr_parser.make_prefix_op (PLUS_PLUS, $2, $1); }
+                | MINUS_MINUS oper_expr %prec UNARY
+                  { $$ = curr_parser.make_prefix_op (MINUS_MINUS, $2, $1); }
+                | EXPR_NOT oper_expr %prec UNARY
+                  { $$ = curr_parser.make_prefix_op (EXPR_NOT, $2, $1); }
+                | '+' oper_expr %prec UNARY
+                  { $$ = curr_parser.make_prefix_op ('+', $2, $1); }
+                | '-' oper_expr %prec UNARY
+                  { $$ = curr_parser.make_prefix_op ('-', $2, $1); }
+                | oper_expr POW oper_expr
+                  { $$ = curr_parser.make_binary_op (POW, $1, $2, $3); }
+                | oper_expr EPOW oper_expr
+                  { $$ = curr_parser.make_binary_op (EPOW, $1, $2, $3); }
+                | oper_expr '+' oper_expr
+                  { $$ = curr_parser.make_binary_op ('+', $1, $2, $3); }
+                | oper_expr '-' oper_expr
+                  { $$ = curr_parser.make_binary_op ('-', $1, $2, $3); }
+                | oper_expr '*' oper_expr
+                  { $$ = curr_parser.make_binary_op ('*', $1, $2, $3); }
+                | oper_expr '/' oper_expr
+                  { $$ = curr_parser.make_binary_op ('/', $1, $2, $3); }
+                | oper_expr EPLUS oper_expr
+                  { $$ = curr_parser.make_binary_op ('+', $1, $2, $3); }
+                | oper_expr EMINUS oper_expr
+                  { $$ = curr_parser.make_binary_op ('-', $1, $2, $3); }
+                | oper_expr EMUL oper_expr
+                  { $$ = curr_parser.make_binary_op (EMUL, $1, $2, $3); }
+                | oper_expr EDIV oper_expr
+                  { $$ = curr_parser.make_binary_op (EDIV, $1, $2, $3); }
+                | oper_expr LEFTDIV oper_expr
+                  { $$ = curr_parser.make_binary_op (LEFTDIV, $1, $2, $3); }
+                | oper_expr ELEFTDIV oper_expr
+                  { $$ = curr_parser.make_binary_op (ELEFTDIV, $1, $2, $3); }
+                ;
+
+colon_expr      : colon_expr1
+                  { $$ = curr_parser.finish_colon_expression ($1); }
+                ;
+
+colon_expr1     : oper_expr
+                  { $$ = new tree_colon_expression ($1); }
+                | colon_expr1 ':' oper_expr
+                  {
+                    if (! ($$ = $1->append ($3)))
+                      ABORT_PARSE;
+                  }
+                ;
+
+simple_expr     : colon_expr
+                  { $$ = $1; }
+                | simple_expr LSHIFT simple_expr
+                  { $$ = curr_parser.make_binary_op (LSHIFT, $1, $2, $3); }
+                | simple_expr RSHIFT simple_expr
+                  { $$ = curr_parser.make_binary_op (RSHIFT, $1, $2, $3); }
+                | simple_expr EXPR_LT simple_expr
+                  { $$ = curr_parser.make_binary_op (EXPR_LT, $1, $2, $3); }
+                | simple_expr EXPR_LE simple_expr
+                  { $$ = curr_parser.make_binary_op (EXPR_LE, $1, $2, $3); }
+                | simple_expr EXPR_EQ simple_expr
+                  { $$ = curr_parser.make_binary_op (EXPR_EQ, $1, $2, $3); }
+                | simple_expr EXPR_GE simple_expr
+                  { $$ = curr_parser.make_binary_op (EXPR_GE, $1, $2, $3); }
+                | simple_expr EXPR_GT simple_expr
+                  { $$ = curr_parser.make_binary_op (EXPR_GT, $1, $2, $3); }
+                | simple_expr EXPR_NE simple_expr
+                  { $$ = curr_parser.make_binary_op (EXPR_NE, $1, $2, $3); }
+                | simple_expr EXPR_AND simple_expr
+                  { $$ = curr_parser.make_binary_op (EXPR_AND, $1, $2, $3); }
+                | simple_expr EXPR_OR simple_expr
+                  { $$ = curr_parser.make_binary_op (EXPR_OR, $1, $2, $3); }
+                | simple_expr EXPR_AND_AND simple_expr
+                  { $$ = curr_parser.make_boolean_op (EXPR_AND_AND, $1, $2, $3); }
+                | simple_expr EXPR_OR_OR simple_expr
+                  { $$ = curr_parser.make_boolean_op (EXPR_OR_OR, $1, $2, $3); }
+                ;
+
+// Arrange for the lexer to return CLOSE_BRACE for ']' by looking ahead
+// one token for an assignment op.
+
+assign_lhs      : simple_expr
+                  {
+                    $$ = new tree_argument_list ($1);
+                    $$->mark_as_simple_assign_lhs ();
+                  }
+                | '[' arg_list opt_comma CLOSE_BRACE
+                  {
+                    $$ = $2;
+                    curr_lexer->looking_at_matrix_or_assign_lhs = false;
+                    for (std::set<std::string>::const_iterator p = curr_lexer->pending_local_variables.begin ();
+                         p != curr_lexer->pending_local_variables.end ();
+                         p++)
+                      {
+                        symbol_table::force_variable (*p);
+                      }
+                    curr_lexer->pending_local_variables.clear ();
+                  }
+                ;
+
+assign_expr     : assign_lhs '=' expression
+                  { $$ = curr_parser.make_assign_op ('=', $1, $2, $3); }
+                | assign_lhs ADD_EQ expression
+                  { $$ = curr_parser.make_assign_op (ADD_EQ, $1, $2, $3); }
+                | assign_lhs SUB_EQ expression
+                  { $$ = curr_parser.make_assign_op (SUB_EQ, $1, $2, $3); }
+                | assign_lhs MUL_EQ expression
+                  { $$ = curr_parser.make_assign_op (MUL_EQ, $1, $2, $3); }
+                | assign_lhs DIV_EQ expression
+                  { $$ = curr_parser.make_assign_op (DIV_EQ, $1, $2, $3); }
+                | assign_lhs LEFTDIV_EQ expression
+                  { $$ = curr_parser.make_assign_op (LEFTDIV_EQ, $1, $2, $3); }
+                | assign_lhs POW_EQ expression
+                  { $$ = curr_parser.make_assign_op (POW_EQ, $1, $2, $3); }
+                | assign_lhs LSHIFT_EQ expression
+                  { $$ = curr_parser.make_assign_op (LSHIFT_EQ, $1, $2, $3); }
+                | assign_lhs RSHIFT_EQ expression
+                  { $$ = curr_parser.make_assign_op (RSHIFT_EQ, $1, $2, $3); }
+                | assign_lhs EMUL_EQ expression
+                  { $$ = curr_parser.make_assign_op (EMUL_EQ, $1, $2, $3); }
+                | assign_lhs EDIV_EQ expression
+                  { $$ = curr_parser.make_assign_op (EDIV_EQ, $1, $2, $3); }
+                | assign_lhs ELEFTDIV_EQ expression
+                  { $$ = curr_parser.make_assign_op (ELEFTDIV_EQ, $1, $2, $3); }
+                | assign_lhs EPOW_EQ expression
+                  { $$ = curr_parser.make_assign_op (EPOW_EQ, $1, $2, $3); }
+                | assign_lhs AND_EQ expression
+                  { $$ = curr_parser.make_assign_op (AND_EQ, $1, $2, $3); }
+                | assign_lhs OR_EQ expression
+                  { $$ = curr_parser.make_assign_op (OR_EQ, $1, $2, $3); }
+                ;
+
+expression      : simple_expr
+                  { $$ = $1; }
+                | assign_expr
+                  { $$ = $1; }
+                | anon_fcn_handle
+                  { $$ = $1; }
+                ;
+
+// ================================================
+// Commands, declarations, and function definitions
+// ================================================
+
+command         : declaration
+                  { $$ = $1; }
+                | select_command
+                  { $$ = $1; }
+                | loop_command
+                  { $$ = $1; }
+                | jump_command
+                  { $$ = $1; }
+                | except_command
+                  { $$ = $1; }
+                | function
+                  { $$ = $1; }
+                | file
+                  { $$ = $1; }
+                ;
+
+// =====================
+// Declaration statemnts
+// =====================
+
+parsing_decl_list
+                : // empty
+                  { curr_lexer->looking_at_decl_list = true; }
+
+declaration     : GLOBAL parsing_decl_list decl1
+                  {
+                    $$ = curr_parser.make_decl_command (GLOBAL, $1, $3);
+                    curr_lexer->looking_at_decl_list = false;
+                  }
+                | PERSISTENT parsing_decl_list decl1
+                  {
+                    $$ = curr_parser.make_decl_command (PERSISTENT, $1, $3);
+                    curr_lexer->looking_at_decl_list = false;
+                  }
+                ;
+
+decl1           : decl2
+                  { $$ = new tree_decl_init_list ($1); }
+                | decl1 decl2
+                  {
+                    $1->append ($2);
+                    $$ = $1;
+                  }
+                ;
+
+decl_param_init : // empty
+                { curr_lexer->looking_at_initializer_expression = true; }
+
+decl2           : identifier
+                  { $$ = new tree_decl_elt ($1); }
+                | identifier '=' decl_param_init expression
+                  {
+                    curr_lexer->looking_at_initializer_expression = false;
+                    $$ = new tree_decl_elt ($1, $4);
+                  }
+                | magic_tilde
+                  {
+                    $$ = new tree_decl_elt ($1);
+                  }
+                ;
+
+// ====================
+// Selection statements
+// ====================
+
+select_command  : if_command
+                  { $$ = $1; }
+                | switch_command
+                  { $$ = $1; }
+                ;
+
+// ============
+// If statement
+// ============
+
+if_command      : IF stash_comment if_cmd_list END
+                  {
+                    if (! ($$ = curr_parser.finish_if_command ($1, $3, $4, $2)))
+                      ABORT_PARSE;
+                  }
+                ;
+
+if_cmd_list     : if_cmd_list1
+                  { $$ = $1; }
+                | if_cmd_list1 else_clause
+                  {
+                    $1->append ($2);
+                    $$ = $1;
+                  }
+                ;
+
+if_cmd_list1    : expression opt_sep opt_list
+                  {
+                    $1->mark_braindead_shortcircuit (curr_lexer->fcn_file_full_name);
+
+                    $$ = curr_parser.start_if_command ($1, $3);
+                  }
+                | if_cmd_list1 elseif_clause
+                  {
+                    $1->append ($2);
+                    $$ = $1;
+                  }
+                ;
+
+elseif_clause   : ELSEIF stash_comment opt_sep expression opt_sep opt_list
+                  {
+                    $4->mark_braindead_shortcircuit (curr_lexer->fcn_file_full_name);
+
+                    $$ = curr_parser.make_elseif_clause ($1, $4, $6, $2);
+                  }
+                ;
+
+else_clause     : ELSE stash_comment opt_sep opt_list
+                  { $$ = new tree_if_clause ($4, $2); }
+                ;
+
+// ================
+// Switch statement
+// ================
+
+switch_command  : SWITCH stash_comment expression opt_sep case_list END
+                  {
+                    if (! ($$ = curr_parser.finish_switch_command ($1, $3, $5, $6, $2)))
+                      ABORT_PARSE;
+                  }
+                ;
+
+case_list       : // empty
+                  { $$ = new tree_switch_case_list (); }
+                | default_case
+                  { $$ = new tree_switch_case_list ($1); }
+                | case_list1
+                  { $$ = $1; }
+                | case_list1 default_case
+                  {
+                    $1->append ($2);
+                    $$ = $1;
+                  }
+                ;
+
+case_list1      : switch_case
+                  { $$ = new tree_switch_case_list ($1); }
+                | case_list1 switch_case
+                  {
+                    $1->append ($2);
+                    $$ = $1;
+                  }
+                ;
+
+switch_case     : CASE stash_comment opt_sep expression opt_sep opt_list
+                  { $$ = curr_parser.make_switch_case ($1, $4, $6, $2); }
+                ;
+
+default_case    : OTHERWISE stash_comment opt_sep opt_list
+                  {
+                    $$ = new tree_switch_case ($4, $2);
+                  }
+                ;
+
+// =======
+// Looping
+// =======
+
+loop_command    : WHILE stash_comment expression opt_sep opt_list END
+                  {
+                    $3->mark_braindead_shortcircuit (curr_lexer->fcn_file_full_name);
+
+                    if (! ($$ = curr_parser.make_while_command ($1, $3, $5, $6, $2)))
+                      ABORT_PARSE;
+                  }
+                | DO stash_comment opt_sep opt_list UNTIL expression
+                  {
+                    if (! ($$ = curr_parser.make_do_until_command ($5, $4, $6, $2)))
+                      ABORT_PARSE;
+                  }
+                | FOR stash_comment assign_lhs '=' expression opt_sep opt_list END
+                  {
+                    if (! ($$ = curr_parser.make_for_command (FOR, $1, $3, $5, 0,
+                                                  $7, $8, $2)))
+                      ABORT_PARSE;
+                  }
+                | FOR stash_comment '(' assign_lhs '=' expression ')' opt_sep opt_list END
+                  {
+                    if (! ($$ = curr_parser.make_for_command (FOR, $1, $4, $6, 0,
+                                                  $9, $10, $2)))
+                      ABORT_PARSE;
+                  }
+                | PARFOR stash_comment assign_lhs '=' expression opt_sep opt_list END
+                  {
+                    if (! ($$ = curr_parser.make_for_command (PARFOR, $1, $3, $5,
+                                                  0, $7, $8, $2)))
+                      ABORT_PARSE;
+                  }
+                | PARFOR stash_comment '(' assign_lhs '=' expression ',' expression ')' opt_sep opt_list END
+                  {
+                    if (! ($$ = curr_parser.make_for_command (PARFOR, $1, $4, $6,
+                                                  $8, $11, $12, $2)))
+                      ABORT_PARSE;
+                  }
+                ;
+
+// =======
+// Jumping
+// =======
+
+jump_command    : BREAK
+                  {
+                    if (! ($$ = curr_parser.make_break_command ($1)))
+                      ABORT_PARSE;
+                  }
+                | CONTINUE
+                  {
+                    if (! ($$ = curr_parser.make_continue_command ($1)))
+                      ABORT_PARSE;
+                  }
+                | FUNC_RET
+                  {
+                    if (! ($$ = curr_parser.make_return_command ($1)))
+                      ABORT_PARSE;
+                  }
+                ;
+
+// ==========
+// Exceptions
+// ==========
+
+except_command  : UNWIND stash_comment opt_sep opt_list CLEANUP
+                  stash_comment opt_sep opt_list END
+                  {
+                    if (! ($$ = curr_parser.make_unwind_command ($1, $4, $8, $9, $2, $6)))
+                      ABORT_PARSE;
+                  }
+                | TRY stash_comment opt_sep opt_list CATCH
+                  stash_comment opt_sep opt_list END
+                  {
+                    if (! ($$ = curr_parser.make_try_command ($1, $4, $8, $9, $2, $6)))
+                      ABORT_PARSE;
+                  }
+                | TRY stash_comment opt_sep opt_list END
+                  {
+                    if (! ($$ = curr_parser.make_try_command ($1, $4, 0, $5, $2, 0)))
+                      ABORT_PARSE;
+                  }
+                ;
+
+// ===========================================
+// Some 'subroutines' for function definitions
+// ===========================================
+
+push_fcn_symtab : // empty
+                  {
+                    curr_parser.curr_fcn_depth++;
+
+                    if (curr_parser.max_fcn_depth < curr_parser.curr_fcn_depth)
+                      curr_parser.max_fcn_depth = curr_parser.curr_fcn_depth;
+
+                    parser_symtab_context.push ();
+
+                    symbol_table::set_scope (symbol_table::alloc_scope ());
+
+                    curr_parser.function_scopes.push_back (symbol_table::current_scope ());
+
+                    if (! curr_lexer->reading_script_file
+                        && curr_parser.curr_fcn_depth == 1
+                        && ! curr_parser.parsing_subfunctions)
+                      curr_parser.primary_fcn_scope = symbol_table::current_scope ();
+
+                    if (curr_lexer->reading_script_file
+                        && curr_parser.curr_fcn_depth > 1)
+                      curr_parser.bison_error ("nested functions not implemented in this context");
+                  }
+                ;
+
+// ===========================
+// List of function parameters
+// ===========================
+
+param_list_beg  : '('
+                  {
+                    curr_lexer->looking_at_parameter_list = true;
+
+                    if (curr_lexer->looking_at_function_handle)
+                      {
+                        parser_symtab_context.push ();
+                        symbol_table::set_scope (symbol_table::alloc_scope ());
+                        curr_lexer->looking_at_function_handle--;
+                        curr_lexer->looking_at_anon_fcn_args = true;
+                      }
+                  }
+                ;
+
+param_list_end  : ')'
+                  {
+                    curr_lexer->looking_at_parameter_list = false;
+                    curr_lexer->looking_for_object_index = false;
+                  }
+                ;
+
+param_list      : param_list_beg param_list1 param_list_end
+                  {
+                    curr_lexer->quote_is_transpose = false;
+                    $$ = $2;
+                  }
+                | param_list_beg error
+                  {
+                    curr_parser.bison_error ("invalid parameter list");
+                    $$ = 0;
+                    ABORT_PARSE;
+                  }
+                ;
+
+param_list1     : // empty
+                  { $$ = 0; }
+                | param_list2
+                  {
+                    $1->mark_as_formal_parameters ();
+                    if ($1->validate (tree_parameter_list::in))
+                      $$ = $1;
+                    else
+                      ABORT_PARSE;
+                  }
+                ;
+
+param_list2     : decl2
+                  { $$ = new tree_parameter_list ($1); }
+                | param_list2 ',' decl2
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
+                ;
+
+// ===================================
+// List of function return value names
+// ===================================
+
+return_list     : '[' ']'
+                  {
+                    curr_lexer->looking_at_return_list = false;
+                    $$ = new tree_parameter_list ();
+                  }
+                | return_list1
+                  {
+                    curr_lexer->looking_at_return_list = false;
+                    if ($1->validate (tree_parameter_list::out))
+                      $$ = $1;
+                    else
+                      ABORT_PARSE;
+                  }
+                | '[' return_list1 ']'
+                  {
+                    curr_lexer->looking_at_return_list = false;
+                    if ($2->validate (tree_parameter_list::out))
+                      $$ = $2;
+                    else
+                      ABORT_PARSE;
+                  }
+                ;
+
+return_list1    : identifier
+                  { $$ = new tree_parameter_list (new tree_decl_elt ($1)); }
+                | return_list1 ',' identifier
+                  {
+                    $1->append (new tree_decl_elt ($3));
+                    $$ = $1;
+                  }
+                ;
+
+// =======================
+// Script or function file
+// =======================
+
+file            : INPUT_FILE opt_nl opt_list END_OF_INPUT
+                  {
+                    if (! curr_lexer->reading_fcn_file)
+                      {
+                        tree_statement *end_of_script
+                          = curr_parser.make_end ("endscript",
+                                                  curr_lexer->input_line_number,
+                                                  curr_lexer->current_input_column);
+
+                        curr_parser.make_script ($3, end_of_script);
+                      }
+
+                    $$ = 0;
+                  }
+                ;
+
+// ===================
+// Function definition
+// ===================
+
+function_beg    : push_fcn_symtab FCN stash_comment
+                  {
+                    $$ = $3;
+                    if (curr_lexer->reading_classdef_file
+                        || curr_lexer->parsing_classdef)
+                      curr_lexer->maybe_classdef_get_set_method = true;
+                  }
+                ;
+
+function        : function_beg function1
+                  {
+                    $$ = curr_parser.finish_function (0, $2, $1);
+                    curr_parser.recover_from_parsing_function ();
+                  }
+                | function_beg return_list '=' function1
+                  {
+                    $$ = curr_parser.finish_function ($2, $4, $1);
+                    curr_parser.recover_from_parsing_function ();
+                  }
+                ;
+
+fcn_name        : identifier
+                  {
+                    std::string id_name = $1->name ();
+
+                    curr_lexer->parsed_function_name.top () = true;
+                    curr_lexer->maybe_classdef_get_set_method = false;
+
+                    $$ = $1;
+                  }
+                | GET '.' identifier
+                  {
+                    curr_lexer->parsed_function_name.top () = true;
+                    curr_lexer->maybe_classdef_get_set_method = false;
+                    curr_lexer->parsing_classdef_get_method = true;
+                    $$ = $3;
+                  }
+                | SET '.' identifier
+                  {
+                    curr_lexer->parsed_function_name.top () = true;
+                    curr_lexer->maybe_classdef_get_set_method = false;
+                    curr_lexer->parsing_classdef_set_method = true;
+                    $$ = $3;
+                  }
+                ;
+
+function1       : fcn_name function2
+                  {
+                    std::string fname = $1->name ();
+
+                    delete $1;
+
+                    if (! ($$ = curr_parser.frob_function (fname, $2)))
+                      ABORT_PARSE;
+                  }
+                ;
+
+function2       : param_list opt_sep opt_list function_end
+                  { $$ = curr_parser.start_function ($1, $3, $4); }
+                | opt_sep opt_list function_end
+                  { $$ = curr_parser.start_function (0, $2, $3); }
+                ;
+
+function_end    : END
+                  {
+                    curr_parser.endfunction_found = true;
+                    if (curr_parser.end_token_ok ($1, token::function_end))
+                      $$ = curr_parser.make_end ("endfunction", $1->line (), $1->column ());
+                    else
+                      ABORT_PARSE;
+                  }
+                | END_OF_INPUT
+                  {
+// A lot of tests are based on the assumption that this is OK
+//                  if (curr_lexer->reading_script_file)
+//                    {
+//                      curr_parser.bison_error ("function body open at end of script");
+//                      YYABORT;
+//                    }
+
+                    if (curr_parser.endfunction_found)
+                      {
+                        curr_parser.bison_error ("inconsistent function endings -- "
+                                 "if one function is explicitly ended, "
+                                 "so must all the others");
+                        YYABORT;
+                      }
+
+                    if (! (curr_lexer->reading_fcn_file || curr_lexer->reading_script_file
+                           || (curr_lexer)->input_from_eval_string ()))
+                      {
+                        curr_parser.bison_error ("function body open at end of input");
+                        YYABORT;
+                      }
+
+                    if (curr_lexer->reading_classdef_file)
+                      {
+                        curr_parser.bison_error ("classdef body open at end of input");
+                        YYABORT;
+                      }
+
+                    $$ = curr_parser.make_end ("endfunction",
+                                                curr_lexer->input_line_number,
+                                                curr_lexer->current_input_column);
+                  }
+                ;
+
+// =============
+// Classdef file
+// =============
+
+classdef_file   : CLASSDEF_FILE classdef opt_sep END_OF_INPUT
+                  {
+                    curr_parser->classdef_object = $2;
+                    $$ = 0;
+                  }
+                ;
+
+// ========
+// Classdef
+// ========
+
+classdef_beg    : CLASSDEF
+                  {
+                    if (! reading_classdef_file)
+                      {
+                        curr_parser->bison_error ("classdef must appear inside a file containing only a class definition");
+                        YYABORT;
+                      }
+
+                    curr_lexer->parsing_classdef = true;
+                    $$ = $1;
+                  }
+                ;
+
+classdef        : classdef_beg stash_comment opt_attr_list identifier opt_superclass_list opt_sep class_body opt_sep END
+                  {
+                    curr_lexer->parsing_classdef = false;
+<<<<<<< local
+                    if (! ($$ = curr_parser->make_classdef ($1, $3, $4, $5, $7, $9, $2)))
+=======
+
+                    if (curr_parser.end_token_ok ($1, token::classdef_end))
+                      $$ = curr_parser.make_end ("endclassdef", $1->line (), $1->column ());
+                    else
+>>>>>>> other
+                      ABORT_PARSE;
+                  }
+                ;
+
+opt_attr_list   : // empty
+                  { $$ = 0; }
+                | '(' attr_list ')'
+                  { $$ = $2; }
+                ;
+
+attr_list       : attr
+                  { $$ = new tree_classdef_attribute_list ($1); }
+                | attr_list ',' attr
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
+                ;
+
+attr            : identifier
+                  { $$ = new tree_classdef_attribute ($1); }
+                | identifier '=' decl_param_init expression
+                  {
+                    curr_lexer->looking_at_initializer_expression = false;
+                    $$ = new tree_classdef_attribute ($1, $4);
+                  }
+                | EXPR_NOT identifier
+                  { $$ = new tree_classdef_attribute ($2, false); }
+                ;
+
+opt_superclass_list
+                : // empty
+                  { $$ = 0; }
+                | superclass_list
+                  { $$ = $1; }
+                ;
+
+superclass_list : EXPR_LT superclass
+                  { $$ = new tree_classdef_superclass_list ($2); }
+                | superclass_list EXPR_AND superclass
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
+                ;
+
+superclass      : identifier
+                  { $$ = new tree_classdef_superclass ($1); }
+                | identifier '.' identifier
+                  { $$ = new tree_classdef_superclass ($3, $1); }
+                ;
+
+class_body      : properties_block
+                  { $$ = new tree_classdef_body ($1); }
+                | methods_block
+                  { $$ = new tree_classdef_body ($1); }
+                | events_block
+                  { $$ = new tree_classdef_body ($1); }
+                | enum_block
+                  { $$ = new tree_classdef_body ($1); }
+                | class_body opt_sep properties_block
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
+                | class_body opt_sep methods_block
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
+                | class_body opt_sep events_block
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
+                | class_body opt_sep enum_block
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
+                ;
+
+properties_block
+                : PROPERTIES stash_comment opt_attr_list opt_sep property_list opt_sep END
+                  {
+                    if (! ($$ = curr_parser->make_classdef_properties_block
+                                               ($1, $3, $5, $7, $2)))
+                      ABORT_PARSE;
+                  }
+                ;
+
+property_list
+                : class_property
+                  { $$ = new tree_classdef_property_list ($1); }
+                | property_list opt_sep class_property
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
+                ;
+
+class_property  : identifier
+                  { $$ = new tree_classdef_property ($1); }
+                | identifier '=' decl_param_init expression ';'
+                  {
+                    curr_lexer->looking_at_initializer_expression = false;
+                    $$ = new tree_classdef_property ($1, $4);
+                  }
+                ;
+
+methods_block   : METHODS stash_comment opt_attr_list opt_sep methods_list opt_sep END
+                  {
+                    if (! ($$ = curr_parser->make_classdef_methods_block
+                                               ($1, $3, $5, $7, $2)))
+                      ABORT_PARSE;
+                  }
+                ;
+
+methods_list    : function
+                  {
+                    octave_value fcn;
+                    if ($1)
+                      fcn = $1->function ();
+                    delete $1;
+                    $$ = new tree_classdef_methods_list (fcn);
+                  }
+                | methods_list opt_sep function
+                  {
+                    octave_value fcn;
+                    if ($3)
+                      fcn = $3->function ();
+                    delete $3;
+
+                    $1->append (fcn);
+                    $$ = $1;
+                  }
+                ;
+
+events_block    : EVENTS stash_comment opt_attr_list opt_sep events_list opt_sep END
+                  {
+                    if (! ($$ = curr_parser->make_classdef_events_block
+                                               ($1, $3, $5, $7, $2)))
+                      ABORT_PARSE;
+                  }
+                ;
+
+events_list     : class_event
+                  { $$ = new tree_classdef_events_list ($1); }
+                | events_list opt_sep class_event
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
+                ;
+
+class_event     : identifier
+                  { $$ = new tree_classdef_event ($1); }
+                ;
+
+enum_block      : ENUMERATION stash_comment opt_attr_list opt_sep enum_list opt_sep END
+                  {
+                    if (! ($$ = curr_parser->make_classdef_enum_block
+                                               ($1, $3, $5, $7, $2)))
+                      ABORT_PARSE;
+                  }
+                ;
+
+enum_list       : class_enum
+                  { $$ = new tree_classdef_enum_list ($1); }
+                | enum_list opt_sep class_enum
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
+                ;
+
+class_enum      : identifier '(' expression ')'
+                  { $$ = new tree_classdef_enum ($1, $3); }
+                ;
+
+// =============
+// Miscellaneous
+// =============
+
+stash_comment   : // empty
+                  { $$ = octave_comment_buffer::get_comment (); }
+                ;
+
+parse_error     : LEXICAL_ERROR
+                  { curr_parser.bison_error ("parse error"); }
+                | error
+                ;
+
+sep_no_nl       : ','
+                  { $$ = ','; }
+                | ';'
+                  { $$ = ';'; }
+                | sep_no_nl ','
+                  { $$ = $1; }
+                | sep_no_nl ';'
+                  { $$ = $1; }
+                ;
+
+opt_sep_no_nl   : // empty
+                  { $$ = 0; }
+                | sep_no_nl
+                  { $$ = $1; }
+                ;
+
+opt_nl          : // empty
+                  { $$ = 0; }
+                | nl
+                  { $$ = $1; }
+                ;
+
+nl              : '\n'
+                  { $$ = '\n'; }
+                | nl '\n'
+                  { $$ = $1; }
+                ;
+
+sep             : ','
+                  { $$ = ','; }
+                | ';'
+                  { $$ = ';'; }
+                | '\n'
+                  { $$ = '\n'; }
+                | sep ','
+                  { $$ = $1; }
+                | sep ';'
+                  { $$ = $1; }
+                | sep '\n'
+                  { $$ = $1; }
+                ;
+
+opt_sep         : // empty
+                  { $$ = 0; }
+                | sep
+                  { $$ = $1; }
+                ;
+
+opt_comma       : // empty
+                  { $$ = 0; }
+                | ','
+                  { $$ = ','; }
+                ;
+
+%%
+
+// Generic error messages.
+
+#undef curr_lexer
+
+static void
+yyerror (octave_parser& curr_parser, const char *s)
+{
+  curr_parser.bison_error (s);
+}
+
+octave_parser::~octave_parser (void)
+{
+#if defined (OCTAVE_USE_PUSH_PARSER)
+  yypstate_delete (static_cast<yypstate *> (parser_state));
+#endif
+
+  delete stmt_list;
+
+  delete curr_lexer;
+}
+void octave_parser::init (void)
+{
+#if defined (OCTAVE_USE_PUSH_PARSER)
+  parser_state = yypstate_new ();
+#endif
+
+  CURR_LEXER = curr_lexer;
+}
+
+void
+octave_parser::reset (void)
+{
+  delete stmt_list;
+
+  stmt_list = 0;
+
+  curr_lexer->reset ();
+}
+
+int
+octave_parser::run (void)
+{
+  int status = 0;
+
+#if defined (OCTAVE_USE_PUSH_PARSER)
+
+  do
+    {
+      YYSTYPE lval;
+
+      int token = octave_lex (&lval, scanner);
+
+      yypstate *pstate = static_cast<yypstate *> (parser_state);
+
+      status = octave_push_parse (pstate, token, &lval, *this);
+    }
+  while (status == YYPUSH_MORE);
+
+#else
+
+  status = octave_parse (*this);
+
+#endif
+
+  return status;
+}
+
+// Error mesages for mismatched end tokens.
+
+void
+octave_parser::end_error (const char *type, token::end_tok_type ettype,
+                          int l, int c)
+{
+  static const char *fmt
+    = "'%s' command matched by '%s' near line %d column %d";
+
+  switch (ettype)
+    {
+    case token::simple_end:
+      error (fmt, type, "end", l, c);
+      break;
+
+    case token::for_end:
+      error (fmt, type, "endfor", l, c);
+      break;
+
+    case token::function_end:
+      error (fmt, type, "endfunction", l, c);
+      break;
+
+    case token::classdef_end:
+      error (fmt, type, "endclassdef", l, c);
+      break;
+
+    case token::if_end:
+      error (fmt, type, "endif", l, c);
+      break;
+
+    case token::switch_end:
+      error (fmt, type, "endswitch", l, c);
+      break;
+
+    case token::while_end:
+      error (fmt, type, "endwhile", l, c);
+      break;
+
+    case token::try_catch_end:
+      error (fmt, type, "end_try_catch", l, c);
+      break;
+
+    case token::unwind_protect_end:
+      error (fmt, type, "end_unwind_protect", l, c);
+      break;
+
+    default:
+      panic_impossible ();
+      break;
+    }
+}
+
+// Check to see that end tokens are properly matched.
+
+bool
+octave_parser::end_token_ok (token *tok, token::end_tok_type expected)
+{
+  bool retval = true;
+
+  token::end_tok_type ettype = tok->ettype ();
+
+  if (ettype != expected && ettype != token::simple_end)
+    {
+      retval = false;
+
+      bison_error ("parse error");
+
+      int l = tok->line ();
+      int c = tok->column ();
+
+      switch (expected)
+        {
+        case token::classdef_end:
+          end_error ("classdef", ettype, l, c);
+          break;
+
+        case token::for_end:
+          end_error ("for", ettype, l, c);
+          break;
+
+        case token::enumeration_end:
+          end_error ("enumeration", ettype, l, c);
+          break;
+
+        case token::function_end:
+          end_error ("function", ettype, l, c);
+          break;
+
+        case token::if_end:
+          end_error ("if", ettype, l, c);
+          break;
+
+        case token::parfor_end:
+          end_error ("parfor", ettype, l, c);
+          break;
+
+        case token::try_catch_end:
+          end_error ("try", ettype, l, c);
+          break;
+
+        case token::switch_end:
+          end_error ("switch", ettype, l, c);
+          break;
+
+        case token::unwind_protect_end:
+          end_error ("unwind_protect", ettype, l, c);
+          break;
+
+        case token::while_end:
+          end_error ("while", ettype, l, c);
+          break;
+
+        default:
+          panic_impossible ();
+          break;
+        }
+    }
+
+  return retval;
+}
+
+// Maybe print a warning if an assignment expression is used as the
+// test in a logical expression.
+
+void
+octave_parser::maybe_warn_assign_as_truth_value (tree_expression *expr)
+{
+  if (expr->is_assignment_expression ()
+      && expr->paren_count () < 2)
+    {
+      if (curr_lexer->fcn_file_full_name.empty ())
+        warning_with_id
+          ("Octave:assign-as-truth-value",
+           "suggest parenthesis around assignment used as truth value");
+      else
+        warning_with_id
+          ("Octave:assign-as-truth-value",
+           "suggest parenthesis around assignment used as truth value near line %d, column %d in file '%s'",
+           expr->line (), expr->column (), curr_lexer->fcn_file_full_name.c_str ());
+    }
+}
+
+// Maybe print a warning about switch labels that aren't constants.
+
+void
+octave_parser::maybe_warn_variable_switch_label (tree_expression *expr)
+{
+  if (! expr->is_constant ())
+    {
+      if (curr_lexer->fcn_file_full_name.empty ())
+        warning_with_id ("Octave:variable-switch-label",
+                         "variable switch label");
+      else
+        warning_with_id
+          ("Octave:variable-switch-label",
+           "variable switch label near line %d, column %d in file '%s'",
+           expr->line (), expr->column (), curr_lexer->fcn_file_full_name.c_str ());
+    }
+}
+
+static tree_expression *
+fold (tree_binary_expression *e)
+{
+  tree_expression *retval = e;
+
+  unwind_protect frame;
+
+  frame.protect_var (error_state);
+  frame.protect_var (warning_state);
+
+  frame.protect_var (discard_error_messages);
+  frame.protect_var (discard_warning_messages);
+
+  discard_error_messages = true;
+  discard_warning_messages = true;
+
+  tree_expression *op1 = e->lhs ();
+  tree_expression *op2 = e->rhs ();
+
+  if (op1->is_constant () && op2->is_constant ())
+    {
+      octave_value tmp = e->rvalue1 ();
+
+      if (! (error_state || warning_state))
+        {
+          tree_constant *tc_retval
+            = new tree_constant (tmp, op1->line (), op1->column ());
+
+          std::ostringstream buf;
+
+          tree_print_code tpc (buf);
+
+          e->accept (tpc);
+
+          tc_retval->stash_original_text (buf.str ());
+
+          delete e;
+
+          retval = tc_retval;
+        }
+    }
+
+  return retval;
+}
+
+static tree_expression *
+fold (tree_unary_expression *e)
+{
+  tree_expression *retval = e;
+
+  unwind_protect frame;
+
+  frame.protect_var (error_state);
+  frame.protect_var (warning_state);
+
+  frame.protect_var (discard_error_messages);
+  frame.protect_var (discard_warning_messages);
+
+  discard_error_messages = true;
+  discard_warning_messages = true;
+
+  tree_expression *op = e->operand ();
+
+  if (op->is_constant ())
+    {
+      octave_value tmp = e->rvalue1 ();
+
+      if (! (error_state || warning_state))
+        {
+          tree_constant *tc_retval
+            = new tree_constant (tmp, op->line (), op->column ());
+
+          std::ostringstream buf;
+
+          tree_print_code tpc (buf);
+
+          e->accept (tpc);
+
+          tc_retval->stash_original_text (buf.str ());
+
+          delete e;
+
+          retval = tc_retval;
+        }
+    }
+
+  return retval;
+}
+
+// Finish building a range.
+
+tree_expression *
+octave_parser::finish_colon_expression (tree_colon_expression *e)
+{
+  tree_expression *retval = e;
+
+  unwind_protect frame;
+
+  frame.protect_var (error_state);
+  frame.protect_var (warning_state);
+
+  frame.protect_var (discard_error_messages);
+  frame.protect_var (discard_warning_messages);
+
+  discard_error_messages = true;
+  discard_warning_messages = true;
+
+  tree_expression *base = e->base ();
+  tree_expression *limit = e->limit ();
+  tree_expression *incr = e->increment ();
+
+  if (base)
+    {
+      if (limit)
+        {
+          if (base->is_constant () && limit->is_constant ()
+              && (! incr || (incr && incr->is_constant ())))
+            {
+              octave_value tmp = e->rvalue1 ();
+
+              if (! (error_state || warning_state))
+                {
+                  tree_constant *tc_retval
+                    = new tree_constant (tmp, base->line (), base->column ());
+
+                  std::ostringstream buf;
+
+                  tree_print_code tpc (buf);
+
+                  e->accept (tpc);
+
+                  tc_retval->stash_original_text (buf.str ());
+
+                  delete e;
+
+                  retval = tc_retval;
+                }
+            }
+        }
+      else
+        {
+          e->preserve_base ();
+          delete e;
+
+          // FIXME -- need to attempt constant folding here
+          // too (we need a generic way to do that).
+          retval = base;
+        }
+    }
+
+  return retval;
+}
+
+// Make a constant.
+
+tree_constant *
+octave_parser::make_constant (int op, token *tok_val)
+{
+  int l = tok_val->line ();
+  int c = tok_val->column ();
+
+  tree_constant *retval = 0;
+
+  switch (op)
+    {
+    case NUM:
+      {
+        octave_value tmp (tok_val->number ());
+        retval = new tree_constant (tmp, l, c);
+        retval->stash_original_text (tok_val->text_rep ());
+      }
+      break;
+
+    case IMAG_NUM:
+      {
+        octave_value tmp (Complex (0.0, tok_val->number ()));
+        retval = new tree_constant (tmp, l, c);
+        retval->stash_original_text (tok_val->text_rep ());
+      }
+      break;
+
+    case DQ_STRING:
+    case SQ_STRING:
+      {
+        std::string txt = tok_val->text ();
+
+        char delim = op == DQ_STRING ? '"' : '\'';
+        octave_value tmp (txt, delim);
+
+        if (txt.empty ())
+          {
+            if (op == DQ_STRING)
+              tmp = octave_null_str::instance;
+            else
+              tmp = octave_null_sq_str::instance;
+          }
+
+        retval = new tree_constant (tmp, l, c);
+
+        if (op == DQ_STRING)
+          txt = undo_string_escapes (txt);
+
+        // FIXME -- maybe this should also be handled by
+        // tok_val->text_rep () for character strings?
+        retval->stash_original_text (delim + txt + delim);
+      }
+      break;
+
+    default:
+      panic_impossible ();
+      break;
+    }
+
+  return retval;
+}
+
+// Make a function handle.
+
+tree_fcn_handle *
+octave_parser::make_fcn_handle (token *tok_val)
+{
+  int l = tok_val->line ();
+  int c = tok_val->column ();
+
+  tree_fcn_handle *retval = new tree_fcn_handle (tok_val->text (), l, c);
+
+  return retval;
+}
+
+// Make an anonymous function handle.
+
+tree_anon_fcn_handle *
+octave_parser::make_anon_fcn_handle (tree_parameter_list *param_list,
+                                     tree_statement *stmt)
+{
+  // FIXME -- need to get these from the location of the @ symbol.
+  int l = curr_lexer->input_line_number;
+  int c = curr_lexer->current_input_column;
+
+  tree_parameter_list *ret_list = 0;
+
+  symbol_table::scope_id fcn_scope = symbol_table::current_scope ();
+
+  if (parser_symtab_context.empty ())
+    panic_impossible ();
+
+  parser_symtab_context.pop ();
+
+  stmt->set_print_flag (false);
+
+  tree_statement_list *body = new tree_statement_list (stmt);
+
+  body->mark_as_anon_function_body ();
+
+  tree_anon_fcn_handle *retval
+    = new tree_anon_fcn_handle (param_list, ret_list, body, fcn_scope, l, c);
+  // FIXME: Stash the filename.  This does not work and produces
+  // errors when executed.
+  //retval->stash_file_name (curr_lexer->fcn_file_name);
+
+  return retval;
+}
+
+// Build a binary expression.
+
+tree_expression *
+octave_parser::make_binary_op (int op, tree_expression *op1, token *tok_val,
+                               tree_expression *op2)
+{
+  octave_value::binary_op t = octave_value::unknown_binary_op;
+
+  switch (op)
+    {
+    case POW:
+      t = octave_value::op_pow;
+      break;
+
+    case EPOW:
+      t = octave_value::op_el_pow;
+      break;
+
+    case '+':
+      t = octave_value::op_add;
+      break;
+
+    case '-':
+      t = octave_value::op_sub;
+      break;
+
+    case '*':
+      t = octave_value::op_mul;
+      break;
+
+    case '/':
+      t = octave_value::op_div;
+      break;
+
+    case EMUL:
+      t = octave_value::op_el_mul;
+      break;
+
+    case EDIV:
+      t = octave_value::op_el_div;
+      break;
+
+    case LEFTDIV:
+      t = octave_value::op_ldiv;
+      break;
+
+    case ELEFTDIV:
+      t = octave_value::op_el_ldiv;
+      break;
+
+    case LSHIFT:
+      t = octave_value::op_lshift;
+      break;
+
+    case RSHIFT:
+      t = octave_value::op_rshift;
+      break;
+
+    case EXPR_LT:
+      t = octave_value::op_lt;
+      break;
+
+    case EXPR_LE:
+      t = octave_value::op_le;
+      break;
+
+    case EXPR_EQ:
+      t = octave_value::op_eq;
+      break;
+
+    case EXPR_GE:
+      t = octave_value::op_ge;
+      break;
+
+    case EXPR_GT:
+      t = octave_value::op_gt;
+      break;
+
+    case EXPR_NE:
+      t = octave_value::op_ne;
+      break;
+
+    case EXPR_AND:
+      t = octave_value::op_el_and;
+      break;
+
+    case EXPR_OR:
+      t = octave_value::op_el_or;
+      break;
+
+    default:
+      panic_impossible ();
+      break;
+    }
+
+  int l = tok_val->line ();
+  int c = tok_val->column ();
+
+  tree_binary_expression *e
+    = maybe_compound_binary_expression (op1, op2, l, c, t);
+
+  return fold (e);
+}
+
+// Build a boolean expression.
+
+tree_expression *
+octave_parser::make_boolean_op (int op, tree_expression *op1, token *tok_val,
+                                tree_expression *op2)
+{
+  tree_boolean_expression::type t;
+
+  switch (op)
+    {
+    case EXPR_AND_AND:
+      t = tree_boolean_expression::bool_and;
+      break;
+
+    case EXPR_OR_OR:
+      t = tree_boolean_expression::bool_or;
+      break;
+
+    default:
+      panic_impossible ();
+      break;
+    }
+
+  int l = tok_val->line ();
+  int c = tok_val->column ();
+
+  tree_boolean_expression *e
+    = new tree_boolean_expression (op1, op2, l, c, t);
+
+  return fold (e);
+}
+
+// Build a prefix expression.
+
+tree_expression *
+octave_parser::make_prefix_op (int op, tree_expression *op1, token *tok_val)
+{
+  octave_value::unary_op t = octave_value::unknown_unary_op;
+
+  switch (op)
+    {
+    case EXPR_NOT:
+      t = octave_value::op_not;
+      break;
+
+    case '+':
+      t = octave_value::op_uplus;
+      break;
+
+    case '-':
+      t = octave_value::op_uminus;
+      break;
+
+    case PLUS_PLUS:
+      t = octave_value::op_incr;
+      break;
+
+    case MINUS_MINUS:
+      t = octave_value::op_decr;
+      break;
+
+    default:
+      panic_impossible ();
+      break;
+    }
+
+  int l = tok_val->line ();
+  int c = tok_val->column ();
+
+  tree_prefix_expression *e
+    = new tree_prefix_expression (op1, l, c, t);
+
+  return fold (e);
+}
+
+// Build a postfix expression.
+
+tree_expression *
+octave_parser::make_postfix_op (int op, tree_expression *op1, token *tok_val)
+{
+  octave_value::unary_op t = octave_value::unknown_unary_op;
+
+  switch (op)
+    {
+    case QUOTE:
+      t = octave_value::op_hermitian;
+      break;
+
+    case TRANSPOSE:
+      t = octave_value::op_transpose;
+      break;
+
+    case PLUS_PLUS:
+      t = octave_value::op_incr;
+      break;
+
+    case MINUS_MINUS:
+      t = octave_value::op_decr;
+      break;
+
+    default:
+      panic_impossible ();
+      break;
+    }
+
+  int l = tok_val->line ();
+  int c = tok_val->column ();
+
+  tree_postfix_expression *e
+    = new tree_postfix_expression (op1, l, c, t);
+
+  return fold (e);
+}
+
+// Build an unwind-protect command.
+
+tree_command *
+octave_parser::make_unwind_command (token *unwind_tok,
+                                    tree_statement_list *body,
+                                    tree_statement_list *cleanup_stmts,
+                                    token *end_tok,
+                                    octave_comment_list *lc,
+                                    octave_comment_list *mc)
+{
+  tree_command *retval = 0;
+
+  if (end_token_ok (end_tok, token::unwind_protect_end))
+    {
+      octave_comment_list *tc = octave_comment_buffer::get_comment ();
+
+      int l = unwind_tok->line ();
+      int c = unwind_tok->column ();
+
+      retval = new tree_unwind_protect_command (body, cleanup_stmts,
+                                                lc, mc, tc, l, c);
+    }
+
+  return retval;
+}
+
+// Build a try-catch command.
+
+tree_command *
+octave_parser::make_try_command (token *try_tok, tree_statement_list *body,
+                                 tree_statement_list *cleanup_stmts,
+                                 token *end_tok,
+                                 octave_comment_list *lc,
+                                 octave_comment_list *mc)
+{
+  tree_command *retval = 0;
+
+  if (end_token_ok (end_tok, token::try_catch_end))
+    {
+      octave_comment_list *tc = octave_comment_buffer::get_comment ();
+
+      int l = try_tok->line ();
+      int c = try_tok->column ();
+
+      retval = new tree_try_catch_command (body, cleanup_stmts,
+                                           lc, mc, tc, l, c);
+    }
+
+  return retval;
+}
+
+// Build a while command.
+
+tree_command *
+octave_parser::make_while_command (token *while_tok, tree_expression *expr,
+                                   tree_statement_list *body, token *end_tok,
+                                   octave_comment_list *lc)
+{
+  tree_command *retval = 0;
+
+  maybe_warn_assign_as_truth_value (expr);
+
+  if (end_token_ok (end_tok, token::while_end))
+    {
+      octave_comment_list *tc = octave_comment_buffer::get_comment ();
+
+      curr_lexer->looping--;
+
+      int l = while_tok->line ();
+      int c = while_tok->column ();
+
+      retval = new tree_while_command (expr, body, lc, tc, l, c);
+    }
+
+  return retval;
+}
+
+// Build a do-until command.
+
+tree_command *
+octave_parser::make_do_until_command (token *until_tok,
+                                      tree_statement_list *body,
+                                      tree_expression *expr,
+                                      octave_comment_list *lc)
+{
+  tree_command *retval = 0;
+
+  maybe_warn_assign_as_truth_value (expr);
+
+  octave_comment_list *tc = octave_comment_buffer::get_comment ();
+
+  curr_lexer->looping--;
+
+  int l = until_tok->line ();
+  int c = until_tok->column ();
+
+  retval = new tree_do_until_command (expr, body, lc, tc, l, c);
+
+  return retval;
+}
+
+// Build a for command.
+
+tree_command *
+octave_parser::make_for_command (int tok_id, token *for_tok,
+                                 tree_argument_list *lhs,
+                                 tree_expression *expr,
+                                 tree_expression *maxproc,
+                                 tree_statement_list *body, token *end_tok,
+                                 octave_comment_list *lc)
+{
+  tree_command *retval = 0;
+
+  bool parfor = tok_id == PARFOR;
+
+  if (end_token_ok (end_tok, parfor ? token::parfor_end : token::for_end))
+    {
+      octave_comment_list *tc = octave_comment_buffer::get_comment ();
+
+      curr_lexer->looping--;
+
+      int l = for_tok->line ();
+      int c = for_tok->column ();
+
+      if (lhs->length () == 1)
+        {
+          tree_expression *tmp = lhs->remove_front ();
+
+          retval = new tree_simple_for_command (parfor, tmp, expr, maxproc,
+                                                body, lc, tc, l, c);
+
+          delete lhs;
+        }
+      else
+        {
+          if (parfor)
+            bison_error ("invalid syntax for parfor statement");
+          else
+            retval = new tree_complex_for_command (lhs, expr, body,
+                                                   lc, tc, l, c);
+        }
+    }
+
+  return retval;
+}
+
+// Build a break command.
+
+tree_command *
+octave_parser::make_break_command (token *break_tok)
+{
+  tree_command *retval = 0;
+
+  int l = break_tok->line ();
+  int c = break_tok->column ();
+
+  retval = new tree_break_command (l, c);
+
+  return retval;
+}
+
+// Build a continue command.
+
+tree_command *
+octave_parser::make_continue_command (token *continue_tok)
+{
+  tree_command *retval = 0;
+
+  int l = continue_tok->line ();
+  int c = continue_tok->column ();
+
+  retval = new tree_continue_command (l, c);
+
+  return retval;
+}
+
+// Build a return command.
+
+tree_command *
+octave_parser::make_return_command (token *return_tok)
+{
+  tree_command *retval = 0;
+
+  int l = return_tok->line ();
+  int c = return_tok->column ();
+
+  retval = new tree_return_command (l, c);
+
+  return retval;
+}
+
+// Start an if command.
+
+tree_if_command_list *
+octave_parser::start_if_command (tree_expression *expr,
+                                 tree_statement_list *list)
+{
+  maybe_warn_assign_as_truth_value (expr);
+
+  tree_if_clause *t = new tree_if_clause (expr, list);
+
+  return new tree_if_command_list (t);
+}
+
+// Finish an if command.
+
+tree_if_command *
+octave_parser::finish_if_command (token *if_tok, tree_if_command_list *list,
+                                  token *end_tok, octave_comment_list *lc)
+{
+  tree_if_command *retval = 0;
+
+  if (end_token_ok (end_tok, token::if_end))
+    {
+      octave_comment_list *tc = octave_comment_buffer::get_comment ();
+
+      int l = if_tok->line ();
+      int c = if_tok->column ();
+
+      if (list && ! list->empty ())
+        {
+          tree_if_clause *elt = list->front ();
+
+          if (elt)
+            {
+              elt->line (l);
+              elt->column (c);
+            }
+        }
+
+      retval = new tree_if_command (list, lc, tc, l, c);
+    }
+
+  return retval;
+}
+
+// Build an elseif clause.
+
+tree_if_clause *
+octave_parser::make_elseif_clause (token *elseif_tok, tree_expression *expr,
+                                   tree_statement_list *list,
+                                   octave_comment_list *lc)
+{
+  maybe_warn_assign_as_truth_value (expr);
+
+  int l = elseif_tok->line ();
+  int c = elseif_tok->column ();
+
+  return new tree_if_clause (expr, list, lc, l, c);
+}
+
+// Finish a switch command.
+
+tree_switch_command *
+octave_parser::finish_switch_command (token *switch_tok, tree_expression *expr,
+                                      tree_switch_case_list *list,
+                                      token *end_tok, octave_comment_list *lc)
+{
+  tree_switch_command *retval = 0;
+
+  if (end_token_ok (end_tok, token::switch_end))
+    {
+      octave_comment_list *tc = octave_comment_buffer::get_comment ();
+
+      int l = switch_tok->line ();
+      int c = switch_tok->column ();
+
+      if (list && ! list->empty ())
+        {
+          tree_switch_case *elt = list->front ();
+
+          if (elt)
+            {
+              elt->line (l);
+              elt->column (c);
+            }
+        }
+
+      retval = new tree_switch_command (expr, list, lc, tc, l, c);
+    }
+
+  return retval;
+}
+
+// Build a switch case.
+
+tree_switch_case *
+octave_parser::make_switch_case (token *case_tok, tree_expression *expr,
+                                 tree_statement_list *list,
+                                 octave_comment_list *lc)
+{
+  maybe_warn_variable_switch_label (expr);
+
+  int l = case_tok->line ();
+  int c = case_tok->column ();
+
+  return new tree_switch_case (expr, list, lc, l, c);
+}
+
+// Build an assignment to a variable.
+
+tree_expression *
+octave_parser::make_assign_op (int op, tree_argument_list *lhs, token *eq_tok,
+                               tree_expression *rhs)
+{
+  tree_expression *retval = 0;
+
+  octave_value::assign_op t = octave_value::unknown_assign_op;
+
+  switch (op)
+    {
+    case '=':
+      t = octave_value::op_asn_eq;
+      break;
+
+    case ADD_EQ:
+      t = octave_value::op_add_eq;
+      break;
+
+    case SUB_EQ:
+      t = octave_value::op_sub_eq;
+      break;
+
+    case MUL_EQ:
+      t = octave_value::op_mul_eq;
+      break;
+
+    case DIV_EQ:
+      t = octave_value::op_div_eq;
+      break;
+
+    case LEFTDIV_EQ:
+      t = octave_value::op_ldiv_eq;
+      break;
+
+    case POW_EQ:
+      t = octave_value::op_pow_eq;
+      break;
+
+    case LSHIFT_EQ:
+      t = octave_value::op_lshift_eq;
+      break;
+
+    case RSHIFT_EQ:
+      t = octave_value::op_rshift_eq;
+      break;
+
+    case EMUL_EQ:
+      t = octave_value::op_el_mul_eq;
+      break;
+
+    case EDIV_EQ:
+      t = octave_value::op_el_div_eq;
+      break;
+
+    case ELEFTDIV_EQ:
+      t = octave_value::op_el_ldiv_eq;
+      break;
+
+    case EPOW_EQ:
+      t = octave_value::op_el_pow_eq;
+      break;
+
+    case AND_EQ:
+      t = octave_value::op_el_and_eq;
+      break;
+
+    case OR_EQ:
+      t = octave_value::op_el_or_eq;
+      break;
+
+    default:
+      panic_impossible ();
+      break;
+    }
+
+  int l = eq_tok->line ();
+  int c = eq_tok->column ();
+
+  if (lhs->is_simple_assign_lhs ())
+    {
+      tree_expression *tmp = lhs->remove_front ();
+
+      retval = new tree_simple_assignment (tmp, rhs, false, l, c, t);
+
+      delete lhs;
+    }
+  else if (t == octave_value::op_asn_eq)
+    return new tree_multi_assignment (lhs, rhs, false, l, c);
+  else
+    bison_error ("computed multiple assignment not allowed");
+
+  return retval;
+}
+
+// Define a script.
+
+void
+octave_parser::make_script (tree_statement_list *cmds,
+                            tree_statement *end_script)
+{
+  if (! cmds)
+    cmds = new tree_statement_list ();
+
+  cmds->append (end_script);
+
+  octave_user_script *script
+    = new octave_user_script (curr_lexer->fcn_file_full_name,
+                              curr_lexer->fcn_file_name,
+                              cmds, curr_lexer->help_text);
+
+  curr_lexer->help_text = "";
+
+  octave_time now;
+
+  script->stash_fcn_file_time (now);
+
+  primary_fcn_ptr = script;
+
+  // Unmark any symbols that may have been tagged as local variables
+  // while parsing (for example, by force_local_variable in lex.l).
+
+  symbol_table::unmark_forced_variables ();
+}
+
+// Begin defining a function.
+
+octave_user_function *
+octave_parser::start_function (tree_parameter_list *param_list,
+                               tree_statement_list *body,
+                               tree_statement *end_fcn_stmt)
+{
+  // We'll fill in the return list later.
+
+  if (! body)
+    body = new tree_statement_list ();
+
+  body->append (end_fcn_stmt);
+
+  octave_user_function *fcn
+    = new octave_user_function (symbol_table::current_scope (),
+                                param_list, 0, body);
+
+  if (fcn)
+    {
+      octave_comment_list *tc = octave_comment_buffer::get_comment ();
+
+      fcn->stash_trailing_comment (tc);
+    }
+
+  return fcn;
+}
+
+tree_statement *
+octave_parser::make_end (const std::string& type, int l, int c)
+{
+  return make_statement (new tree_no_op_command (type, l, c));
+}
+
+// Do most of the work for defining a function.
+
+octave_user_function *
+octave_parser::frob_function (const std::string& fname,
+                              octave_user_function *fcn)
+{
+  std::string id_name = fname;
+
+  // If input is coming from a file, issue a warning if the name of
+  // the file does not match the name of the function stated in the
+  // file.  Matlab doesn't provide a diagnostic (it ignores the stated
+  // name).
+  if (! autoloading && curr_lexer->reading_fcn_file
+      && curr_fcn_depth == 1 && ! parsing_subfunctions)
+  {
+    // FIXME -- should curr_lexer->fcn_file_name already be
+    // preprocessed when we get here?  It seems to only be a
+    // problem with relative file names.
+
+    std::string nm = curr_lexer->fcn_file_name;
+
+    size_t pos = nm.find_last_of (file_ops::dir_sep_chars ());
+
+    if (pos != std::string::npos)
+      nm = curr_lexer->fcn_file_name.substr (pos+1);
+
+    if (nm != id_name)
+      {
+        warning_with_id
+          ("Octave:function-name-clash",
+           "function name '%s' does not agree with function file name '%s'",
+           id_name.c_str (), curr_lexer->fcn_file_full_name.c_str ());
+
+        id_name = nm;
+      }
+  }
+
+  if (curr_lexer->reading_fcn_file || curr_lexer->reading_classdef_file || autoloading)
+    {
+      octave_time now;
+
+      fcn->stash_fcn_file_name (curr_lexer->fcn_file_full_name);
+      fcn->stash_fcn_file_time (now);
+      fcn->mark_as_system_fcn_file ();
+
+      if (fcn_file_from_relative_lookup)
+        fcn->mark_relative ();
+
+      if (curr_fcn_depth > 1 || parsing_subfunctions)
+        {
+          fcn->stash_parent_fcn_name (curr_lexer->fcn_file_name);
+
+          if (curr_fcn_depth > 1)
+            fcn->stash_parent_fcn_scope (function_scopes[function_scopes.size ()-2]);
+          else
+            fcn->stash_parent_fcn_scope (primary_fcn_scope);
+        }
+
+      if (curr_lexer->parsing_class_method)
+        {
+          if (curr_class_name == id_name)
+            fcn->mark_as_class_constructor ();
+          else
+            fcn->mark_as_class_method ();
+
+          fcn->stash_dispatch_class (curr_class_name);
+        }
+
+      std::string nm = fcn->fcn_file_name ();
+
+      file_stat fs (nm);
+
+      if (fs && fs.is_newer (now))
+        warning_with_id ("Octave:future-time-stamp",
+                         "time stamp for '%s' is in the future", nm.c_str ());
+    }
+  else if (! input_from_tmp_history_file
+           && ! curr_lexer->force_script
+           && curr_lexer->reading_script_file
+           && curr_lexer->fcn_file_name == id_name)
+    {
+      warning ("function '%s' defined within script file '%s'",
+               id_name.c_str (), curr_lexer->fcn_file_full_name.c_str ());
+    }
+
+  fcn->stash_function_name (id_name);
+  fcn->stash_fcn_location (curr_lexer->input_line_number,
+                           curr_lexer->current_input_column);
+
+  if (! curr_lexer->help_text.empty () && curr_fcn_depth == 1
+      && ! parsing_subfunctions)
+    {
+      fcn->document (curr_lexer->help_text);
+
+      curr_lexer->help_text = "";
+    }
+
+  if (curr_lexer->reading_fcn_file && curr_fcn_depth == 1
+      && ! parsing_subfunctions)
+    primary_fcn_ptr = fcn;
+
+  return fcn;
+}
+
+tree_function_def *
+octave_parser::finish_function (tree_parameter_list *ret_list,
+                                octave_user_function *fcn,
+                                octave_comment_list *lc)
+{
+  tree_function_def *retval = 0;
+
+  if (ret_list)
+    ret_list->mark_as_formal_parameters ();
+
+  if (fcn)
+    {
+      std::string nm = fcn->name ();
+      std::string file = fcn->fcn_file_name ();
+
+      std::string tmp = nm;
+      if (! file.empty ())
+        tmp += ": " + file;
+
+      symbol_table::cache_name (fcn->scope (), tmp);
+
+      if (lc)
+        fcn->stash_leading_comment (lc);
+
+      fcn->define_ret_list (ret_list);
+
+      if (curr_fcn_depth > 1 || parsing_subfunctions)
+        {
+          fcn->mark_as_subfunction ();
+
+          if (endfunction_found && function_scopes.size () > 1)
+            {
+              symbol_table::scope_id pscope
+                = function_scopes[function_scopes.size ()-2];
+
+              symbol_table::install_nestfunction (nm, octave_value (fcn),
+                                                  pscope);
+            }
+          else
+            symbol_table::install_subfunction (nm, octave_value (fcn),
+                                               primary_fcn_scope);
+        }
+
+      if (curr_fcn_depth == 1 && fcn)
+        symbol_table::update_nest (fcn->scope ());
+
+      if (! curr_lexer->reading_fcn_file && curr_fcn_depth == 1)
+        {
+          // We are either reading a script file or defining a function
+          // at the command line, so this definition creates a
+          // tree_function object that is placed in the parse tree.
+          // Otherwise, it is just inserted in the symbol table,
+          // either as a subfunction or nested function (see above),
+          // or as the primary function for the file, via
+          // primary_fcn_ptr (see also load_fcn_from_file,,
+          // parse_fcn_file, and
+          // symbol_table::fcn_info::fcn_info_rep::find_user_function).
+
+          retval = new tree_function_def (fcn);
+        }
+
+      // Unmark any symbols that may have been tagged as local
+      // variables while parsing (for example, by force_local_variable
+      // in lex.l).
+
+      symbol_table::unmark_forced_variables (fcn->scope ());
+    }
+
+  return retval;
+}
+
+void
+octave_parser::recover_from_parsing_function (void)
+{
+  if (parser_symtab_context.empty ())
+    panic_impossible ();
+
+  parser_symtab_context.pop ();
+
+  if (curr_lexer->reading_fcn_file && curr_fcn_depth == 1
+      && ! parsing_subfunctions)
+    parsing_subfunctions = true;
+
+  curr_fcn_depth--;
+  function_scopes.pop_back ();
+
+  curr_lexer->defining_func--;
+  curr_lexer->parsed_function_name.pop ();
+  curr_lexer->looking_at_return_list = false;
+  curr_lexer->looking_at_parameter_list = false;
+}
+
+tree_funcall *
+octave_parser::make_superclass_ref (const std::string& method_nm,
+                                    const std::string& package_nm,
+                                    const std::string& class_nm,
+                                    int l, int c)
+{
+  octave_value_list args;
+
+  args(2) = class_nm;
+  args(1) = package_nm;
+  args(0) = method_nm;
+
+  octave_value fcn
+    = symbol_table::find_built_in_function ("__superclass_reference__");
+
+  return new tree_funcall (fcn, args);
+}
+
+tree_funcall *
+octave_parser::make_meta_class_query (const std::string& package_nm,
+                                      const std::string& class_nm,
+                                      int l, int c)
+{
+  octave_value_list args;
+
+  args(1) = class_nm;
+  args(0) = package_nm;
+
+  octave_value fcn
+    = symbol_table::find_built_in_function ("__meta_class_query__");
+
+  return new tree_funcall (fcn, args);
+}
+
+// A CLASSDEF block defines a class that has a constructor and other
+// methods, but it is not an executable command.  Parsing the block
+// makes some changes in the symbol table (inserting the constructor
+// and methods, and adding to the list of known objects) and creates
+// a parse tree containing meta information about the class.
+
+tree_classdef *
+octave_parser::make_classdef (token *tok_val,
+                              tree_classdef_attribute_list *a,
+                              tree_identifier *id,
+                              tree_classdef_superclass_list *sc,
+                              tree_classdef_body *body, token *end_tok,
+                              octave_comment_list *lc)
+{
+  tree_classdef *retval = 0;
+
+  std::string cls_name = id->name ();
+
+  std::string nm = curr_fcn_file_name;
+
+  size_t pos = nm.find_last_of (file_ops::dir_sep_chars ());
+
+  if (pos != std::string::npos)
+    nm = curr_fcn_file_name.substr (pos+1);
+
+  if (nm != cls_name)
+    {
+      bison_error ("invalid classdef definition, the class name must match the file name");
+      return retval;
+    }
+
+  if (end_token_ok (end_tok, token::classdef_end))
+    {
+      octave_comment_list *tc = octave_comment_buffer::get_comment ();
+
+      int l = tok_val->line ();
+      int c = tok_val->column ();
+
+      retval = new tree_classdef (a, id, sc, body, lc, tc, l, c);
+    }
+
+  return retval;
+}
+
+tree_classdef_properties_block *
+octave_parser::make_classdef_properties_block (token *tok_val,
+                                               tree_classdef_attribute_list *a,
+                                               tree_classdef_property_list *plist,
+                                               token *end_tok,
+                                               octave_comment_list *lc)
+{
+  tree_classdef_properties_block *retval = 0;
+
+  if (end_token_ok (end_tok, token::properties_end))
+    {
+      octave_comment_list *tc = octave_comment_buffer::get_comment ();
+
+      int l = tok_val->line ();
+      int c = tok_val->column ();
+
+      retval = new tree_classdef_properties_block (a, plist, lc, tc, l, c);
+    }
+
+  return retval;
+}
+
+tree_classdef_methods_block *
+octave_parser::make_classdef_methods_block (token *tok_val,
+                                            tree_classdef_attribute_list *a,
+                                            tree_classdef_methods_list *mlist,
+                                            token *end_tok,
+                                            octave_comment_list *lc)
+{
+  tree_classdef_methods_block *retval = 0;
+
+  if (end_token_ok (end_tok, token::methods_end))
+    {
+      octave_comment_list *tc = octave_comment_buffer::get_comment ();
+
+      int l = tok_val->line ();
+      int c = tok_val->column ();
+
+      retval = new tree_classdef_methods_block (a, mlist, lc, tc, l, c);
+    }
+
+  return retval;
+}
+
+tree_classdef_events_block *
+octave_parser::make_classdef_events_block (token *tok_val,
+                                           tree_classdef_attribute_list *a,
+                                           tree_classdef_events_list *elist,
+                                           token *end_tok,
+                                           octave_comment_list *lc)
+{
+  tree_classdef_events_block *retval = 0;
+
+  if (end_token_ok (end_tok, token::events_end))
+    {
+      octave_comment_list *tc = octave_comment_buffer::get_comment ();
+
+      int l = tok_val->line ();
+      int c = tok_val->column ();
+
+      retval = new tree_classdef_events_block (a, elist, lc, tc, l, c);
+    }
+
+  return retval;
+}
+
+tree_classdef_enum_block *
+octave_parser::make_classdef_enum_block (token *tok_val,
+                                         tree_classdef_attribute_list *a,
+                                         tree_classdef_enum_list *elist,
+                                         token *end_tok,
+                                         octave_comment_list *lc)
+{
+  tree_classdef_enum_block *retval = 0;
+
+  if (end_token_ok (end_tok, token::enumeration_end))
+    {
+      octave_comment_list *tc = octave_comment_buffer::get_comment ();
+
+      int l = tok_val->line ();
+      int c = tok_val->column ();
+
+      retval = new tree_classdef_enum_block (a, elist, lc, tc, l, c);
+    }
+
+  return retval;
+}
+
+// Make an index expression.
+
+tree_index_expression *
+octave_parser::make_index_expression (tree_expression *expr,
+                                      tree_argument_list *args, char type)
+{
+  tree_index_expression *retval = 0;
+
+  if (args && args->has_magic_tilde ())
+    {
+      bison_error ("invalid use of empty argument (~) in index expression");
+      return retval;
+    }
+
+  int l = expr->line ();
+  int c = expr->column ();
+
+  if (! expr->is_postfix_indexed ()) 
+    expr->set_postfix_index (type);
+
+  if (expr->is_index_expression ())
+    {
+      tree_index_expression *tmp = static_cast<tree_index_expression *> (expr);
+
+      tmp->append (args, type);
+
+      retval = tmp;
+    }
+  else
+    retval = new tree_index_expression (expr, args, l, c, type);
+
+  return retval;
+}
+
+// Make an indirect reference expression.
+
+tree_index_expression *
+octave_parser::make_indirect_ref (tree_expression *expr,
+                                  const std::string& elt)
+{
+  tree_index_expression *retval = 0;
+
+  int l = expr->line ();
+  int c = expr->column ();
+
+  if (! expr->is_postfix_indexed ()) 
+    expr->set_postfix_index ('.');
+
+  if (expr->is_index_expression ())
+    {
+      tree_index_expression *tmp = static_cast<tree_index_expression *> (expr);
+
+      tmp->append (elt);
+
+      retval = tmp;
+    }
+  else
+    retval = new tree_index_expression (expr, elt, l, c);
+
+  curr_lexer->looking_at_indirect_ref = false;
+
+  return retval;
+}
+
+// Make an indirect reference expression with dynamic field name.
+
+tree_index_expression *
+octave_parser::make_indirect_ref (tree_expression *expr, tree_expression *elt)
+{
+  tree_index_expression *retval = 0;
+
+  int l = expr->line ();
+  int c = expr->column ();
+
+  if (! expr->is_postfix_indexed ()) 
+    expr->set_postfix_index ('.');
+
+  if (expr->is_index_expression ())
+    {
+      tree_index_expression *tmp = static_cast<tree_index_expression *> (expr);
+
+      tmp->append (elt);
+
+      retval = tmp;
+    }
+  else
+    retval = new tree_index_expression (expr, elt, l, c);
+
+  curr_lexer->looking_at_indirect_ref = false;
+
+  return retval;
+}
+
+// Make a declaration command.
+
+tree_decl_command *
+octave_parser::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 PERSISTENT:
+      if (curr_fcn_depth > 0)
+        retval = new tree_persistent_command (lst, l, c);
+      else
+        {
+          if (curr_lexer->reading_script_file)
+            warning ("ignoring persistent declaration near line %d of file '%s'",
+                     l, curr_lexer->fcn_file_full_name.c_str ());
+          else
+            warning ("ignoring persistent declaration near line %d", l);
+        }
+      break;
+
+    default:
+      panic_impossible ();
+      break;
+    }
+
+  return retval;
+}
+
+tree_argument_list *
+octave_parser::validate_matrix_row (tree_argument_list *row)
+{
+  if (row && row->has_magic_tilde ())
+    bison_error ("invalid use of tilde (~) in matrix expression");
+  return row;
+}
+
+// Finish building a matrix list.
+
+tree_expression *
+octave_parser::finish_matrix (tree_matrix *m)
+{
+  tree_expression *retval = m;
+
+  unwind_protect frame;
+
+  frame.protect_var (error_state);
+  frame.protect_var (warning_state);
+
+  frame.protect_var (discard_error_messages);
+  frame.protect_var (discard_warning_messages);
+
+  discard_error_messages = true;
+  discard_warning_messages = true;
+
+  if (m->all_elements_are_constant ())
+    {
+      octave_value tmp = m->rvalue1 ();
+
+      if (! (error_state || warning_state))
+        {
+          tree_constant *tc_retval
+            = new tree_constant (tmp, m->line (), m->column ());
+
+          std::ostringstream buf;
+
+          tree_print_code tpc (buf);
+
+          m->accept (tpc);
+
+          tc_retval->stash_original_text (buf.str ());
+
+          delete m;
+
+          retval = tc_retval;
+        }
+    }
+
+  return retval;
+}
+
+// Finish building a cell list.
+
+tree_expression *
+octave_parser::finish_cell (tree_cell *c)
+{
+  return finish_matrix (c);
+}
+
+void
+octave_parser::maybe_warn_missing_semi (tree_statement_list *t)
+{
+  if (curr_fcn_depth > 0)
+    {
+      tree_statement *tmp = t->back ();
+
+      if (tmp->is_expression ())
+        warning_with_id
+          ("Octave:missing-semicolon",
+           "missing semicolon near line %d, column %d in file '%s'",
+            tmp->line (), tmp->column (), curr_lexer->fcn_file_full_name.c_str ());
+    }
+}
+
+tree_statement_list *
+octave_parser::set_stmt_print_flag (tree_statement_list *list, char sep,
+                                    bool warn_missing_semi)
+{
+  tree_statement *tmp = list->back ();
+
+  switch (sep)
+    {
+    case ';':
+      tmp->set_print_flag (false);
+      break;
+
+    case 0:
+    case ',':
+    case '\n':
+      tmp->set_print_flag (true);
+      if (warn_missing_semi)
+        maybe_warn_missing_semi (list);
+      break;
+
+    default:
+      warning ("unrecognized separator type!");
+      break;
+    }
+
+  // Even if a statement is null, we add it to the list then remove it
+  // here so that the print flag is applied to the correct statement.
+
+  if (tmp->is_null_statement ())
+    {
+      list->pop_back ();
+      delete tmp;
+    }
+
+  return list;
+}
+
+tree_statement_list *
+octave_parser::make_statement_list (tree_statement *stmt)
+{
+  return new tree_statement_list (stmt);
+}
+
+tree_statement_list *
+octave_parser::append_statement_list (tree_statement_list *list, char sep,
+                                      tree_statement *stmt,
+                                      bool warn_missing_semi)
+{
+  set_stmt_print_flag (list, sep, warn_missing_semi);
+
+  list->append (stmt);
+
+  return list;
+}
+
+void
+octave_parser::bison_error (const char *s)
+
+{
+  int err_col = curr_lexer->current_input_column - 1;
+
+  std::ostringstream output_buf;
+
+  if (curr_lexer->reading_fcn_file || curr_lexer->reading_script_file || curr_lexer->reading_classdef_file)
+    output_buf << "parse error near line " << curr_lexer->input_line_number
+               << " of file " << curr_lexer->fcn_file_full_name;
+  else
+    output_buf << "parse error:";
+
+  if (s && strcmp (s, "parse error") != 0)
+    output_buf << "\n\n  " << s;
+
+  output_buf << "\n\n";
+
+  if (! current_input_line.empty ())
+    {
+      size_t len = current_input_line.length ();
+
+      if (current_input_line[len-1] == '\n')
+        current_input_line.resize (len-1);
+
+      // Print the line, maybe with a pointer near the error token.
+
+      output_buf << ">>> " << current_input_line << "\n";
+
+      if (err_col == 0)
+        err_col = len;
+
+      for (int i = 0; i < err_col + 3; i++)
+        output_buf << " ";
+
+      output_buf << "^";
+    }
+
+  output_buf << "\n";
+
+  std::string msg = output_buf.str ();
+
+  parse_error ("%s", msg.c_str ());
+}
+
+static void
+safe_fclose (FILE *f)
+{
+  // FIXME -- comments at the end of an input file are
+  // discarded (otherwise, they would be appended to the next
+  // statement, possibly from the command line or another file, which
+  // can be quite confusing).
+
+  octave_comment_list *tc = octave_comment_buffer::get_comment ();
+
+  delete tc;
+
+  if (f)
+    fclose (static_cast<FILE *> (f));
+}
+
+static octave_function *
+parse_fcn_file (const std::string& full_file, const std::string& file,
+                const std::string& dispatch_type,
+                bool require_file, bool force_script, bool autoload,    
+                bool relative_lookup, const std::string& warn_for)
+{
+  unwind_protect frame;
+
+  octave_function *fcn_ptr = 0;
+
+  // Open function file and parse.
+
+  FILE *in_stream = command_editor::get_input_stream ();
+
+  frame.add_fcn (command_editor::set_input_stream, in_stream);
+
+  frame.protect_var (line_editing);
+
+  line_editing = false;
+
+  frame.add_fcn (command_history::ignore_entries,
+                 command_history::ignoring_entries ());
+
+  command_history::ignore_entries ();
+
+  FILE *ffile = 0;
+
+  if (! full_file.empty ())
+    ffile = gnulib::fopen (full_file.c_str (), "rb");
+
+  frame.add_fcn (safe_fclose, ffile);
+
+  if (ffile)
+    {
+      bool eof;
+
+      // octave_parser constructor sets this for us.
+      frame.protect_var (CURR_LEXER);
+
+<<<<<<< local
+      octave_parser *curr_parser = new octave_parser ();
+      frame.add_fcn (octave_parser::cleanup, curr_parser);
+=======
+      octave_parser curr_parser (ffile);
+>>>>>>> other
+
+<<<<<<< local
+      curr_parser->curr_class_name = dispatch_type;
+      curr_parser->autoloading = autoload;
+      curr_parser->fcn_file_from_relative_lookup = relative_lookup;
+=======
+      curr_parser.curr_class_name = dispatch_type;
+      curr_parser.autoloading = autoload;
+      curr_parser.fcn_file_from_relative_lookup = relative_lookup;
+>>>>>>> other
+
+<<<<<<< local
+      std::string help_txt
+        = gobble_leading_white_space
+            (ffile, eof,
+             curr_parser->curr_lexer->input_line_number,
+             curr_parser->curr_lexer->current_input_column);
+=======
+      // Do this with an unwind-protect cleanup function so that
+      // the forced variables will be unmarked in the event of an
+      // interrupt.
+      symbol_table::scope_id scope = symbol_table::top_scope ();
+      frame.add_fcn (symbol_table::unmark_forced_variables, scope);
+>>>>>>> other
+
+<<<<<<< local
+      if (! help_txt.empty ())
+        help_buf.push (help_txt);
+=======
+      curr_parser.curr_lexer->force_script = force_script;
+      curr_parser.curr_lexer->prep_for_file ();
+      curr_parser.curr_lexer->parsing_class_method = ! dispatch_type.empty ();
+>>>>>>> other
+
+<<<<<<< local
+      if (! eof)
+        {
+          std::string file_type;
+=======
+      curr_parser.curr_lexer->fcn_file_name = file;
+      curr_parser.curr_lexer->fcn_file_full_name = full_file;
+>>>>>>> other
+
+<<<<<<< local
+          frame.protect_var (get_input_from_eval_string);
+          frame.protect_var (reading_fcn_file);
+          frame.protect_var (reading_script_file);
+          frame.protect_var (reading_classdef_file);
+          frame.protect_var (Vecho_executing_commands);
+=======
+      int status = curr_parser.run ();
+>>>>>>> other
+
+<<<<<<< local
+          get_input_from_eval_string = false;
+=======
+      fcn_ptr = curr_parser.primary_fcn_ptr;
+>>>>>>> other
+
+<<<<<<< local
+          if (! force_script && looking_at_function_keyword (ffile))
+            {
+              file_type = "function";
+
+              Vecho_executing_commands = ECHO_OFF;
+
+              reading_classdef_file = false;
+              reading_fcn_file = true;
+              reading_script_file = false;
+            }
+          else if (! force_script && looking_at_classdef_keyword (ffile))
+            {
+              file_type = "classdef";
+
+              Vecho_executing_commands = ECHO_OFF;
+
+              reading_classdef_file = true;
+              reading_fcn_file = false;
+              reading_script_file = false;
+            }
+          else
+            {
+              file_type = "script";
+
+              Vecho_executing_commands = ECHO_OFF;
+
+              reading_classdef_file = false;
+              reading_fcn_file = false;
+              reading_script_file = true;
+            }
+
+          // Do this with an unwind-protect cleanup function so that
+          // the forced variables will be unmarked in the event of an
+          // interrupt.
+          symbol_table::scope_id scope = symbol_table::top_scope ();
+          frame.add_fcn (symbol_table::unmark_forced_variables, scope);
+
+          if (! help_txt.empty ())
+            help_buf.push (help_txt);
+
+          if (reading_script_file)
+            curr_parser->curr_lexer->prep_for_script_file ();
+          else if (reading_classdef_file)
+            curr_parser->curr_lexer->prep_for_classdef_file ();
+          else
+            curr_parser->curr_lexer->prep_for_function_file ();
+
+          curr_parser->curr_lexer->parsing_class_method = ! dispatch_type.empty ();
+
+          frame.protect_var (global_command);
+
+          global_command = 0;
+
+          int status = curr_parser->run ();
+
+          // Use an unwind-protect cleanup function so that the
+          // global_command list will be deleted in the event of an
+          // interrupt.
+
+          frame.add_fcn (cleanup_statement_list, &global_command);
+
+          fcn_ptr = curr_parser->primary_fcn_ptr;
+
+          if (status == 0)
+            {
+              if (reading_classdef_file && curr_parser->classdef_object)
+                {
+                  // Convert parse tree for classdef object to
+                  // meta.class info (and stash it in the symbol
+                  // table?).  Return pointer to constructor?
+
+                  if (fcn_ptr)
+                    panic_impossible ();
+
+                  fcn_ptr = curr_parser->classdef_object->make_meta_class ();
+                }
+            }
+          else
+            {
+              error ("parse error while reading %s file %s",
+                     file_type.c_str(), ff.c_str ());
+            }
+        }
+      else
+        {
+          int l = curr_parser->curr_lexer->input_line_number;
+          int c = curr_parser->curr_lexer->current_input_column;
+
+          tree_statement *end_of_script
+            = curr_parser->make_end ("endscript", l, c);
+
+          curr_parser->make_script (0, end_of_script);
+
+          fcn_ptr = curr_parser->primary_fcn_ptr;
+        }
+=======
+      if (status != 0)
+        error ("parse error while reading file %s", full_file.c_str ());
+>>>>>>> other
+    }
+  else if (require_file)
+    error ("no such file, '%s'", full_file.c_str ());
+  else if (! warn_for.empty ())
+    error ("%s: unable to open file '%s'", warn_for.c_str (),
+           full_file.c_str ());
+
+  return fcn_ptr;
+}
+
+std::string
+get_help_from_file (const std::string& nm, bool& symbol_found,
+                    std::string& full_file)
+{
+  std::string retval;
+
+  full_file = fcn_file_in_path (nm);
+
+  std::string file = full_file;
+
+  size_t file_len = file.length ();
+
+  if ((file_len > 4 && file.substr (file_len-4) == ".oct")
+      || (file_len > 4 && file.substr (file_len-4) == ".mex")
+      || (file_len > 2 && file.substr (file_len-2) == ".m"))
+    {
+      file = octave_env::base_pathname (file);
+      file = file.substr (0, file.find_last_of ('.'));
+
+      size_t pos = file.find_last_of (file_ops::dir_sep_str ());
+      if (pos != std::string::npos)
+        file = file.substr (pos+1);
+    }
+
+  if (! file.empty ())
+    {
+      symbol_found = true;
+
+      octave_function *fcn
+        = parse_fcn_file (full_file, file, "", true, false, false, false, "");
+
+      if (fcn)
+        {
+          retval = fcn->doc_string ();
+
+          delete fcn;
+        }
+    }
+
+  return retval;
+}
+
+std::string
+get_help_from_file (const std::string& nm, bool& symbol_found)
+{
+  std::string file;
+  return get_help_from_file (nm, symbol_found, file);
+}
+
+std::string
+lookup_autoload (const std::string& nm)
+{
+  std::string retval;
+
+  typedef std::map<std::string, std::string>::const_iterator am_iter;
+
+  am_iter p = autoload_map.find (nm);
+
+  if (p != autoload_map.end ())
+    retval = load_path::find_file (p->second);
+
+  return retval;
+}
+
+string_vector
+autoloaded_functions (void)
+{
+  string_vector names (autoload_map.size ());
+
+  octave_idx_type i = 0;
+  typedef std::map<std::string, std::string>::const_iterator am_iter;
+  for (am_iter p = autoload_map.begin (); p != autoload_map.end (); p++)
+    names[i++] = p->first;
+
+  return names;
+}
+
+string_vector
+reverse_lookup_autoload (const std::string& nm)
+{
+  string_vector names;
+
+  typedef std::map<std::string, std::string>::const_iterator am_iter;
+  for (am_iter p = autoload_map.begin (); p != autoload_map.end (); p++)
+    if (nm == p->second)
+      names.append (p->first);
+
+  return names;
+}
+
+octave_function *
+load_fcn_from_file (const std::string& file_name, const std::string& dir_name,
+                    const std::string& dispatch_type,
+                    const std::string& fcn_name, bool autoload)
+{
+  octave_function *retval = 0;
+
+  unwind_protect frame;
+
+  std::string nm = file_name;
+
+  size_t nm_len = nm.length ();
+
+  std::string file;
+
+  bool relative_lookup = false;
+
+  file = nm;
+
+  if ((nm_len > 4 && nm.substr (nm_len-4) == ".oct")
+      || (nm_len > 4 && nm.substr (nm_len-4) == ".mex")
+      || (nm_len > 2 && nm.substr (nm_len-2) == ".m"))
+    {
+      nm = octave_env::base_pathname (file);
+      nm = nm.substr (0, nm.find_last_of ('.'));
+
+      size_t pos = nm.find_last_of (file_ops::dir_sep_str ());
+      if (pos != std::string::npos)
+        nm = nm.substr (pos+1);
+    }
+
+  relative_lookup = ! octave_env::absolute_pathname (file);
+
+  file = octave_env::make_absolute (file);
+
+  int len = file.length ();
+
+  if (len > 4 && file.substr (len-4, len-1) == ".oct")
+    {
+      if (autoload && ! fcn_name.empty ())
+        nm = fcn_name;
+
+      retval = octave_dynamic_loader::load_oct (nm, file, relative_lookup);
+    }
+  else if (len > 4 && file.substr (len-4, len-1) == ".mex")
+    {
+      // Temporarily load m-file version of mex-file, if it exists,
+      // to get the help-string to use.
+
+      octave_function *tmpfcn = parse_fcn_file (file.substr (0, len - 2),
+                                                nm, dispatch_type, false,
+                                                autoload, autoload,
+                                                relative_lookup, "");
+
+      retval = octave_dynamic_loader::load_mex (nm, file, relative_lookup);
+
+      if (tmpfcn)
+        retval->document (tmpfcn->doc_string ());
+      delete tmpfcn;
+    }
+  else if (len > 2)
+    {
+      retval = parse_fcn_file (file, nm, dispatch_type, true, autoload,
+                               autoload, relative_lookup, "");
+    }
+
+  if (retval)
+    {
+      retval->stash_dir_name (dir_name);
+
+      if (retval->is_user_function ())
+        {
+          symbol_table::scope_id id = retval->scope ();
+
+          symbol_table::stash_dir_name_for_subfunctions (id, dir_name);
+        }
+    }
+
+  return retval;
+}
+
+DEFUN (autoload, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} {} autoload (@var{function}, @var{file})\n\
+Define @var{function} to autoload from @var{file}.\n\
+\n\
+The second argument, @var{file}, should be an absolute file name or\n\
+a file name in the same directory as the function or script from which\n\
+the autoload command was run.  @var{file} should not depend on the\n\
+Octave load path.\n\
+\n\
+Normally, calls to @code{autoload} appear in PKG_ADD script files that\n\
+are evaluated when a directory is added to the Octave's load path.  To\n\
+avoid having to hardcode directory names in @var{file}, if @var{file}\n\
+is in the same directory as the PKG_ADD script then\n\
+\n\
+@example\n\
+autoload (\"foo\", \"bar.oct\");\n\
+@end example\n\
+\n\
+@noindent\n\
+will load the function @code{foo} from the file @code{bar.oct}.  The above\n\
+when @code{bar.oct} is not in the same directory or uses like\n\
+\n\
+@example\n\
+autoload (\"foo\", file_in_loadpath (\"bar.oct\"))\n\
+@end example\n\
+\n\
+@noindent\n\
+are strongly discouraged, as their behavior might be unpredictable.\n\
+\n\
+With no arguments, return a structure containing the current autoload map.\n\
+@seealso{PKG_ADD}\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+  int nargin = args.length ();
+
+  if (nargin == 0)
+    {
+      Cell func_names (dim_vector (autoload_map.size (), 1));
+      Cell file_names (dim_vector (autoload_map.size (), 1));
+
+      octave_idx_type i = 0;
+      typedef std::map<std::string, std::string>::const_iterator am_iter;
+      for (am_iter p = autoload_map.begin (); p != autoload_map.end (); p++)
+        {
+          func_names(i) = p->first;
+          file_names(i) = p->second;
+
+          i++;
+        }
+
+      octave_map m;
+
+      m.assign ("function", func_names);
+      m.assign ("file", file_names);
+
+      retval = m;
+    }
+  else if (nargin == 2)
+    {
+      string_vector argv = args.make_argv ("autoload");
+
+      if (! error_state)
+        {
+          std::string nm = argv[2];
+
+          if (! octave_env::absolute_pathname (nm))
+            {
+              octave_user_code *fcn = octave_call_stack::caller_user_code ();
+
+              bool found = false;
+
+              if (fcn)
+                {
+                  std::string fname = fcn->fcn_file_name ();
+
+                  if (! fname.empty ())
+                    {
+                      fname = octave_env::make_absolute (fname);
+                      fname = fname.substr (0, fname.find_last_of (file_ops::dir_sep_str ()) + 1);
+
+                      file_stat fs (fname + nm);
+
+                      if (fs.exists ())
+                        {
+                          nm = fname + nm;
+                          found = true;
+                        }
+                    }
+                }
+              if (! found)
+                warning_with_id ("Octave:autoload-relative-file-name",
+                                 "autoload: '%s' is not an absolute file name",
+                                 nm.c_str ());
+            }
+          autoload_map[argv[1]] = nm;
+        }
+    }
+  else
+    print_usage ();
+
+  return retval;
+}
+
+void
+source_file (const std::string& file_name, const std::string& context,
+             bool verbose, bool require_file, const std::string& warn_for)
+{
+  // Map from absolute name of script file to recursion level.  We
+  // use a map instead of simply placing a limit on recursion in the
+  // source_file function so that two mutually recursive scripts
+  // written as
+  //
+  //   foo1.m:
+  //   ------
+  //   foo2
+  //
+  //   foo2.m:
+  //   ------
+  //   foo1
+  //
+  // and called with
+  //
+  //   foo1
+  //
+  // (for example) will behave the same if they are written as
+  //
+  //   foo1.m:
+  //   ------
+  //   source ("foo2.m")
+  //
+  //   foo2.m:
+  //   ------
+  //   source ("foo1.m")
+  //
+  // and called with
+  //
+  //   source ("foo1.m")
+  //
+  // (for example).
+
+  static std::map<std::string, int> source_call_depth;
+
+  std::string file_full_name = file_ops::tilde_expand (file_name);
+
+  file_full_name = octave_env::make_absolute (file_full_name);
+
+  unwind_protect frame;
+
+  if (source_call_depth.find (file_full_name) == source_call_depth.end ())
+    source_call_depth[file_full_name] = -1;
+
+  frame.protect_var (source_call_depth[file_full_name]);
+
+  source_call_depth[file_full_name]++;
+
+  if (source_call_depth[file_full_name] >= Vmax_recursion_depth)
+    {
+      error ("max_recursion_depth exceeded");
+      return;
+    }
+
+  if (! context.empty ())
+    {
+      if (context == "caller")
+        octave_call_stack::goto_caller_frame ();
+      else if (context == "base")
+        octave_call_stack::goto_base_frame ();
+      else
+        error ("source: context must be \"caller\" or \"base\"");
+
+      if (! error_state)
+        frame.add_fcn (octave_call_stack::pop);
+    }
+
+  if (! error_state)
+    {
+      octave_function *fcn = parse_fcn_file (file_full_name, file_name,
+                                             "", require_file, true,
+                                             false, false, warn_for);
+
+      if (! error_state)
+        {
+          if (fcn && fcn->is_user_script ())
+            {
+              octave_value_list args;
+
+              if (verbose)
+                {
+                  std::cout << "executing commands from " << file_full_name << " ... ";
+                  reading_startup_message_printed = true;
+                  std::cout.flush ();
+                }
+
+              fcn->do_multi_index_op (0, args);
+
+              if (verbose)
+                std::cout << "done." << std::endl;
+
+              delete fcn;
+            }
+        }
+      else
+        error ("source: error sourcing file '%s'",
+               file_full_name.c_str ());
+    }
+}
+
+DEFUN (mfilename, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn  {Built-in Function} {} mfilename ()\n\
+@deftypefnx {Built-in Function} {} mfilename (\"fullpath\")\n\
+@deftypefnx {Built-in Function} {} mfilename (\"fullpathext\")\n\
+Return the name of the currently executing file.  At the top-level,\n\
+return the empty string.  Given the argument @code{\"fullpath\"},\n\
+include the directory part of the file name, but not the extension.\n\
+Given the argument @code{\"fullpathext\"}, include the directory part\n\
+of the file name and the extension.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+  int nargin = args.length ();
+
+  if (nargin > 1)
+    {
+      print_usage ();
+      return retval;
+    }
+
+  std::string arg;
+
+  if (nargin == 1)
+    {
+      arg = args(0).string_value ();
+
+      if (error_state)
+        {
+          error ("mfilename: expecting argument to be a character string");
+          return retval;
+        }
+    }
+
+  std::string fname;
+
+  octave_user_code *fcn = octave_call_stack::caller_user_code ();
+
+  if (fcn)
+    {
+      fname = fcn->fcn_file_name ();
+
+      if (fname.empty ())
+        fname = fcn->name ();
+    }
+
+  if (arg == "fullpathext")
+    retval = fname;
+  else
+    {
+      size_t dpos = fname.rfind (file_ops::dir_sep_char ());
+      size_t epos = fname.rfind ('.');
+
+      if (epos <= dpos)
+        epos = std::string::npos;
+
+      fname = (epos != std::string::npos) ? fname.substr (0, epos) : fname;
+
+      if (arg == "fullpath")
+        retval = fname;
+      else
+        retval = (dpos != std::string::npos) ? fname.substr (dpos+1) : fname;
+    }
+
+  return retval;
+}
+
+
+DEFUN (source, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} {} source (@var{file})\n\
+Parse and execute the contents of @var{file}.  This is equivalent to\n\
+executing commands from a script file, but without requiring the file to\n\
+be named @file{@var{file}.m}.\n\
+@end deftypefn")
+{
+  octave_value_list retval;
+
+  int nargin = args.length ();
+
+  if (nargin == 1 || nargin == 2)
+    {
+      std::string file_name = args(0).string_value ();
+
+      if (! error_state)
+        {
+          std::string context;
+
+          if (nargin == 2)
+            context = args(1).string_value ();
+
+          if (! error_state)
+            source_file (file_name, context);
+          else
+            error ("source: expecting context to be character string");
+        }
+      else
+        error ("source: expecting file name as argument");
+    }
+  else
+    print_usage ();
+
+  return retval;
+}
+
+// Evaluate an Octave function (built-in or interpreted) and return
+// the list of result values.  NAME is the name of the function to
+// call.  ARGS are the arguments to the function.  NARGOUT is the
+// number of output arguments expected.
+
+octave_value_list
+feval (const std::string& name, const octave_value_list& args, int nargout)
+{
+  octave_value_list retval;
+
+  octave_value fcn = symbol_table::find_function (name, args);
+
+  if (fcn.is_defined ())
+    retval = fcn.do_multi_index_op (nargout, args);
+  else
+    {
+      maybe_missing_function_hook (name);
+      if (! error_state)
+        error ("feval: function '%s' not found", name.c_str ());
+    }
+
+  return retval;
+}
+
+octave_value_list
+feval (octave_function *fcn, const octave_value_list& args, int nargout)
+{
+  octave_value_list retval;
+
+  if (fcn)
+    retval = fcn->do_multi_index_op (nargout, args);
+
+  return retval;
+}
+
+static octave_value_list
+get_feval_args (const octave_value_list& args)
+{
+  return args.slice (1, args.length () - 1, true);
+}
+
+
+// Evaluate an Octave function (built-in or interpreted) and return
+// the list of result values.  The first element of ARGS should be a
+// string containing the name of the function to call, then the rest
+// are the actual arguments to the function.  NARGOUT is the number of
+// output arguments expected.
+
+octave_value_list
+feval (const octave_value_list& args, int nargout)
+{
+  octave_value_list retval;
+
+  int nargin = args.length ();
+
+  if (nargin > 0)
+    {
+      octave_value f_arg = args(0);
+
+      if (f_arg.is_string ())
+        {
+          std::string name = f_arg.string_value ();
+
+          if (! error_state)
+            {
+              octave_value_list tmp_args = get_feval_args (args);
+
+              retval = feval (name, tmp_args, nargout);
+            }
+        }
+      else if (f_arg.is_function_handle ()
+               || f_arg.is_anonymous_function ()
+               || f_arg.is_inline_function ())
+        {
+          const octave_value_list tmp_args = get_feval_args (args);
+
+          retval = f_arg.do_multi_index_op (nargout, tmp_args);
+        }
+      else
+        error ("feval: first argument must be a string, inline function or a function handle");
+    }
+
+  return retval;
+}
+
+DEFUN (feval, args, nargout,
+  "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} {} feval (@var{name}, @dots{})\n\
+Evaluate the function named @var{name}.  Any arguments after the first\n\
+are passed on to the named function.  For example,\n\
+\n\
+@example\n\
+@group\n\
+feval (\"acos\", -1)\n\
+     @result{} 3.1416\n\
+@end group\n\
+@end example\n\
+\n\
+@noindent\n\
+calls the function @code{acos} with the argument @samp{-1}.\n\
+\n\
+The function @code{feval} can also be used with function handles of\n\
+any sort (@pxref{Function Handles}).  Historically, @code{feval} was\n\
+the only way to call user-supplied functions in strings, but\n\
+function handles are now preferred due to the cleaner syntax they\n\
+offer.  For example,\n\
+\n\
+@example\n\
+@group\n\
+@var{f} = @@exp;\n\
+feval (@var{f}, 1)\n\
+    @result{} 2.7183\n\
+@var{f} (1)\n\
+    @result{} 2.7183\n\
+@end group\n\
+@end example\n\
+\n\
+@noindent\n\
+are equivalent ways to call the function referred to by @var{f}.  If it\n\
+cannot be predicted beforehand that @var{f} is a function handle or the\n\
+function name in a string, @code{feval} can be used instead.\n\
+@end deftypefn")
+{
+  octave_value_list retval;
+
+  int nargin = args.length ();
+
+  if (nargin > 0)
+    retval = feval (args, nargout);
+  else
+    print_usage ();
+
+  return retval;
+}
+
+DEFUN (builtin, args, nargout,
+  "-*- texinfo -*-\n\
+@deftypefn {Loadable Function} {[@dots{}]} builtin (@var{f}, @dots{})\n\
+Call the base function @var{f} even if @var{f} is overloaded to\n\
+another function for the given type signature.\n\
+@end deftypefn")
+{
+  octave_value_list retval;
+
+  int nargin = args.length ();
+
+  if (nargin > 0)
+    {
+      const std::string name (args(0).string_value ());
+
+      if (! error_state)
+        {
+          octave_value fcn = symbol_table::builtin_find (name);
+
+          if (fcn.is_defined ())
+            retval = feval (fcn.function_value (), args.splice (0, 1),
+                            nargout);
+          else
+            error ("builtin: lookup for symbol '%s' failed", name.c_str ());
+        }
+      else
+        error ("builtin: function name (F) must be a string");
+    }
+  else
+    print_usage ();
+
+  return retval;
+}
+
+octave_value_list
+eval_string (const std::string& eval_str, bool silent,
+             int& parse_status, int nargout)
+{
+  octave_value_list retval;
+
+  unwind_protect frame;
+
+  // octave_parser constructor sets this for us.
+  frame.protect_var (CURR_LEXER);
+
+  octave_parser curr_parser (eval_str);
+
+  frame.protect_var (line_editing);
+
+  line_editing = false;
+
+  do
+    {
+      curr_parser.reset ();
+
+      // Do this with an unwind-protect cleanup function so that the
+      // forced variables will be unmarked in the event of an
+      // interrupt.
+      symbol_table::scope_id scope = symbol_table::top_scope ();
+      frame.add_fcn (symbol_table::unmark_forced_variables, scope);
+
+      parse_status = curr_parser.run ();
+
+      // Unmark forced variables.
+      frame.run (1);
+
+      if (parse_status == 0)
+        {
+          if (curr_parser.stmt_list)
+            {
+              tree_statement *stmt = 0;
+
+              if (curr_parser.stmt_list->length () == 1
+                  && (stmt = curr_parser.stmt_list->front ())
+                  && stmt->is_expression ())
+                {
+                  tree_expression *expr = stmt->expression ();
+
+                  if (silent)
+                    expr->set_print_flag (false);
+
+                  bool do_bind_ans = false;
+
+                  if (expr->is_identifier ())
+                    {
+                      tree_identifier *id
+                        = dynamic_cast<tree_identifier *> (expr);
+
+                      do_bind_ans = (! id->is_variable ());
+                    }
+                  else
+                    do_bind_ans = (! expr->is_assignment_expression ());
+
+                  retval = expr->rvalue (nargout);
+
+                  if (do_bind_ans && ! (error_state || retval.empty ()))
+                    bind_ans (retval(0), expr->print_result ());
+
+                  if (nargout == 0)
+                    retval = octave_value_list ();
+                }
+              else if (nargout == 0)
+                curr_parser.stmt_list->accept (*current_evaluator);
+              else
+                error ("eval: invalid use of statement list");
+
+              if (error_state
+                  || tree_return_command::returning
+                  || tree_break_command::breaking
+                  || tree_continue_command::continuing)
+                break;
+            }
+          else if (curr_parser.curr_lexer->end_of_input)
+            break;
+        }
+    }
+  while (parse_status == 0);
+
+  return retval;
+}
+
+octave_value
+eval_string (const std::string& eval_str, bool silent, int& parse_status)
+{
+  octave_value retval;
+
+  octave_value_list tmp = eval_string (eval_str, silent, parse_status, 1);
+
+  if (! tmp.empty ())
+    retval = tmp(0);
+
+  return retval;
+}
+
+static octave_value_list
+eval_string (const octave_value& arg, bool silent, int& parse_status,
+             int nargout)
+{
+  std::string s = arg.string_value ();
+
+  if (error_state)
+    {
+      error ("eval: expecting std::string argument");
+      return octave_value (-1);
+    }
+
+  return eval_string (s, silent, parse_status, nargout);
+}
+
+void
+cleanup_statement_list (tree_statement_list **lst)
+{
+  if (*lst)
+    {
+      delete *lst;
+      *lst = 0;
+    }
+}
+
+DEFUN (eval, args, nargout,
+  "-*- texinfo -*-\n\
+@deftypefn  {Built-in Function} {} eval (@var{try})\n\
+@deftypefnx {Built-in Function} {} eval (@var{try}, @var{catch})\n\
+Parse the string @var{try} and evaluate it as if it were an Octave\n\
+program.  If that fails, evaluate the optional string @var{catch}.\n\
+The string @var{try} is evaluated in the current context,\n\
+so any results remain available after @code{eval} returns.\n\
+\n\
+The following example makes the variable @var{a} with the approximate\n\
+value 3.1416 available.\n\
+\n\
+@example\n\
+eval (\"a = acos(-1);\");\n\
+@end example\n\
+\n\
+If an error occurs during the evaluation of @var{try} the @var{catch}\n\
+string is evaluated, as the following example shows:\n\
+\n\
+@example\n\
+@group\n\
+eval ('error (\"This is a bad example\");',\n\
+      'printf (\"This error occurred:\\n%s\\n\", lasterr ());');\n\
+     @print{} This error occurred:\n\
+        This is a bad example\n\
+@end group\n\
+@end example\n\
+\n\
+Consider using try/catch blocks instead if you are only using @code{eval}\n\
+as an error-capturing mechanism rather than for the execution of arbitrary\n\
+code strings.\n\
+@seealso{evalin}\n\
+@end deftypefn")
+{
+  octave_value_list retval;
+
+  int nargin = args.length ();
+
+  if (nargin > 0)
+    {
+      unwind_protect frame;
+
+      if (nargin > 1)
+        {
+          frame.protect_var (buffer_error_messages);
+          buffer_error_messages++;
+        }
+
+      int parse_status = 0;
+
+      octave_value_list tmp = eval_string (args(0), nargout > 0,
+                                           parse_status, nargout);
+
+      if (nargin > 1 && (parse_status != 0 || error_state))
+        {
+          error_state = 0;
+
+          // Set up for letting the user print any messages from
+          // errors that occurred in the first part of this eval().
+
+          buffer_error_messages--;
+
+          tmp = eval_string (args(1), nargout > 0, parse_status, nargout);
+
+          if (nargout > 0)
+            retval = tmp;
+        }
+      else if (nargout > 0)
+        retval = tmp;
+    }
+  else
+    print_usage ();
+
+  return retval;
+}
+
+/*
+
+%!shared x
+%! x = 1;
+
+%!assert (eval ("x"), 1)
+%!assert (eval ("x;"))
+%!assert (eval ("x;"), 1);
+
+%!test
+%! y = eval ("x");
+%! assert (y, 1);
+
+%!test
+%! y = eval ("x;");
+%! assert (y, 1);
+
+%!test
+%! eval ("x = 1;")
+%! assert (x,1);
+
+%!test
+%! eval ("flipud = 2;");
+%! assert (flipud, 2);
+
+%!function y = __f ()
+%!  eval ("flipud = 2;");
+%!  y = flipud;
+%!endfunction
+%!assert (__f(), 2)
+
+% bug #35645
+%!test
+%! [a,] = gcd (1,2);
+%! [a,b,] = gcd (1, 2);
+
+*/
+
+DEFUN (assignin, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} {} assignin (@var{context}, @var{varname}, @var{value})\n\
+Assign @var{value} to @var{varname} in context @var{context}, which\n\
+may be either @code{\"base\"} or @code{\"caller\"}.\n\
+@seealso{evalin}\n\
+@end deftypefn")
+{
+  octave_value_list retval;
+
+  int nargin = args.length ();
+
+  if (nargin == 3)
+    {
+      std::string context = args(0).string_value ();
+
+      if (! error_state)
+        {
+          unwind_protect frame;
+
+          if (context == "caller")
+            octave_call_stack::goto_caller_frame ();
+          else if (context == "base")
+            octave_call_stack::goto_base_frame ();
+          else
+            error ("assignin: CONTEXT must be \"caller\" or \"base\"");
+
+          if (! error_state)
+            {
+              frame.add_fcn (octave_call_stack::pop);
+
+              std::string nm = args(1).string_value ();
+
+              if (! error_state)
+                {
+                  if (valid_identifier (nm))
+                    symbol_table::varref (nm) = args(2);
+                  else
+                    error ("assignin: invalid variable name in argument VARNAME");
+                }
+              else
+                error ("assignin: VARNAME must be a string");
+            }
+        }
+      else
+        error ("assignin: CONTEXT must be a string");
+    }
+  else
+    print_usage ();
+
+  return retval;
+}
+
+DEFUN (evalin, args, nargout,
+  "-*- texinfo -*-\n\
+@deftypefn  {Built-in Function} {} evalin (@var{context}, @var{try})\n\
+@deftypefnx {Built-in Function} {} evalin (@var{context}, @var{try}, @var{catch})\n\
+Like @code{eval}, except that the expressions are evaluated in the\n\
+context @var{context}, which may be either @code{\"caller\"} or\n\
+@code{\"base\"}.\n\
+@seealso{eval, assignin}\n\
+@end deftypefn")
+{
+  octave_value_list retval;
+
+  int nargin = args.length ();
+
+  if (nargin > 1)
+    {
+      std::string context = args(0).string_value ();
+
+      if (! error_state)
+        {
+          unwind_protect frame;
+
+          if (context == "caller")
+            octave_call_stack::goto_caller_frame ();
+          else if (context == "base")
+            octave_call_stack::goto_base_frame ();
+          else
+            error ("evalin: CONTEXT must be \"caller\" or \"base\"");
+
+          if (! error_state)
+            {
+              frame.add_fcn (octave_call_stack::pop);
+
+              if (nargin > 2)
+                {
+                  frame.protect_var (buffer_error_messages);
+                  buffer_error_messages++;
+                }
+
+              int parse_status = 0;
+
+              octave_value_list tmp = eval_string (args(1), nargout > 0,
+                                                   parse_status, nargout);
+
+              if (nargout > 0)
+                retval = tmp;
+
+              if (nargin > 2 && (parse_status != 0 || error_state))
+                {
+                  error_state = 0;
+
+                  // Set up for letting the user print any messages from
+                  // errors that occurred in the first part of this eval().
+
+                  buffer_error_messages--;
+
+                  tmp = eval_string (args(2), nargout > 0,
+                                     parse_status, nargout);
+
+                  retval = (nargout > 0) ? tmp : octave_value_list ();
+                }
+            }
+        }
+      else
+        error ("evalin: CONTEXT must be a string");
+    }
+  else
+    print_usage ();
+
+  return retval;
+}
+
+DEFUN (__parser_debug_flag__, args, nargout,
+  "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} {@var{old_val} =} __parser_debug_flag__ (@var{new_val}))\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+  bool debug_flag = octave_debug;
+
+  retval = set_internal_variable (debug_flag, args, nargout,
+                                  "__parser_debug_flag__");
+
+  octave_debug = debug_flag;
+
+  return retval;
+}
--- a/libinterp/parse-tree/oct-parse.yy	Thu Feb 28 02:04:24 2013 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4834 +0,0 @@
-/*
-
-Copyright (C) 1993-2012 John W. Eaton
-Copyright (C) 2009 David Grundberg
-Copyright (C) 2009-2010 VZLU Prague
-
-This file is part of Octave.
-
-Octave 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 3 of the License, or (at your
-option) any later version.
-
-Octave 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 Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-// Parser for Octave.
-
-// C decarations.
-
-%{
-#define YYDEBUG 1
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <cassert>
-#include <cstdio>
-#include <cstdlib>
-
-#include <iostream>
-#include <map>
-#include <sstream>
-
-#include "Cell.h"
-#include "Matrix.h"
-#include "cmd-edit.h"
-#include "cmd-hist.h"
-#include "file-ops.h"
-#include "file-stat.h"
-#include "oct-env.h"
-#include "oct-time.h"
-#include "quit.h"
-
-#include "comment-list.h"
-#include "defaults.h"
-#include "defun.h"
-#include "dirfns.h"
-#include "dynamic-ld.h"
-#include "error.h"
-#include "input.h"
-#include "lex.h"
-#include "load-path.h"
-#include "oct-hist.h"
-#include "oct-map.h"
-#include "ov-classdef.h"
-#include "ov-fcn-handle.h"
-#include "ov-usr-fcn.h"
-#include "ov-null-mat.h"
-#include "toplev.h"
-#include "pager.h"
-#include "parse.h"
-#include "parse-private.h"
-#include "pt-all.h"
-#include "pt-eval.h"
-#include "pt-funcall.h"
-#include "symtab.h"
-#include "token.h"
-#include "unwind-prot.h"
-#include "utils.h"
-#include "variables.h"
-
-// oct-parse.h must be included after pt-all.h
-#include <oct-parse.h>
-
-extern int octave_lex (YYSTYPE *, void *);
-
-// Global access to currently active lexer.
-// FIXME -- to be removed after more parser+lexer refactoring.
-lexical_feedback *CURR_LEXER = 0;
-
-#if defined (GNULIB_NAMESPACE)
-// Calls to the following functions appear in the generated output from
-// Bison without the namespace tag.  Redefine them so we will use them
-// via the gnulib namespace.
-#define fclose GNULIB_NAMESPACE::fclose
-#define fprintf GNULIB_NAMESPACE::fprintf
-#define malloc GNULIB_NAMESPACE::malloc
-#endif
-
-// Buffer for help text snagged from function files.
-std::stack<std::string> help_buf;
-
-// TRUE means we are using readline.
-// (--no-line-editing)
-bool line_editing = true;
-
-// TRUE means we printed messages about reading startup files.
-bool reading_startup_message_printed = false;
-
-// TRUE means input is coming from startup file.
-bool input_from_startup_file = false;
-
-// Keep track of symbol table information when parsing functions.
-symtab_context parser_symtab_context;
-
-// List of autoloads (function -> file mapping).
-static std::map<std::string, std::string> autoload_map;
-
-// Forward declarations for some functions defined at the bottom of
-// the file.
-
-static void yyerror (octave_parser *curr_parser, const char *s);
-
-// Finish building a statement.
-template <class T>
-static tree_statement *
-make_statement (T *arg)
-{
-  octave_comment_list *comment = octave_comment_buffer::get_comment ();
-
-  return new tree_statement (arg, comment);
-}
-
-#define ABORT_PARSE \
-  do \
-    { \
-      global_command = 0; \
-      yyerrok; \
-      if (! parser_symtab_context.empty ()) \
-        parser_symtab_context.pop (); \
-      if ((interactive || forced_interactive)   \
-          && ! get_input_from_eval_string)      \
-        YYACCEPT; \
-      else \
-        YYABORT; \
-    } \
-  while (0)
-
-#define curr_lexer curr_parser->curr_lexer
-#define scanner curr_lexer->scanner
-
-%}
-
-// Bison declarations.
-
-// Don't add spaces around the = here; it causes some versions of
-// bison to fail to properly recognize the directive.
-
-%name-prefix="octave_"
-
-// We are using the pure parser interface and the reentrant lexer
-// interface but the Octave parser and lexer are NOT properly
-// reentrant because both still use many global variables.  It should be
-// safe to create a parser object and call it while anotehr parser
-// object is active (to parse a callback function while the main
-// interactive parser is waiting for input, for example) if you take
-// care to properly save and restore (typically with an unwind_protect
-// object) relevant global values before and after the nested call.
-
-%define api.pure
-%parse-param { octave_parser *curr_parser }
-%lex-param { void *scanner }
-
-%union
-{
-  // The type of the basic tokens returned by the lexer.
-  token *tok_val;
-
-  // Comment strings that we need to deal with mid-rule.
-  octave_comment_list *comment_type;
-
-  // Types for the nonterminals we generate.
-  char sep_type;
-  token *tok_type;
-  tree *tree_type;
-  tree_matrix *tree_matrix_type;
-  tree_cell *tree_cell_type;
-  tree_expression *tree_expression_type;
-  tree_constant *tree_constant_type;
-  tree_fcn_handle *tree_fcn_handle_type;
-  tree_funcall *tree_funcall_type;
-  tree_function_def *tree_function_def_type;
-  tree_anon_fcn_handle *tree_anon_fcn_handle_type;
-  tree_identifier *tree_identifier_type;
-  tree_index_expression *tree_index_expression_type;
-  tree_colon_expression *tree_colon_expression_type;
-  tree_argument_list *tree_argument_list_type;
-  tree_parameter_list *tree_parameter_list_type;
-  tree_command *tree_command_type;
-  tree_if_command *tree_if_command_type;
-  tree_if_clause *tree_if_clause_type;
-  tree_if_command_list *tree_if_command_list_type;
-  tree_switch_command *tree_switch_command_type;
-  tree_switch_case *tree_switch_case_type;
-  tree_switch_case_list *tree_switch_case_list_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;
-  octave_user_function *octave_user_function_type;
-
-  tree_classdef *tree_classdef_type;
-  tree_classdef_attribute* tree_classdef_attribute_type;
-  tree_classdef_attribute_list* tree_classdef_attribute_list_type;
-  tree_classdef_superclass* tree_classdef_superclass_type;
-  tree_classdef_superclass_list* tree_classdef_superclass_list_type;
-  tree_classdef_body* tree_classdef_body_type;
-  tree_classdef_property* tree_classdef_property_type;
-  tree_classdef_property_list* tree_classdef_property_list_type;
-  tree_classdef_properties_block* tree_classdef_properties_block_type;
-  tree_classdef_methods_list* tree_classdef_methods_list_type;
-  tree_classdef_methods_block* tree_classdef_methods_block_type;
-  tree_classdef_event* tree_classdef_event_type;
-  tree_classdef_events_list* tree_classdef_events_list_type;
-  tree_classdef_events_block* tree_classdef_events_block_type;
-  tree_classdef_enum* tree_classdef_enum_type;
-  tree_classdef_enum_list* tree_classdef_enum_list_type;
-  tree_classdef_enum_block* tree_classdef_enum_block_type;
-}
-
-// Tokens with line and column information.
-%token <tok_val> '=' ':' '-' '+' '*' '/'
-%token <tok_val> ADD_EQ SUB_EQ MUL_EQ DIV_EQ LEFTDIV_EQ POW_EQ
-%token <tok_val> EMUL_EQ EDIV_EQ ELEFTDIV_EQ EPOW_EQ AND_EQ OR_EQ
-%token <tok_val> LSHIFT_EQ RSHIFT_EQ LSHIFT RSHIFT
-%token <tok_val> EXPR_AND_AND EXPR_OR_OR
-%token <tok_val> EXPR_AND EXPR_OR EXPR_NOT
-%token <tok_val> EXPR_LT EXPR_LE EXPR_EQ EXPR_NE EXPR_GE EXPR_GT
-%token <tok_val> LEFTDIV EMUL EDIV ELEFTDIV EPLUS EMINUS
-%token <tok_val> QUOTE TRANSPOSE
-%token <tok_val> PLUS_PLUS MINUS_MINUS POW EPOW
-%token <tok_val> NUM IMAG_NUM
-%token <tok_val> STRUCT_ELT
-%token <tok_val> NAME
-%token <tok_val> END
-%token <tok_val> DQ_STRING SQ_STRING
-%token <tok_val> FOR PARFOR WHILE DO UNTIL
-%token <tok_val> IF ELSEIF ELSE
-%token <tok_val> SWITCH CASE OTHERWISE
-%token <tok_val> BREAK CONTINUE FUNC_RET
-%token <tok_val> UNWIND CLEANUP
-%token <tok_val> TRY CATCH
-%token <tok_val> GLOBAL PERSISTENT
-%token <tok_val> FCN_HANDLE
-%token <tok_val> CLASSDEF
-%token <tok_val> PROPERTIES METHODS EVENTS ENUMERATION
-%token <tok_val> METAQUERY
-%token <tok_val> SUPERCLASSREF
-%token <tok_val> GET SET
-
-// Other tokens.
-%token END_OF_INPUT LEXICAL_ERROR
-%token FCN SCRIPT_FILE CLASSDEF_FILE FUNCTION_FILE
-// %token VARARGIN VARARGOUT
-%token CLOSE_BRACE
-
-// Nonterminals we construct.
-%type <comment_type> stash_comment function_beg
-%type <tok_type> classdef_beg
-%type <sep_type> sep_no_nl opt_sep_no_nl sep opt_sep opt_comma
-%type <tree_type> input
-%type <tree_constant_type> string constant magic_colon
-%type <tree_anon_fcn_handle_type> anon_fcn_handle
-%type <tree_fcn_handle_type> fcn_handle
-%type <tree_matrix_type> matrix_rows matrix_rows1
-%type <tree_cell_type> cell_rows cell_rows1
-%type <tree_expression_type> matrix cell
-%type <tree_expression_type> primary_expr oper_expr
-%type <tree_expression_type> simple_expr colon_expr assign_expr expression
-%type <tree_identifier_type> identifier fcn_name magic_tilde
-%type <tree_funcall_type> superclass_identifier meta_identifier
-%type <octave_user_function_type> function1 function2
-%type <tree_index_expression_type> word_list_cmd
-%type <tree_colon_expression_type> colon_expr1
-%type <tree_argument_list_type> arg_list word_list assign_lhs
-%type <tree_argument_list_type> cell_or_matrix_row
-%type <tree_parameter_list_type> param_list param_list1 param_list2
-%type <tree_parameter_list_type> return_list return_list1
-%type <tree_command_type> command select_command loop_command
-%type <tree_command_type> jump_command except_command
-%type <tree_function_def_type> function
-%type <tree_classdef_type> classdef
-%type <tree_command_type> script_file classdef_file
-%type <tree_command_type> function_file function_list
-%type <tree_if_command_type> if_command
-%type <tree_if_clause_type> elseif_clause else_clause
-%type <tree_if_command_list_type> if_cmd_list1 if_cmd_list
-%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_decl_elt_type> decl2
-%type <tree_decl_init_list_type> decl1
-%type <tree_decl_command_type> declaration
-%type <tree_statement_type> statement function_end
-%type <tree_statement_list_type> simple_list simple_list1 list list1
-%type <tree_statement_list_type> opt_list input1
-
-%type <tree_classdef_attribute_type> attr
-%type <tree_classdef_attribute_list_type> attr_list opt_attr_list
-%type <tree_classdef_superclass_type> superclass
-%type <tree_classdef_superclass_list_type> superclass_list opt_superclass_list
-%type <tree_classdef_body_type> class_body
-%type <tree_classdef_property_type> class_property
-%type <tree_classdef_property_list_type> property_list
-%type <tree_classdef_properties_block_type> properties_block
-%type <tree_classdef_methods_list_type> methods_list
-%type <tree_classdef_methods_block_type> methods_block
-%type <tree_classdef_event_type> class_event
-%type <tree_classdef_events_list_type> events_list
-%type <tree_classdef_events_block_type> events_block
-%type <tree_classdef_enum_type> class_enum
-%type <tree_classdef_enum_list_type> enum_list
-%type <tree_classdef_enum_block_type> enum_block
-
-// Precedence and associativity.
-%right '=' ADD_EQ SUB_EQ MUL_EQ DIV_EQ LEFTDIV_EQ POW_EQ EMUL_EQ EDIV_EQ ELEFTDIV_EQ EPOW_EQ OR_EQ AND_EQ LSHIFT_EQ RSHIFT_EQ
-%left EXPR_OR_OR
-%left EXPR_AND_AND
-%left EXPR_OR
-%left EXPR_AND
-%left EXPR_LT EXPR_LE EXPR_EQ EXPR_NE EXPR_GE EXPR_GT
-%left LSHIFT RSHIFT
-%left ':'
-%left '-' '+' EPLUS EMINUS
-%left '*' '/' LEFTDIV EMUL EDIV ELEFTDIV
-%right UNARY EXPR_NOT
-%left POW EPOW QUOTE TRANSPOSE
-%right PLUS_PLUS MINUS_MINUS
-%left '(' '.' '{'
-
-// Where to start.
-%start input
-
-%%
-
-// ==============================
-// Statements and statement lists
-// ==============================
-
-input           : input1
-                  {
-                    global_command = $1;
-                    promptflag = 1;
-                    YYACCEPT;
-                  }
-                | function_file
-                  { YYACCEPT; }
-                | classdef_file
-                  { YYACCEPT; }
-                | simple_list parse_error
-                  { ABORT_PARSE; }
-                | parse_error
-                  { ABORT_PARSE; }
-                ;
-
-input1          : '\n'
-                  { $$ = 0; }
-                | END_OF_INPUT
-                  {
-                    curr_parser->end_of_input = true;
-                    $$ = 0;
-                  }
-                | simple_list
-                  { $$ = $1; }
-                | simple_list '\n'
-                  { $$ = $1; }
-                | simple_list END_OF_INPUT
-                  { $$ = $1; }
-                ;
-
-simple_list     : simple_list1 opt_sep_no_nl
-                  { $$ = curr_parser->set_stmt_print_flag ($1, $2, false); }
-                ;
-
-simple_list1    : statement
-                  { $$ = curr_parser->make_statement_list ($1); }
-                | simple_list1 sep_no_nl statement
-                  { $$ = curr_parser->append_statement_list ($1, $2, $3, false); }
-                ;
-
-opt_list        : // empty
-                  { $$ = new tree_statement_list (); }
-                | list
-                  { $$ = $1; }
-                ;
-
-list            : list1 opt_sep
-                  { $$ = curr_parser->set_stmt_print_flag ($1, $2, true); }
-                ;
-
-list1           : statement
-                  { $$ = curr_parser->make_statement_list ($1); }
-                | list1 sep statement
-                  { $$ = curr_parser->append_statement_list ($1, $2, $3, true); }
-                ;
-
-statement       : expression
-                  { $$ = make_statement ($1); }
-                | command
-                  { $$ = make_statement ($1); }
-                | word_list_cmd
-                  { $$ = make_statement ($1); }
-                ;
-
-// =================
-// Word-list command
-// =================
-
-// These are not really like expressions since they can't appear on
-// the RHS of an assignment.  But they are also not like commands (IF,
-// WHILE, etc.
-
-word_list_cmd   : identifier word_list
-                  { $$ = curr_parser->make_index_expression ($1, $2, '('); }
-                ;
-
-word_list       : string
-                  { $$ = new tree_argument_list ($1); }
-                | word_list string
-                  {
-                    $1->append ($2);
-                    $$ = $1;
-                  }
-                ;
-
-// ===========
-// Expressions
-// ===========
-
-identifier      : NAME
-                  {
-                    symbol_table::symbol_record *sr = $1->sym_rec ();
-                    $$ = new tree_identifier (*sr, $1->line (), $1->column ());
-                  }
-                ;
-
-superclass_identifier
-                : SUPERCLASSREF
-                  {
-                    std::string method_nm = $1->superclass_method_name ();
-                    std::string package_nm = $1->superclass_package_name ();
-                    std::string class_nm = $1->superclass_class_name ();
-
-                    $$ = curr_parser->make_superclass_ref
-                                        (method_nm, package_nm, class_nm,
-                                         $1->line (), $1->column ());
-                  }
-                ;
-
-meta_identifier : METAQUERY
-                  {
-                    std::string package_nm = $1->meta_package_name ();
-                    std::string class_nm = $1->meta_class_name ();
-
-                    $$ = curr_parser->make_meta_class_query
-                                        (package_nm, class_nm,
-                                         $1->line (), $1->column ());
-                  }
-                ;
-
-string          : DQ_STRING
-                  { $$ = curr_parser->make_constant (DQ_STRING, $1); }
-                | SQ_STRING
-                  { $$ = curr_parser->make_constant (SQ_STRING, $1); }
-                ;
-
-constant        : NUM
-                  { $$ = curr_parser->make_constant (NUM, $1); }
-                | IMAG_NUM
-                  { $$ = curr_parser->make_constant (IMAG_NUM, $1); }
-                | string
-                  { $$ = $1; }
-                ;
-
-matrix          : '[' ']'
-                  {
-                    $$ = new tree_constant (octave_null_matrix::instance);
-                    curr_lexer->looking_at_matrix_or_assign_lhs = false;
-                    curr_lexer->pending_local_variables.clear ();
-                  }
-                | '[' ';' ']'
-                  {
-                    $$ = new tree_constant (octave_null_matrix::instance);
-                    curr_lexer->looking_at_matrix_or_assign_lhs = false;
-                    curr_lexer->pending_local_variables.clear ();
-                  }
-                | '[' ',' ']'
-                  {
-                    $$ = new tree_constant (octave_null_matrix::instance);
-                    curr_lexer->looking_at_matrix_or_assign_lhs = false;
-                    curr_lexer->pending_local_variables.clear ();
-                  }
-                | '[' matrix_rows ']'
-                  {
-                    $$ = curr_parser->finish_matrix ($2);
-                    curr_lexer->looking_at_matrix_or_assign_lhs = false;
-                    curr_lexer->pending_local_variables.clear ();
-                  }
-                ;
-
-matrix_rows     : matrix_rows1
-                  { $$ = $1; }
-                | matrix_rows1 ';'      // Ignore trailing semicolon.
-                  { $$ = $1; }
-                ;
-
-matrix_rows1    : cell_or_matrix_row
-                  { $$ = new tree_matrix ($1); }
-                | matrix_rows1 ';' cell_or_matrix_row
-                  {
-                    $1->append ($3);
-                    $$ = $1;
-                  }
-                ;
-
-cell            : '{' '}'
-                  { $$ = new tree_constant (octave_value (Cell ())); }
-                | '{' ';' '}'
-                  { $$ = new tree_constant (octave_value (Cell ())); }
-                | '{' cell_rows '}'
-                  { $$ = curr_parser->finish_cell ($2); }
-                ;
-
-cell_rows       : cell_rows1
-                  { $$ = $1; }
-                | cell_rows1 ';'        // Ignore trailing semicolon.
-                  { $$ = $1; }
-                ;
-
-cell_rows1      : cell_or_matrix_row
-                  { $$ = new tree_cell ($1); }
-                | cell_rows1 ';' cell_or_matrix_row
-                  {
-                    $1->append ($3);
-                    $$ = $1;
-                  }
-                ;
-
-cell_or_matrix_row
-                : arg_list
-                  { $$ = curr_parser->validate_matrix_row ($1); }
-                | arg_list ','  // Ignore trailing comma.
-                  { $$ = curr_parser->validate_matrix_row ($1); }
-                ;
-
-fcn_handle      : '@' FCN_HANDLE
-                  {
-                    $$ = curr_parser->make_fcn_handle ($2);
-                    curr_lexer->looking_at_function_handle--;
-                  }
-                ;
-
-anon_fcn_handle : '@' param_list statement
-                  {
-                    curr_lexer->quote_is_transpose = false;
-                    $$ = curr_parser->make_anon_fcn_handle ($2, $3);
-                  }
-                ;
-
-primary_expr    : identifier
-                  { $$ = $1; }
-                | constant
-                  { $$ = $1; }
-                | fcn_handle
-                  { $$ = $1; }
-                | matrix
-                  { $$ = $1; }
-                | cell
-                  { $$ = $1; }
-                | meta_identifier
-                  { $$ = $1; }
-                | superclass_identifier
-                  { $$ = $1; }
-                | '(' expression ')'
-                  { $$ = $2->mark_in_parens (); }
-                ;
-
-magic_colon     : ':'
-                  {
-                    octave_value tmp (octave_value::magic_colon_t);
-                    $$ = new tree_constant (tmp);
-                  }
-                ;
-
-magic_tilde     : EXPR_NOT
-                  {
-                    $$ = new tree_black_hole ();
-                  }
-                ;
-
-arg_list        : expression
-                  { $$ = new tree_argument_list ($1); }
-                | magic_colon
-                  { $$ = new tree_argument_list ($1); }
-                | magic_tilde
-                  { $$ = new tree_argument_list ($1); }
-                | arg_list ',' magic_colon
-                  {
-                    $1->append ($3);
-                    $$ = $1;
-                  }
-                | arg_list ',' magic_tilde
-                  {
-                    $1->append ($3);
-                    $$ = $1;
-                  }
-                | arg_list ',' expression
-                  {
-                    $1->append ($3);
-                    $$ = $1;
-                  }
-                ;
-
-indirect_ref_op : '.'
-                  { curr_lexer->looking_at_indirect_ref = true; }
-                ;
-
-oper_expr       : primary_expr
-                  { $$ = $1; }
-                | oper_expr PLUS_PLUS
-                  { $$ = curr_parser->make_postfix_op (PLUS_PLUS, $1, $2); }
-                | oper_expr MINUS_MINUS
-                  { $$ = curr_parser->make_postfix_op (MINUS_MINUS, $1, $2); }
-                | oper_expr '(' ')'
-                  { $$ = curr_parser->make_index_expression ($1, 0, '('); }
-                | oper_expr '(' arg_list ')'
-                  { $$ = curr_parser->make_index_expression ($1, $3, '('); }
-                | oper_expr '{' '}'
-                  { $$ = curr_parser->make_index_expression ($1, 0, '{'); }
-                | oper_expr '{' arg_list '}'
-                  { $$ = curr_parser->make_index_expression ($1, $3, '{'); }
-                | oper_expr QUOTE
-                  { $$ = curr_parser->make_postfix_op (QUOTE, $1, $2); }
-                | oper_expr TRANSPOSE
-                  { $$ = curr_parser->make_postfix_op (TRANSPOSE, $1, $2); }
-                | oper_expr indirect_ref_op STRUCT_ELT
-                  { $$ = curr_parser->make_indirect_ref ($1, $3->text ()); }
-                | oper_expr indirect_ref_op '(' expression ')'
-                  { $$ = curr_parser->make_indirect_ref ($1, $4); }
-                | PLUS_PLUS oper_expr %prec UNARY
-                  { $$ = curr_parser->make_prefix_op (PLUS_PLUS, $2, $1); }
-                | MINUS_MINUS oper_expr %prec UNARY
-                  { $$ = curr_parser->make_prefix_op (MINUS_MINUS, $2, $1); }
-                | EXPR_NOT oper_expr %prec UNARY
-                  { $$ = curr_parser->make_prefix_op (EXPR_NOT, $2, $1); }
-                | '+' oper_expr %prec UNARY
-                  { $$ = curr_parser->make_prefix_op ('+', $2, $1); }
-                | '-' oper_expr %prec UNARY
-                  { $$ = curr_parser->make_prefix_op ('-', $2, $1); }
-                | oper_expr POW oper_expr
-                  { $$ = curr_parser->make_binary_op (POW, $1, $2, $3); }
-                | oper_expr EPOW oper_expr
-                  { $$ = curr_parser->make_binary_op (EPOW, $1, $2, $3); }
-                | oper_expr '+' oper_expr
-                  { $$ = curr_parser->make_binary_op ('+', $1, $2, $3); }
-                | oper_expr '-' oper_expr
-                  { $$ = curr_parser->make_binary_op ('-', $1, $2, $3); }
-                | oper_expr '*' oper_expr
-                  { $$ = curr_parser->make_binary_op ('*', $1, $2, $3); }
-                | oper_expr '/' oper_expr
-                  { $$ = curr_parser->make_binary_op ('/', $1, $2, $3); }
-                | oper_expr EPLUS oper_expr
-                  { $$ = curr_parser->make_binary_op ('+', $1, $2, $3); }
-                | oper_expr EMINUS oper_expr
-                  { $$ = curr_parser->make_binary_op ('-', $1, $2, $3); }
-                | oper_expr EMUL oper_expr
-                  { $$ = curr_parser->make_binary_op (EMUL, $1, $2, $3); }
-                | oper_expr EDIV oper_expr
-                  { $$ = curr_parser->make_binary_op (EDIV, $1, $2, $3); }
-                | oper_expr LEFTDIV oper_expr
-                  { $$ = curr_parser->make_binary_op (LEFTDIV, $1, $2, $3); }
-                | oper_expr ELEFTDIV oper_expr
-                  { $$ = curr_parser->make_binary_op (ELEFTDIV, $1, $2, $3); }
-                ;
-
-colon_expr      : colon_expr1
-                  { $$ = curr_parser->finish_colon_expression ($1); }
-                ;
-
-colon_expr1     : oper_expr
-                  { $$ = new tree_colon_expression ($1); }
-                | colon_expr1 ':' oper_expr
-                  {
-                    if (! ($$ = $1->append ($3)))
-                      ABORT_PARSE;
-                  }
-                ;
-
-simple_expr     : colon_expr
-                  { $$ = $1; }
-                | simple_expr LSHIFT simple_expr
-                  { $$ = curr_parser->make_binary_op (LSHIFT, $1, $2, $3); }
-                | simple_expr RSHIFT simple_expr
-                  { $$ = curr_parser->make_binary_op (RSHIFT, $1, $2, $3); }
-                | simple_expr EXPR_LT simple_expr
-                  { $$ = curr_parser->make_binary_op (EXPR_LT, $1, $2, $3); }
-                | simple_expr EXPR_LE simple_expr
-                  { $$ = curr_parser->make_binary_op (EXPR_LE, $1, $2, $3); }
-                | simple_expr EXPR_EQ simple_expr
-                  { $$ = curr_parser->make_binary_op (EXPR_EQ, $1, $2, $3); }
-                | simple_expr EXPR_GE simple_expr
-                  { $$ = curr_parser->make_binary_op (EXPR_GE, $1, $2, $3); }
-                | simple_expr EXPR_GT simple_expr
-                  { $$ = curr_parser->make_binary_op (EXPR_GT, $1, $2, $3); }
-                | simple_expr EXPR_NE simple_expr
-                  { $$ = curr_parser->make_binary_op (EXPR_NE, $1, $2, $3); }
-                | simple_expr EXPR_AND simple_expr
-                  { $$ = curr_parser->make_binary_op (EXPR_AND, $1, $2, $3); }
-                | simple_expr EXPR_OR simple_expr
-                  { $$ = curr_parser->make_binary_op (EXPR_OR, $1, $2, $3); }
-                | simple_expr EXPR_AND_AND simple_expr
-                  { $$ = curr_parser->make_boolean_op (EXPR_AND_AND, $1, $2, $3); }
-                | simple_expr EXPR_OR_OR simple_expr
-                  { $$ = curr_parser->make_boolean_op (EXPR_OR_OR, $1, $2, $3); }
-                ;
-
-// Arrange for the lexer to return CLOSE_BRACE for ']' by looking ahead
-// one token for an assignment op.
-
-assign_lhs      : simple_expr
-                  {
-                    $$ = new tree_argument_list ($1);
-                    $$->mark_as_simple_assign_lhs ();
-                  }
-                | '[' arg_list opt_comma CLOSE_BRACE
-                  {
-                    $$ = $2;
-                    curr_lexer->looking_at_matrix_or_assign_lhs = false;
-                    for (std::set<std::string>::const_iterator p = curr_lexer->pending_local_variables.begin ();
-                         p != curr_lexer->pending_local_variables.end ();
-                         p++)
-                      {
-                        symbol_table::force_variable (*p);
-                      }
-                    curr_lexer->pending_local_variables.clear ();
-                  }
-                ;
-
-assign_expr     : assign_lhs '=' expression
-                  { $$ = curr_parser->make_assign_op ('=', $1, $2, $3); }
-                | assign_lhs ADD_EQ expression
-                  { $$ = curr_parser->make_assign_op (ADD_EQ, $1, $2, $3); }
-                | assign_lhs SUB_EQ expression
-                  { $$ = curr_parser->make_assign_op (SUB_EQ, $1, $2, $3); }
-                | assign_lhs MUL_EQ expression
-                  { $$ = curr_parser->make_assign_op (MUL_EQ, $1, $2, $3); }
-                | assign_lhs DIV_EQ expression
-                  { $$ = curr_parser->make_assign_op (DIV_EQ, $1, $2, $3); }
-                | assign_lhs LEFTDIV_EQ expression
-                  { $$ = curr_parser->make_assign_op (LEFTDIV_EQ, $1, $2, $3); }
-                | assign_lhs POW_EQ expression
-                  { $$ = curr_parser->make_assign_op (POW_EQ, $1, $2, $3); }
-                | assign_lhs LSHIFT_EQ expression
-                  { $$ = curr_parser->make_assign_op (LSHIFT_EQ, $1, $2, $3); }
-                | assign_lhs RSHIFT_EQ expression
-                  { $$ = curr_parser->make_assign_op (RSHIFT_EQ, $1, $2, $3); }
-                | assign_lhs EMUL_EQ expression
-                  { $$ = curr_parser->make_assign_op (EMUL_EQ, $1, $2, $3); }
-                | assign_lhs EDIV_EQ expression
-                  { $$ = curr_parser->make_assign_op (EDIV_EQ, $1, $2, $3); }
-                | assign_lhs ELEFTDIV_EQ expression
-                  { $$ = curr_parser->make_assign_op (ELEFTDIV_EQ, $1, $2, $3); }
-                | assign_lhs EPOW_EQ expression
-                  { $$ = curr_parser->make_assign_op (EPOW_EQ, $1, $2, $3); }
-                | assign_lhs AND_EQ expression
-                  { $$ = curr_parser->make_assign_op (AND_EQ, $1, $2, $3); }
-                | assign_lhs OR_EQ expression
-                  { $$ = curr_parser->make_assign_op (OR_EQ, $1, $2, $3); }
-                ;
-
-expression      : simple_expr
-                  { $$ = $1; }
-                | assign_expr
-                  { $$ = $1; }
-                | anon_fcn_handle
-                  { $$ = $1; }
-                ;
-
-// ================================================
-// Commands, declarations, and function definitions
-// ================================================
-
-command         : declaration
-                  { $$ = $1; }
-                | select_command
-                  { $$ = $1; }
-                | loop_command
-                  { $$ = $1; }
-                | jump_command
-                  { $$ = $1; }
-                | except_command
-                  { $$ = $1; }
-                | function
-                  { $$ = $1; }
-                | script_file
-                  { $$ = $1; }
-                ;
-
-// =====================
-// Declaration statemnts
-// =====================
-
-parsing_decl_list
-                : // empty
-                  { curr_lexer->looking_at_decl_list = true; }
-
-declaration     : GLOBAL parsing_decl_list decl1
-                  {
-                    $$ = curr_parser->make_decl_command (GLOBAL, $1, $3);
-                    curr_lexer->looking_at_decl_list = false;
-                  }
-                | PERSISTENT parsing_decl_list decl1
-                  {
-                    $$ = curr_parser->make_decl_command (PERSISTENT, $1, $3);
-                    curr_lexer->looking_at_decl_list = false;
-                  }
-                ;
-
-decl1           : decl2
-                  { $$ = new tree_decl_init_list ($1); }
-                | decl1 decl2
-                  {
-                    $1->append ($2);
-                    $$ = $1;
-                  }
-                ;
-
-decl_param_init : // empty
-                { curr_lexer->looking_at_initializer_expression = true; }
-
-decl2           : identifier
-                  { $$ = new tree_decl_elt ($1); }
-                | identifier '=' decl_param_init expression
-                  {
-                    curr_lexer->looking_at_initializer_expression = false;
-                    $$ = new tree_decl_elt ($1, $4);
-                  }
-                | magic_tilde
-                  {
-                    $$ = new tree_decl_elt ($1);
-                  }
-                ;
-
-// ====================
-// Selection statements
-// ====================
-
-select_command  : if_command
-                  { $$ = $1; }
-                | switch_command
-                  { $$ = $1; }
-                ;
-
-// ============
-// If statement
-// ============
-
-if_command      : IF stash_comment if_cmd_list END
-                  {
-                    if (! ($$ = curr_parser->finish_if_command ($1, $3, $4, $2)))
-                      ABORT_PARSE;
-                  }
-                ;
-
-if_cmd_list     : if_cmd_list1
-                  { $$ = $1; }
-                | if_cmd_list1 else_clause
-                  {
-                    $1->append ($2);
-                    $$ = $1;
-                  }
-                ;
-
-if_cmd_list1    : expression opt_sep opt_list
-                  {
-                    $1->mark_braindead_shortcircuit (curr_fcn_file_full_name);
-
-                    $$ = curr_parser->start_if_command ($1, $3);
-                  }
-                | if_cmd_list1 elseif_clause
-                  {
-                    $1->append ($2);
-                    $$ = $1;
-                  }
-                ;
-
-elseif_clause   : ELSEIF stash_comment opt_sep expression opt_sep opt_list
-                  {
-                    $4->mark_braindead_shortcircuit (curr_fcn_file_full_name);
-
-                    $$ = curr_parser->make_elseif_clause ($1, $4, $6, $2);
-                  }
-                ;
-
-else_clause     : ELSE stash_comment opt_sep opt_list
-                  { $$ = new tree_if_clause ($4, $2); }
-                ;
-
-// ================
-// Switch statement
-// ================
-
-switch_command  : SWITCH stash_comment expression opt_sep case_list END
-                  {
-                    if (! ($$ = curr_parser->finish_switch_command ($1, $3, $5, $6, $2)))
-                      ABORT_PARSE;
-                  }
-                ;
-
-case_list       : // empty
-                  { $$ = new tree_switch_case_list (); }
-                | default_case
-                  { $$ = new tree_switch_case_list ($1); }
-                | case_list1
-                  { $$ = $1; }
-                | case_list1 default_case
-                  {
-                    $1->append ($2);
-                    $$ = $1;
-                  }
-                ;
-
-case_list1      : switch_case
-                  { $$ = new tree_switch_case_list ($1); }
-                | case_list1 switch_case
-                  {
-                    $1->append ($2);
-                    $$ = $1;
-                  }
-                ;
-
-switch_case     : CASE stash_comment opt_sep expression opt_sep opt_list
-                  { $$ = curr_parser->make_switch_case ($1, $4, $6, $2); }
-                ;
-
-default_case    : OTHERWISE stash_comment opt_sep opt_list
-                  {
-                    $$ = new tree_switch_case ($4, $2);
-                  }
-                ;
-
-// =======
-// Looping
-// =======
-
-loop_command    : WHILE stash_comment expression opt_sep opt_list END
-                  {
-                    $3->mark_braindead_shortcircuit (curr_fcn_file_full_name);
-
-                    if (! ($$ = curr_parser->make_while_command ($1, $3, $5, $6, $2)))
-                      ABORT_PARSE;
-                  }
-                | DO stash_comment opt_sep opt_list UNTIL expression
-                  {
-                    if (! ($$ = curr_parser->make_do_until_command ($5, $4, $6, $2)))
-                      ABORT_PARSE;
-                  }
-                | FOR stash_comment assign_lhs '=' expression opt_sep opt_list END
-                  {
-                    if (! ($$ = curr_parser->make_for_command (FOR, $1, $3, $5, 0,
-                                                  $7, $8, $2)))
-                      ABORT_PARSE;
-                  }
-                | FOR stash_comment '(' assign_lhs '=' expression ')' opt_sep opt_list END
-                  {
-                    if (! ($$ = curr_parser->make_for_command (FOR, $1, $4, $6, 0,
-                                                  $9, $10, $2)))
-                      ABORT_PARSE;
-                  }
-                | PARFOR stash_comment assign_lhs '=' expression opt_sep opt_list END
-                  {
-                    if (! ($$ = curr_parser->make_for_command (PARFOR, $1, $3, $5,
-                                                  0, $7, $8, $2)))
-                      ABORT_PARSE;
-                  }
-                | PARFOR stash_comment '(' assign_lhs '=' expression ',' expression ')' opt_sep opt_list END
-                  {
-                    if (! ($$ = curr_parser->make_for_command (PARFOR, $1, $4, $6,
-                                                  $8, $11, $12, $2)))
-                      ABORT_PARSE;
-                  }
-                ;
-
-// =======
-// Jumping
-// =======
-
-jump_command    : BREAK
-                  {
-                    if (! ($$ = curr_parser->make_break_command ($1)))
-                      ABORT_PARSE;
-                  }
-                | CONTINUE
-                  {
-                    if (! ($$ = curr_parser->make_continue_command ($1)))
-                      ABORT_PARSE;
-                  }
-                | FUNC_RET
-                  {
-                    if (! ($$ = curr_parser->make_return_command ($1)))
-                      ABORT_PARSE;
-                  }
-                ;
-
-// ==========
-// Exceptions
-// ==========
-
-except_command  : UNWIND stash_comment opt_sep opt_list CLEANUP
-                  stash_comment opt_sep opt_list END
-                  {
-                    if (! ($$ = curr_parser->make_unwind_command ($1, $4, $8, $9, $2, $6)))
-                      ABORT_PARSE;
-                  }
-                | TRY stash_comment opt_sep opt_list CATCH
-                  stash_comment opt_sep opt_list END
-                  {
-                    if (! ($$ = curr_parser->make_try_command ($1, $4, $8, $9, $2, $6)))
-                      ABORT_PARSE;
-                  }
-                | TRY stash_comment opt_sep opt_list END
-                  {
-                    if (! ($$ = curr_parser->make_try_command ($1, $4, 0, $5, $2, 0)))
-                      ABORT_PARSE;
-                  }
-                ;
-
-// ===========================================
-// Some 'subroutines' for function definitions
-// ===========================================
-
-push_fcn_symtab : // empty
-                  {
-                    curr_parser->curr_fcn_depth++;
-
-                    if (curr_parser->max_fcn_depth < curr_parser->curr_fcn_depth)
-                      curr_parser->max_fcn_depth = curr_parser->curr_fcn_depth;
-
-                    parser_symtab_context.push ();
-
-                    symbol_table::set_scope (symbol_table::alloc_scope ());
-
-                    curr_parser->function_scopes.push_back (symbol_table::current_scope ());
-
-                    if (! reading_script_file && curr_parser->curr_fcn_depth == 1
-                        && ! curr_parser->parsing_subfunctions)
-                      curr_parser->primary_fcn_scope = symbol_table::current_scope ();
-
-                    if (reading_script_file && curr_parser->curr_fcn_depth > 1)
-                      curr_parser->bison_error ("nested functions not implemented in this context");
-                  }
-                ;
-
-// ===========================
-// List of function parameters
-// ===========================
-
-param_list_beg  : '('
-                  {
-                    curr_lexer->looking_at_parameter_list = true;
-
-                    if (curr_lexer->looking_at_function_handle)
-                      {
-                        parser_symtab_context.push ();
-                        symbol_table::set_scope (symbol_table::alloc_scope ());
-                        curr_lexer->looking_at_function_handle--;
-                        curr_lexer->looking_at_anon_fcn_args = true;
-                      }
-                  }
-                ;
-
-param_list_end  : ')'
-                  {
-                    curr_lexer->looking_at_parameter_list = false;
-                    curr_lexer->looking_for_object_index = false;
-                  }
-                ;
-
-param_list      : param_list_beg param_list1 param_list_end
-                  {
-                    curr_lexer->quote_is_transpose = false;
-                    $$ = $2;
-                  }
-                | param_list_beg error
-                  {
-                    curr_parser->bison_error ("invalid parameter list");
-                    $$ = 0;
-                    ABORT_PARSE;
-                  }
-                ;
-
-param_list1     : // empty
-                  { $$ = 0; }
-                | param_list2
-                  {
-                    $1->mark_as_formal_parameters ();
-                    if ($1->validate (tree_parameter_list::in))
-                      $$ = $1;
-                    else
-                      ABORT_PARSE;
-                  }
-                ;
-
-param_list2     : decl2
-                  { $$ = new tree_parameter_list ($1); }
-                | param_list2 ',' decl2
-                  {
-                    $1->append ($3);
-                    $$ = $1;
-                  }
-                ;
-
-// ===================================
-// List of function return value names
-// ===================================
-
-return_list     : '[' ']'
-                  {
-                    curr_lexer->looking_at_return_list = false;
-                    $$ = new tree_parameter_list ();
-                  }
-                | return_list1
-                  {
-                    curr_lexer->looking_at_return_list = false;
-                    if ($1->validate (tree_parameter_list::out))
-                      $$ = $1;
-                    else
-                      ABORT_PARSE;
-                  }
-                | '[' return_list1 ']'
-                  {
-                    curr_lexer->looking_at_return_list = false;
-                    if ($2->validate (tree_parameter_list::out))
-                      $$ = $2;
-                    else
-                      ABORT_PARSE;
-                  }
-                ;
-
-return_list1    : identifier
-                  { $$ = new tree_parameter_list (new tree_decl_elt ($1)); }
-                | return_list1 ',' identifier
-                  {
-                    $1->append (new tree_decl_elt ($3));
-                    $$ = $1;
-                  }
-                ;
-
-// ===========
-// Script file
-// ===========
-
-script_file     : SCRIPT_FILE opt_list END_OF_INPUT
-                  {
-                    tree_statement *end_of_script
-                      = curr_parser->make_end ("endscript",
-                                               curr_lexer->input_line_number,
-                                               curr_lexer->current_input_column);
-
-                    curr_parser->make_script ($2, end_of_script);
-
-                    $$ = 0;
-                  }
-                ;
-
-// =============
-// Function file
-// =============
-
-function_file   : FUNCTION_FILE function_list opt_sep END_OF_INPUT
-                  { $$ = 0; }
-                ;
-
-function_list   : function
-                | function_list sep function
-                ;
-
-// ===================
-// Function definition
-// ===================
-
-function_beg    : push_fcn_symtab FCN stash_comment
-                  {
-                    $$ = $3;
-
-                    if (reading_classdef_file || curr_lexer->parsing_classdef)
-                      curr_lexer->maybe_classdef_get_set_method = true;
-                  }
-                ;
-
-function        : function_beg function1
-                  {
-                    $$ = curr_parser->finish_function (0, $2, $1);
-                    curr_parser->recover_from_parsing_function ();
-                  }
-                | function_beg return_list '=' function1
-                  {
-                    $$ = curr_parser->finish_function ($2, $4, $1);
-                    curr_parser->recover_from_parsing_function ();
-                  }
-                ;
-
-fcn_name        : identifier
-                  {
-                    std::string id_name = $1->name ();
-
-                    curr_lexer->parsed_function_name.top () = true;
-                    curr_lexer->maybe_classdef_get_set_method = false;
-
-                    $$ = $1;
-                  }
-                | GET '.' identifier
-                  {
-                    curr_lexer->parsed_function_name.top () = true;
-                    curr_lexer->maybe_classdef_get_set_method = false;
-                    curr_lexer->parsing_classdef_get_method = true;
-                    $$ = $3;
-                  }
-                | SET '.' identifier
-                  {
-                    curr_lexer->parsed_function_name.top () = true;
-                    curr_lexer->maybe_classdef_get_set_method = false;
-                    curr_lexer->parsing_classdef_set_method = true;
-                    $$ = $3;
-                  }
-                ;
-
-function1       : fcn_name function2
-                  {
-                    std::string fname = $1->name ();
-
-                    delete $1;
-
-                    if (! ($$ = curr_parser->frob_function (fname, $2)))
-                      ABORT_PARSE;
-                  }
-                ;
-
-function2       : param_list opt_sep opt_list function_end
-                  { $$ = curr_parser->start_function ($1, $3, $4); }
-                | opt_sep opt_list function_end
-                  { $$ = curr_parser->start_function (0, $2, $3); }
-                ;
-
-function_end    : END
-                  {
-                    curr_parser->endfunction_found = true;
-                    if (curr_parser->end_token_ok ($1, token::function_end))
-                      $$ = curr_parser->make_end ("endfunction", $1->line (), $1->column ());
-                    else
-                      ABORT_PARSE;
-                  }
-                | END_OF_INPUT
-                  {
-// A lot of tests are based on the assumption that this is OK
-//                  if (reading_script_file)
-//                    {
-//                      curr_parser->bison_error ("function body open at end of script");
-//                      YYABORT;
-//                    }
-
-                    if (curr_parser->endfunction_found)
-                      {
-                        curr_parser->bison_error ("inconsistent function endings -- "
-                                 "if one function is explicitly ended, "
-                                 "so must all the others");
-                        YYABORT;
-                      }
-
-                    if (! (reading_fcn_file || reading_script_file
-                           || get_input_from_eval_string))
-                      {
-                        curr_parser->bison_error ("function body open at end of input");
-                        YYABORT;
-                      }
-
-                    if (reading_classdef_file)
-                      {
-                        curr_parser->bison_error ("classdef body open at end of input");
-                        YYABORT;
-                      }
-
-                    $$ = curr_parser->make_end ("endfunction",
-                                                curr_lexer->input_line_number,
-                                                curr_lexer->current_input_column);
-                  }
-                ;
-
-// =============
-// Classdef file
-// =============
-
-classdef_file   : CLASSDEF_FILE classdef opt_sep END_OF_INPUT
-                  {
-                    curr_parser->classdef_object = $2;
-                    $$ = 0;
-                  }
-                ;
-
-// ========
-// Classdef
-// ========
-
-classdef_beg    : CLASSDEF
-                  {
-                    if (! reading_classdef_file)
-                      {
-                        curr_parser->bison_error ("classdef must appear inside a file containing only a class definition");
-                        YYABORT;
-                      }
-
-                    curr_lexer->parsing_classdef = true;
-                    $$ = $1;
-                  }
-                ;
-
-classdef        : classdef_beg stash_comment opt_attr_list identifier opt_superclass_list opt_sep class_body opt_sep END
-                  {
-                    curr_lexer->parsing_classdef = false;
-                    if (! ($$ = curr_parser->make_classdef ($1, $3, $4, $5, $7, $9, $2)))
-                      ABORT_PARSE;
-                  }
-                ;
-
-opt_attr_list   : // empty
-                  { $$ = 0; }
-                | '(' attr_list ')'
-                  { $$ = $2; }
-                ;
-
-attr_list       : attr
-                  { $$ = new tree_classdef_attribute_list ($1); }
-                | attr_list ',' attr
-                  {
-                    $1->append ($3);
-                    $$ = $1;
-                  }
-                ;
-
-attr            : identifier
-                  { $$ = new tree_classdef_attribute ($1); }
-                | identifier '=' decl_param_init expression
-                  {
-                    curr_lexer->looking_at_initializer_expression = false;
-                    $$ = new tree_classdef_attribute ($1, $4);
-                  }
-                | EXPR_NOT identifier
-                  { $$ = new tree_classdef_attribute ($2, false); }
-                ;
-
-opt_superclass_list
-                : // empty
-                  { $$ = 0; }
-                | superclass_list
-                  { $$ = $1; }
-                ;
-
-superclass_list : EXPR_LT superclass
-                  { $$ = new tree_classdef_superclass_list ($2); }
-                | superclass_list EXPR_AND superclass
-                  {
-                    $1->append ($3);
-                    $$ = $1;
-                  }
-                ;
-
-superclass      : identifier
-                  { $$ = new tree_classdef_superclass ($1); }
-                | identifier '.' identifier
-                  { $$ = new tree_classdef_superclass ($3, $1); }
-                ;
-
-class_body      : properties_block
-                  { $$ = new tree_classdef_body ($1); }
-                | methods_block
-                  { $$ = new tree_classdef_body ($1); }
-                | events_block
-                  { $$ = new tree_classdef_body ($1); }
-                | enum_block
-                  { $$ = new tree_classdef_body ($1); }
-                | class_body opt_sep properties_block
-                  {
-                    $1->append ($3);
-                    $$ = $1;
-                  }
-                | class_body opt_sep methods_block
-                  {
-                    $1->append ($3);
-                    $$ = $1;
-                  }
-                | class_body opt_sep events_block
-                  {
-                    $1->append ($3);
-                    $$ = $1;
-                  }
-                | class_body opt_sep enum_block
-                  {
-                    $1->append ($3);
-                    $$ = $1;
-                  }
-                ;
-
-properties_block
-                : PROPERTIES stash_comment opt_attr_list opt_sep property_list opt_sep END
-                  {
-                    if (! ($$ = curr_parser->make_classdef_properties_block
-                                               ($1, $3, $5, $7, $2)))
-                      ABORT_PARSE;
-                  }
-                ;
-
-property_list
-                : class_property
-                  { $$ = new tree_classdef_property_list ($1); }
-                | property_list opt_sep class_property
-                  {
-                    $1->append ($3);
-                    $$ = $1;
-                  }
-                ;
-
-class_property  : identifier
-                  { $$ = new tree_classdef_property ($1); }
-                | identifier '=' decl_param_init expression ';'
-                  {
-                    curr_lexer->looking_at_initializer_expression = false;
-                    $$ = new tree_classdef_property ($1, $4);
-                  }
-                ;
-
-methods_block   : METHODS stash_comment opt_attr_list opt_sep methods_list opt_sep END
-                  {
-                    if (! ($$ = curr_parser->make_classdef_methods_block
-                                               ($1, $3, $5, $7, $2)))
-                      ABORT_PARSE;
-                  }
-                ;
-
-methods_list    : function
-                  {
-                    octave_value fcn;
-                    if ($1)
-                      fcn = $1->function ();
-                    delete $1;
-                    $$ = new tree_classdef_methods_list (fcn);
-                  }
-                | methods_list opt_sep function
-                  {
-                    octave_value fcn;
-                    if ($3)
-                      fcn = $3->function ();
-                    delete $3;
-
-                    $1->append (fcn);
-                    $$ = $1;
-                  }
-                ;
-
-events_block    : EVENTS stash_comment opt_attr_list opt_sep events_list opt_sep END
-                  {
-                    if (! ($$ = curr_parser->make_classdef_events_block
-                                               ($1, $3, $5, $7, $2)))
-                      ABORT_PARSE;
-                  }
-                ;
-
-events_list     : class_event
-                  { $$ = new tree_classdef_events_list ($1); }
-                | events_list opt_sep class_event
-                  {
-                    $1->append ($3);
-                    $$ = $1;
-                  }
-                ;
-
-class_event     : identifier
-                  { $$ = new tree_classdef_event ($1); }
-                ;
-
-enum_block      : ENUMERATION stash_comment opt_attr_list opt_sep enum_list opt_sep END
-                  {
-                    if (! ($$ = curr_parser->make_classdef_enum_block
-                                               ($1, $3, $5, $7, $2)))
-                      ABORT_PARSE;
-                  }
-                ;
-
-enum_list       : class_enum
-                  { $$ = new tree_classdef_enum_list ($1); }
-                | enum_list opt_sep class_enum
-                  {
-                    $1->append ($3);
-                    $$ = $1;
-                  }
-                ;
-
-class_enum      : identifier '(' expression ')'
-                  { $$ = new tree_classdef_enum ($1, $3); }
-                ;
-
-// =============
-// Miscellaneous
-// =============
-
-stash_comment   : // empty
-                  { $$ = octave_comment_buffer::get_comment (); }
-                ;
-
-parse_error     : LEXICAL_ERROR
-                  { curr_parser->bison_error ("parse error"); }
-                | error
-                ;
-
-sep_no_nl       : ','
-                  { $$ = ','; }
-                | ';'
-                  { $$ = ';'; }
-                | sep_no_nl ','
-                  { $$ = $1; }
-                | sep_no_nl ';'
-                  { $$ = $1; }
-                ;
-
-opt_sep_no_nl   : // empty
-                  { $$ = 0; }
-                | sep_no_nl
-                  { $$ = $1; }
-                ;
-
-sep             : ','
-                  { $$ = ','; }
-                | ';'
-                  { $$ = ';'; }
-                | '\n'
-                  { $$ = '\n'; }
-                | sep ','
-                  { $$ = $1; }
-                | sep ';'
-                  { $$ = $1; }
-                | sep '\n'
-                  { $$ = $1; }
-                ;
-
-opt_sep         : // empty
-                  { $$ = 0; }
-                | sep
-                  { $$ = $1; }
-                ;
-
-opt_comma       : // empty
-                  { $$ = 0; }
-                | ','
-                  { $$ = ','; }
-                ;
-
-%%
-
-// Generic error messages.
-
-#undef curr_lexer
-
-static void
-yyerror (octave_parser *curr_parser, const char *s)
-{
-  curr_parser->bison_error (s);
-}
-
-int
-octave_parser::run (void)
-{
-  return octave_parse (this);
-}
-
-// Error mesages for mismatched end tokens.
-
-void
-octave_parser::end_error (const char *type, token::end_tok_type ettype,
-                          int l, int c)
-{
-  static const char *fmt
-    = "'%s' command matched by '%s' near line %d column %d";
-
-  switch (ettype)
-    {
-    case token::simple_end:
-      error (fmt, type, "end", l, c);
-      break;
-
-    case token::for_end:
-      error (fmt, type, "endfor", l, c);
-      break;
-
-    case token::function_end:
-      error (fmt, type, "endfunction", l, c);
-      break;
-
-    case token::classdef_end:
-      error (fmt, type, "endclassdef", l, c);
-      break;
-
-    case token::if_end:
-      error (fmt, type, "endif", l, c);
-      break;
-
-    case token::switch_end:
-      error (fmt, type, "endswitch", l, c);
-      break;
-
-    case token::while_end:
-      error (fmt, type, "endwhile", l, c);
-      break;
-
-    case token::try_catch_end:
-      error (fmt, type, "end_try_catch", l, c);
-      break;
-
-    case token::unwind_protect_end:
-      error (fmt, type, "end_unwind_protect", l, c);
-      break;
-
-    default:
-      panic_impossible ();
-      break;
-    }
-}
-
-// Check to see that end tokens are properly matched.
-
-bool
-octave_parser::end_token_ok (token *tok, token::end_tok_type expected)
-{
-  bool retval = true;
-
-  token::end_tok_type ettype = tok->ettype ();
-
-  if (ettype != expected && ettype != token::simple_end)
-    {
-      retval = false;
-
-      bison_error ("parse error");
-
-      int l = tok->line ();
-      int c = tok->column ();
-
-      switch (expected)
-        {
-        case token::classdef_end:
-          end_error ("classdef", ettype, l, c);
-          break;
-
-        case token::for_end:
-          end_error ("for", ettype, l, c);
-          break;
-
-        case token::enumeration_end:
-          end_error ("enumeration", ettype, l, c);
-          break;
-
-        case token::function_end:
-          end_error ("function", ettype, l, c);
-          break;
-
-        case token::if_end:
-          end_error ("if", ettype, l, c);
-          break;
-
-        case token::parfor_end:
-          end_error ("parfor", ettype, l, c);
-          break;
-
-        case token::try_catch_end:
-          end_error ("try", ettype, l, c);
-          break;
-
-        case token::switch_end:
-          end_error ("switch", ettype, l, c);
-          break;
-
-        case token::unwind_protect_end:
-          end_error ("unwind_protect", ettype, l, c);
-          break;
-
-        case token::while_end:
-          end_error ("while", ettype, l, c);
-          break;
-
-        default:
-          panic_impossible ();
-          break;
-        }
-    }
-
-  return retval;
-}
-
-// Maybe print a warning if an assignment expression is used as the
-// test in a logical expression.
-
-void
-octave_parser::maybe_warn_assign_as_truth_value (tree_expression *expr)
-{
-  if (expr->is_assignment_expression ()
-      && expr->paren_count () < 2)
-    {
-      if (curr_fcn_file_full_name.empty ())
-        warning_with_id
-          ("Octave:assign-as-truth-value",
-           "suggest parenthesis around assignment used as truth value");
-      else
-        warning_with_id
-          ("Octave:assign-as-truth-value",
-           "suggest parenthesis around assignment used as truth value near line %d, column %d in file '%s'",
-           expr->line (), expr->column (), curr_fcn_file_full_name.c_str ());
-    }
-}
-
-// Maybe print a warning about switch labels that aren't constants.
-
-void
-octave_parser::maybe_warn_variable_switch_label (tree_expression *expr)
-{
-  if (! expr->is_constant ())
-    {
-      if (curr_fcn_file_full_name.empty ())
-        warning_with_id ("Octave:variable-switch-label",
-                         "variable switch label");
-      else
-        warning_with_id
-          ("Octave:variable-switch-label",
-           "variable switch label near line %d, column %d in file '%s'",
-           expr->line (), expr->column (), curr_fcn_file_full_name.c_str ());
-    }
-}
-
-static tree_expression *
-fold (tree_binary_expression *e)
-{
-  tree_expression *retval = e;
-
-  unwind_protect frame;
-
-  frame.protect_var (error_state);
-  frame.protect_var (warning_state);
-
-  frame.protect_var (discard_error_messages);
-  frame.protect_var (discard_warning_messages);
-
-  discard_error_messages = true;
-  discard_warning_messages = true;
-
-  tree_expression *op1 = e->lhs ();
-  tree_expression *op2 = e->rhs ();
-
-  if (op1->is_constant () && op2->is_constant ())
-    {
-      octave_value tmp = e->rvalue1 ();
-
-      if (! (error_state || warning_state))
-        {
-          tree_constant *tc_retval
-            = new tree_constant (tmp, op1->line (), op1->column ());
-
-          std::ostringstream buf;
-
-          tree_print_code tpc (buf);
-
-          e->accept (tpc);
-
-          tc_retval->stash_original_text (buf.str ());
-
-          delete e;
-
-          retval = tc_retval;
-        }
-    }
-
-  return retval;
-}
-
-static tree_expression *
-fold (tree_unary_expression *e)
-{
-  tree_expression *retval = e;
-
-  unwind_protect frame;
-
-  frame.protect_var (error_state);
-  frame.protect_var (warning_state);
-
-  frame.protect_var (discard_error_messages);
-  frame.protect_var (discard_warning_messages);
-
-  discard_error_messages = true;
-  discard_warning_messages = true;
-
-  tree_expression *op = e->operand ();
-
-  if (op->is_constant ())
-    {
-      octave_value tmp = e->rvalue1 ();
-
-      if (! (error_state || warning_state))
-        {
-          tree_constant *tc_retval
-            = new tree_constant (tmp, op->line (), op->column ());
-
-          std::ostringstream buf;
-
-          tree_print_code tpc (buf);
-
-          e->accept (tpc);
-
-          tc_retval->stash_original_text (buf.str ());
-
-          delete e;
-
-          retval = tc_retval;
-        }
-    }
-
-  return retval;
-}
-
-// Finish building a range.
-
-tree_expression *
-octave_parser::finish_colon_expression (tree_colon_expression *e)
-{
-  tree_expression *retval = e;
-
-  unwind_protect frame;
-
-  frame.protect_var (error_state);
-  frame.protect_var (warning_state);
-
-  frame.protect_var (discard_error_messages);
-  frame.protect_var (discard_warning_messages);
-
-  discard_error_messages = true;
-  discard_warning_messages = true;
-
-  tree_expression *base = e->base ();
-  tree_expression *limit = e->limit ();
-  tree_expression *incr = e->increment ();
-
-  if (base)
-    {
-      if (limit)
-        {
-          if (base->is_constant () && limit->is_constant ()
-              && (! incr || (incr && incr->is_constant ())))
-            {
-              octave_value tmp = e->rvalue1 ();
-
-              if (! (error_state || warning_state))
-                {
-                  tree_constant *tc_retval
-                    = new tree_constant (tmp, base->line (), base->column ());
-
-                  std::ostringstream buf;
-
-                  tree_print_code tpc (buf);
-
-                  e->accept (tpc);
-
-                  tc_retval->stash_original_text (buf.str ());
-
-                  delete e;
-
-                  retval = tc_retval;
-                }
-            }
-        }
-      else
-        {
-          e->preserve_base ();
-          delete e;
-
-          // FIXME -- need to attempt constant folding here
-          // too (we need a generic way to do that).
-          retval = base;
-        }
-    }
-
-  return retval;
-}
-
-// Make a constant.
-
-tree_constant *
-octave_parser::make_constant (int op, token *tok_val)
-{
-  int l = tok_val->line ();
-  int c = tok_val->column ();
-
-  tree_constant *retval = 0;
-
-  switch (op)
-    {
-    case NUM:
-      {
-        octave_value tmp (tok_val->number ());
-        retval = new tree_constant (tmp, l, c);
-        retval->stash_original_text (tok_val->text_rep ());
-      }
-      break;
-
-    case IMAG_NUM:
-      {
-        octave_value tmp (Complex (0.0, tok_val->number ()));
-        retval = new tree_constant (tmp, l, c);
-        retval->stash_original_text (tok_val->text_rep ());
-      }
-      break;
-
-    case DQ_STRING:
-    case SQ_STRING:
-      {
-        std::string txt = tok_val->text ();
-
-        char delim = op == DQ_STRING ? '"' : '\'';
-        octave_value tmp (txt, delim);
-
-        if (txt.empty ())
-          {
-            if (op == DQ_STRING)
-              tmp = octave_null_str::instance;
-            else
-              tmp = octave_null_sq_str::instance;
-          }
-
-        retval = new tree_constant (tmp, l, c);
-
-        if (op == DQ_STRING)
-          txt = undo_string_escapes (txt);
-
-        // FIXME -- maybe this should also be handled by
-        // tok_val->text_rep () for character strings?
-        retval->stash_original_text (delim + txt + delim);
-      }
-      break;
-
-    default:
-      panic_impossible ();
-      break;
-    }
-
-  return retval;
-}
-
-// Make a function handle.
-
-tree_fcn_handle *
-octave_parser::make_fcn_handle (token *tok_val)
-{
-  int l = tok_val->line ();
-  int c = tok_val->column ();
-
-  tree_fcn_handle *retval = new tree_fcn_handle (tok_val->text (), l, c);
-
-  return retval;
-}
-
-// Make an anonymous function handle.
-
-tree_anon_fcn_handle *
-octave_parser::make_anon_fcn_handle (tree_parameter_list *param_list,
-                                     tree_statement *stmt)
-{
-  // FIXME -- need to get these from the location of the @ symbol.
-  int l = curr_lexer->input_line_number;
-  int c = curr_lexer->current_input_column;
-
-  tree_parameter_list *ret_list = 0;
-
-  symbol_table::scope_id fcn_scope = symbol_table::current_scope ();
-
-  if (parser_symtab_context.empty ())
-    panic_impossible ();
-
-  parser_symtab_context.pop ();
-
-  stmt->set_print_flag (false);
-
-  tree_statement_list *body = new tree_statement_list (stmt);
-
-  body->mark_as_anon_function_body ();
-
-  tree_anon_fcn_handle *retval
-    = new tree_anon_fcn_handle (param_list, ret_list, body, fcn_scope, l, c);
-  // FIXME: Stash the filename.  This does not work and produces
-  // errors when executed.
-  //retval->stash_file_name (curr_fcn_file_name);
-
-  return retval;
-}
-
-// Build a binary expression.
-
-tree_expression *
-octave_parser::make_binary_op (int op, tree_expression *op1, token *tok_val,
-                               tree_expression *op2)
-{
-  octave_value::binary_op t = octave_value::unknown_binary_op;
-
-  switch (op)
-    {
-    case POW:
-      t = octave_value::op_pow;
-      break;
-
-    case EPOW:
-      t = octave_value::op_el_pow;
-      break;
-
-    case '+':
-      t = octave_value::op_add;
-      break;
-
-    case '-':
-      t = octave_value::op_sub;
-      break;
-
-    case '*':
-      t = octave_value::op_mul;
-      break;
-
-    case '/':
-      t = octave_value::op_div;
-      break;
-
-    case EMUL:
-      t = octave_value::op_el_mul;
-      break;
-
-    case EDIV:
-      t = octave_value::op_el_div;
-      break;
-
-    case LEFTDIV:
-      t = octave_value::op_ldiv;
-      break;
-
-    case ELEFTDIV:
-      t = octave_value::op_el_ldiv;
-      break;
-
-    case LSHIFT:
-      t = octave_value::op_lshift;
-      break;
-
-    case RSHIFT:
-      t = octave_value::op_rshift;
-      break;
-
-    case EXPR_LT:
-      t = octave_value::op_lt;
-      break;
-
-    case EXPR_LE:
-      t = octave_value::op_le;
-      break;
-
-    case EXPR_EQ:
-      t = octave_value::op_eq;
-      break;
-
-    case EXPR_GE:
-      t = octave_value::op_ge;
-      break;
-
-    case EXPR_GT:
-      t = octave_value::op_gt;
-      break;
-
-    case EXPR_NE:
-      t = octave_value::op_ne;
-      break;
-
-    case EXPR_AND:
-      t = octave_value::op_el_and;
-      break;
-
-    case EXPR_OR:
-      t = octave_value::op_el_or;
-      break;
-
-    default:
-      panic_impossible ();
-      break;
-    }
-
-  int l = tok_val->line ();
-  int c = tok_val->column ();
-
-  tree_binary_expression *e
-    = maybe_compound_binary_expression (op1, op2, l, c, t);
-
-  return fold (e);
-}
-
-// Build a boolean expression.
-
-tree_expression *
-octave_parser::make_boolean_op (int op, tree_expression *op1, token *tok_val,
-                                tree_expression *op2)
-{
-  tree_boolean_expression::type t;
-
-  switch (op)
-    {
-    case EXPR_AND_AND:
-      t = tree_boolean_expression::bool_and;
-      break;
-
-    case EXPR_OR_OR:
-      t = tree_boolean_expression::bool_or;
-      break;
-
-    default:
-      panic_impossible ();
-      break;
-    }
-
-  int l = tok_val->line ();
-  int c = tok_val->column ();
-
-  tree_boolean_expression *e
-    = new tree_boolean_expression (op1, op2, l, c, t);
-
-  return fold (e);
-}
-
-// Build a prefix expression.
-
-tree_expression *
-octave_parser::make_prefix_op (int op, tree_expression *op1, token *tok_val)
-{
-  octave_value::unary_op t = octave_value::unknown_unary_op;
-
-  switch (op)
-    {
-    case EXPR_NOT:
-      t = octave_value::op_not;
-      break;
-
-    case '+':
-      t = octave_value::op_uplus;
-      break;
-
-    case '-':
-      t = octave_value::op_uminus;
-      break;
-
-    case PLUS_PLUS:
-      t = octave_value::op_incr;
-      break;
-
-    case MINUS_MINUS:
-      t = octave_value::op_decr;
-      break;
-
-    default:
-      panic_impossible ();
-      break;
-    }
-
-  int l = tok_val->line ();
-  int c = tok_val->column ();
-
-  tree_prefix_expression *e
-    = new tree_prefix_expression (op1, l, c, t);
-
-  return fold (e);
-}
-
-// Build a postfix expression.
-
-tree_expression *
-octave_parser::make_postfix_op (int op, tree_expression *op1, token *tok_val)
-{
-  octave_value::unary_op t = octave_value::unknown_unary_op;
-
-  switch (op)
-    {
-    case QUOTE:
-      t = octave_value::op_hermitian;
-      break;
-
-    case TRANSPOSE:
-      t = octave_value::op_transpose;
-      break;
-
-    case PLUS_PLUS:
-      t = octave_value::op_incr;
-      break;
-
-    case MINUS_MINUS:
-      t = octave_value::op_decr;
-      break;
-
-    default:
-      panic_impossible ();
-      break;
-    }
-
-  int l = tok_val->line ();
-  int c = tok_val->column ();
-
-  tree_postfix_expression *e
-    = new tree_postfix_expression (op1, l, c, t);
-
-  return fold (e);
-}
-
-// Build an unwind-protect command.
-
-tree_command *
-octave_parser::make_unwind_command (token *unwind_tok,
-                                    tree_statement_list *body,
-                                    tree_statement_list *cleanup_stmts,
-                                    token *end_tok,
-                                    octave_comment_list *lc,
-                                    octave_comment_list *mc)
-{
-  tree_command *retval = 0;
-
-  if (end_token_ok (end_tok, token::unwind_protect_end))
-    {
-      octave_comment_list *tc = octave_comment_buffer::get_comment ();
-
-      int l = unwind_tok->line ();
-      int c = unwind_tok->column ();
-
-      retval = new tree_unwind_protect_command (body, cleanup_stmts,
-                                                lc, mc, tc, l, c);
-    }
-
-  return retval;
-}
-
-// Build a try-catch command.
-
-tree_command *
-octave_parser::make_try_command (token *try_tok, tree_statement_list *body,
-                                 tree_statement_list *cleanup_stmts,
-                                 token *end_tok,
-                                 octave_comment_list *lc,
-                                 octave_comment_list *mc)
-{
-  tree_command *retval = 0;
-
-  if (end_token_ok (end_tok, token::try_catch_end))
-    {
-      octave_comment_list *tc = octave_comment_buffer::get_comment ();
-
-      int l = try_tok->line ();
-      int c = try_tok->column ();
-
-      retval = new tree_try_catch_command (body, cleanup_stmts,
-                                           lc, mc, tc, l, c);
-    }
-
-  return retval;
-}
-
-// Build a while command.
-
-tree_command *
-octave_parser::make_while_command (token *while_tok, tree_expression *expr,
-                                   tree_statement_list *body, token *end_tok,
-                                   octave_comment_list *lc)
-{
-  tree_command *retval = 0;
-
-  maybe_warn_assign_as_truth_value (expr);
-
-  if (end_token_ok (end_tok, token::while_end))
-    {
-      octave_comment_list *tc = octave_comment_buffer::get_comment ();
-
-      curr_lexer->looping--;
-
-      int l = while_tok->line ();
-      int c = while_tok->column ();
-
-      retval = new tree_while_command (expr, body, lc, tc, l, c);
-    }
-
-  return retval;
-}
-
-// Build a do-until command.
-
-tree_command *
-octave_parser::make_do_until_command (token *until_tok,
-                                      tree_statement_list *body,
-                                      tree_expression *expr,
-                                      octave_comment_list *lc)
-{
-  tree_command *retval = 0;
-
-  maybe_warn_assign_as_truth_value (expr);
-
-  octave_comment_list *tc = octave_comment_buffer::get_comment ();
-
-  curr_lexer->looping--;
-
-  int l = until_tok->line ();
-  int c = until_tok->column ();
-
-  retval = new tree_do_until_command (expr, body, lc, tc, l, c);
-
-  return retval;
-}
-
-// Build a for command.
-
-tree_command *
-octave_parser::make_for_command (int tok_id, token *for_tok,
-                                 tree_argument_list *lhs,
-                                 tree_expression *expr,
-                                 tree_expression *maxproc,
-                                 tree_statement_list *body, token *end_tok,
-                                 octave_comment_list *lc)
-{
-  tree_command *retval = 0;
-
-  bool parfor = tok_id == PARFOR;
-
-  if (end_token_ok (end_tok, parfor ? token::parfor_end : token::for_end))
-    {
-      octave_comment_list *tc = octave_comment_buffer::get_comment ();
-
-      curr_lexer->looping--;
-
-      int l = for_tok->line ();
-      int c = for_tok->column ();
-
-      if (lhs->length () == 1)
-        {
-          tree_expression *tmp = lhs->remove_front ();
-
-          retval = new tree_simple_for_command (parfor, tmp, expr, maxproc,
-                                                body, lc, tc, l, c);
-
-          delete lhs;
-        }
-      else
-        {
-          if (parfor)
-            bison_error ("invalid syntax for parfor statement");
-          else
-            retval = new tree_complex_for_command (lhs, expr, body,
-                                                   lc, tc, l, c);
-        }
-    }
-
-  return retval;
-}
-
-// Build a break command.
-
-tree_command *
-octave_parser::make_break_command (token *break_tok)
-{
-  tree_command *retval = 0;
-
-  int l = break_tok->line ();
-  int c = break_tok->column ();
-
-  retval = new tree_break_command (l, c);
-
-  return retval;
-}
-
-// Build a continue command.
-
-tree_command *
-octave_parser::make_continue_command (token *continue_tok)
-{
-  tree_command *retval = 0;
-
-  int l = continue_tok->line ();
-  int c = continue_tok->column ();
-
-  retval = new tree_continue_command (l, c);
-
-  return retval;
-}
-
-// Build a return command.
-
-tree_command *
-octave_parser::make_return_command (token *return_tok)
-{
-  tree_command *retval = 0;
-
-  int l = return_tok->line ();
-  int c = return_tok->column ();
-
-  retval = new tree_return_command (l, c);
-
-  return retval;
-}
-
-// Start an if command.
-
-tree_if_command_list *
-octave_parser::start_if_command (tree_expression *expr,
-                                 tree_statement_list *list)
-{
-  maybe_warn_assign_as_truth_value (expr);
-
-  tree_if_clause *t = new tree_if_clause (expr, list);
-
-  return new tree_if_command_list (t);
-}
-
-// Finish an if command.
-
-tree_if_command *
-octave_parser::finish_if_command (token *if_tok, tree_if_command_list *list,
-                                  token *end_tok, octave_comment_list *lc)
-{
-  tree_if_command *retval = 0;
-
-  if (end_token_ok (end_tok, token::if_end))
-    {
-      octave_comment_list *tc = octave_comment_buffer::get_comment ();
-
-      int l = if_tok->line ();
-      int c = if_tok->column ();
-
-      if (list && ! list->empty ())
-        {
-          tree_if_clause *elt = list->front ();
-
-          if (elt)
-            {
-              elt->line (l);
-              elt->column (c);
-            }
-        }
-
-      retval = new tree_if_command (list, lc, tc, l, c);
-    }
-
-  return retval;
-}
-
-// Build an elseif clause.
-
-tree_if_clause *
-octave_parser::make_elseif_clause (token *elseif_tok, tree_expression *expr,
-                                   tree_statement_list *list,
-                                   octave_comment_list *lc)
-{
-  maybe_warn_assign_as_truth_value (expr);
-
-  int l = elseif_tok->line ();
-  int c = elseif_tok->column ();
-
-  return new tree_if_clause (expr, list, lc, l, c);
-}
-
-// Finish a switch command.
-
-tree_switch_command *
-octave_parser::finish_switch_command (token *switch_tok, tree_expression *expr,
-                                      tree_switch_case_list *list,
-                                      token *end_tok, octave_comment_list *lc)
-{
-  tree_switch_command *retval = 0;
-
-  if (end_token_ok (end_tok, token::switch_end))
-    {
-      octave_comment_list *tc = octave_comment_buffer::get_comment ();
-
-      int l = switch_tok->line ();
-      int c = switch_tok->column ();
-
-      if (list && ! list->empty ())
-        {
-          tree_switch_case *elt = list->front ();
-
-          if (elt)
-            {
-              elt->line (l);
-              elt->column (c);
-            }
-        }
-
-      retval = new tree_switch_command (expr, list, lc, tc, l, c);
-    }
-
-  return retval;
-}
-
-// Build a switch case.
-
-tree_switch_case *
-octave_parser::make_switch_case (token *case_tok, tree_expression *expr,
-                                 tree_statement_list *list,
-                                 octave_comment_list *lc)
-{
-  maybe_warn_variable_switch_label (expr);
-
-  int l = case_tok->line ();
-  int c = case_tok->column ();
-
-  return new tree_switch_case (expr, list, lc, l, c);
-}
-
-// Build an assignment to a variable.
-
-tree_expression *
-octave_parser::make_assign_op (int op, tree_argument_list *lhs, token *eq_tok,
-                               tree_expression *rhs)
-{
-  tree_expression *retval = 0;
-
-  octave_value::assign_op t = octave_value::unknown_assign_op;
-
-  switch (op)
-    {
-    case '=':
-      t = octave_value::op_asn_eq;
-      break;
-
-    case ADD_EQ:
-      t = octave_value::op_add_eq;
-      break;
-
-    case SUB_EQ:
-      t = octave_value::op_sub_eq;
-      break;
-
-    case MUL_EQ:
-      t = octave_value::op_mul_eq;
-      break;
-
-    case DIV_EQ:
-      t = octave_value::op_div_eq;
-      break;
-
-    case LEFTDIV_EQ:
-      t = octave_value::op_ldiv_eq;
-      break;
-
-    case POW_EQ:
-      t = octave_value::op_pow_eq;
-      break;
-
-    case LSHIFT_EQ:
-      t = octave_value::op_lshift_eq;
-      break;
-
-    case RSHIFT_EQ:
-      t = octave_value::op_rshift_eq;
-      break;
-
-    case EMUL_EQ:
-      t = octave_value::op_el_mul_eq;
-      break;
-
-    case EDIV_EQ:
-      t = octave_value::op_el_div_eq;
-      break;
-
-    case ELEFTDIV_EQ:
-      t = octave_value::op_el_ldiv_eq;
-      break;
-
-    case EPOW_EQ:
-      t = octave_value::op_el_pow_eq;
-      break;
-
-    case AND_EQ:
-      t = octave_value::op_el_and_eq;
-      break;
-
-    case OR_EQ:
-      t = octave_value::op_el_or_eq;
-      break;
-
-    default:
-      panic_impossible ();
-      break;
-    }
-
-  int l = eq_tok->line ();
-  int c = eq_tok->column ();
-
-  if (lhs->is_simple_assign_lhs ())
-    {
-      tree_expression *tmp = lhs->remove_front ();
-
-      retval = new tree_simple_assignment (tmp, rhs, false, l, c, t);
-
-      delete lhs;
-    }
-  else if (t == octave_value::op_asn_eq)
-    return new tree_multi_assignment (lhs, rhs, false, l, c);
-  else
-    bison_error ("computed multiple assignment not allowed");
-
-  return retval;
-}
-
-// Define a script.
-
-void
-octave_parser::make_script (tree_statement_list *cmds,
-                            tree_statement *end_script)
-{
-  std::string doc_string;
-
-  if (! help_buf.empty ())
-    {
-      doc_string = help_buf.top ();
-      help_buf.pop ();
-    }
-
-  if (! cmds)
-    cmds = new tree_statement_list ();
-
-  cmds->append (end_script);
-
-  octave_user_script *script
-    = new octave_user_script (curr_fcn_file_full_name, curr_fcn_file_name,
-                              cmds, doc_string);
-
-  octave_time now;
-
-  script->stash_fcn_file_time (now);
-
-  primary_fcn_ptr = script;
-
-  // Unmark any symbols that may have been tagged as local variables
-  // while parsing (for example, by force_local_variable in lex.l).
-
-  symbol_table::unmark_forced_variables ();
-}
-
-// Begin defining a function.
-
-octave_user_function *
-octave_parser::start_function (tree_parameter_list *param_list,
-                               tree_statement_list *body,
-                               tree_statement *end_fcn_stmt)
-{
-  // We'll fill in the return list later.
-
-  if (! body)
-    body = new tree_statement_list ();
-
-  body->append (end_fcn_stmt);
-
-  octave_user_function *fcn
-    = new octave_user_function (symbol_table::current_scope (),
-                                param_list, 0, body);
-
-  if (fcn)
-    {
-      octave_comment_list *tc = octave_comment_buffer::get_comment ();
-
-      fcn->stash_trailing_comment (tc);
-    }
-
-  return fcn;
-}
-
-tree_statement *
-octave_parser::make_end (const std::string& type, int l, int c)
-{
-  return make_statement (new tree_no_op_command (type, l, c));
-}
-
-// Do most of the work for defining a function.
-
-octave_user_function *
-octave_parser::frob_function (const std::string& fname,
-                              octave_user_function *fcn)
-{
-  std::string id_name = fname;
-
-  // If input is coming from a file, issue a warning if the name of
-  // the file does not match the name of the function stated in the
-  // file.  Matlab doesn't provide a diagnostic (it ignores the stated
-  // name).
-  if (! autoloading && reading_fcn_file
-      && curr_fcn_depth == 1 && ! parsing_subfunctions)
-  {
-    // FIXME -- should curr_fcn_file_name already be
-    // preprocessed when we get here?  It seems to only be a
-    // problem with relative file names.
-
-    std::string nm = curr_fcn_file_name;
-
-    size_t pos = nm.find_last_of (file_ops::dir_sep_chars ());
-
-    if (pos != std::string::npos)
-      nm = curr_fcn_file_name.substr (pos+1);
-
-    if (nm != id_name)
-      {
-        warning_with_id
-          ("Octave:function-name-clash",
-           "function name '%s' does not agree with function file name '%s'",
-           id_name.c_str (), curr_fcn_file_full_name.c_str ());
-
-        id_name = nm;
-      }
-  }
-
-  if (reading_fcn_file || reading_classdef_file || autoloading)
-    {
-      octave_time now;
-
-      fcn->stash_fcn_file_name (curr_fcn_file_full_name);
-      fcn->stash_fcn_file_time (now);
-      fcn->mark_as_system_fcn_file ();
-
-      if (fcn_file_from_relative_lookup)
-        fcn->mark_relative ();
-
-      if (curr_fcn_depth > 1 || parsing_subfunctions)
-        {
-          fcn->stash_parent_fcn_name (curr_fcn_file_name);
-
-          if (curr_fcn_depth > 1)
-            fcn->stash_parent_fcn_scope (function_scopes[function_scopes.size ()-2]);
-          else
-            fcn->stash_parent_fcn_scope (primary_fcn_scope);
-        }
-
-      if (curr_lexer->parsing_class_method)
-        {
-          if (curr_class_name == id_name)
-            fcn->mark_as_class_constructor ();
-          else
-            fcn->mark_as_class_method ();
-
-          fcn->stash_dispatch_class (curr_class_name);
-        }
-
-      std::string nm = fcn->fcn_file_name ();
-
-      file_stat fs (nm);
-
-      if (fs && fs.is_newer (now))
-        warning_with_id ("Octave:future-time-stamp",
-                         "time stamp for '%s' is in the future", nm.c_str ());
-    }
-  else if (! (input_from_tmp_history_file || input_from_startup_file)
-           && reading_script_file
-           && curr_fcn_file_name == id_name)
-    {
-      warning ("function '%s' defined within script file '%s'",
-               id_name.c_str (), curr_fcn_file_full_name.c_str ());
-    }
-
-  fcn->stash_function_name (id_name);
-  fcn->stash_fcn_location (curr_lexer->input_line_number,
-                           curr_lexer->current_input_column);
-
-  if (! help_buf.empty () && curr_fcn_depth == 1
-      && ! parsing_subfunctions)
-    {
-      fcn->document (help_buf.top ());
-
-      help_buf.pop ();
-    }
-
-  if (reading_fcn_file && curr_fcn_depth == 1
-      && ! parsing_subfunctions)
-    primary_fcn_ptr = fcn;
-
-  return fcn;
-}
-
-tree_function_def *
-octave_parser::finish_function (tree_parameter_list *ret_list,
-                                octave_user_function *fcn,
-                                octave_comment_list *lc)
-{
-  tree_function_def *retval = 0;
-
-  if (ret_list)
-    ret_list->mark_as_formal_parameters ();
-
-  if (fcn)
-    {
-      std::string nm = fcn->name ();
-      std::string file = fcn->fcn_file_name ();
-
-      std::string tmp = nm;
-      if (! file.empty ())
-        tmp += ": " + file;
-
-      symbol_table::cache_name (fcn->scope (), tmp);
-
-      if (lc)
-        fcn->stash_leading_comment (lc);
-
-      fcn->define_ret_list (ret_list);
-
-      if (curr_fcn_depth > 1 || parsing_subfunctions)
-        {
-          fcn->mark_as_subfunction ();
-
-          if (endfunction_found && function_scopes.size () > 1)
-            {
-              symbol_table::scope_id pscope
-                = function_scopes[function_scopes.size ()-2];
-
-              symbol_table::install_nestfunction (nm, octave_value (fcn),
-                                                  pscope);
-            }
-          else
-            symbol_table::install_subfunction (nm, octave_value (fcn),
-                                               primary_fcn_scope);
-        }
-
-      if (curr_fcn_depth == 1 && fcn)
-        symbol_table::update_nest (fcn->scope ());
-
-      if (! reading_fcn_file && curr_fcn_depth == 1)
-        {
-          // We are either reading a script file or defining a function
-          // at the command line, so this definition creates a
-          // tree_function object that is placed in the parse tree.
-          // Otherwise, it is just inserted in the symbol table,
-          // either as a subfunction or nested function (see above),
-          // or as the primary function for the file, via
-          // primary_fcn_ptr (see also load_fcn_from_file,,
-          // parse_fcn_file, and
-          // symbol_table::fcn_info::fcn_info_rep::find_user_function).
-
-          retval = new tree_function_def (fcn);
-        }
-
-      // Unmark any symbols that may have been tagged as local
-      // variables while parsing (for example, by force_local_variable
-      // in lex.l).
-
-      symbol_table::unmark_forced_variables (fcn->scope ());
-    }
-
-  return retval;
-}
-
-void
-octave_parser::recover_from_parsing_function (void)
-{
-  if (parser_symtab_context.empty ())
-    panic_impossible ();
-
-  parser_symtab_context.pop ();
-
-  if (reading_fcn_file && curr_fcn_depth == 1
-      && ! parsing_subfunctions)
-    parsing_subfunctions = true;
-
-  curr_fcn_depth--;
-  function_scopes.pop_back ();
-
-  curr_lexer->defining_func--;
-  curr_lexer->parsed_function_name.pop ();
-  curr_lexer->looking_at_return_list = false;
-  curr_lexer->looking_at_parameter_list = false;
-}
-
-tree_funcall *
-octave_parser::make_superclass_ref (const std::string& method_nm,
-                                    const std::string& package_nm,
-                                    const std::string& class_nm,
-                                    int l, int c)
-{
-  octave_value_list args;
-
-  args(2) = class_nm;
-  args(1) = package_nm;
-  args(0) = method_nm;
-
-  octave_value fcn
-    = symbol_table::find_built_in_function ("__superclass_reference__");
-
-  return new tree_funcall (fcn, args);
-}
-
-tree_funcall *
-octave_parser::make_meta_class_query (const std::string& package_nm,
-                                      const std::string& class_nm,
-                                      int l, int c)
-{
-  octave_value_list args;
-
-  args(1) = class_nm;
-  args(0) = package_nm;
-
-  octave_value fcn
-    = symbol_table::find_built_in_function ("__meta_class_query__");
-
-  return new tree_funcall (fcn, args);
-}
-
-// A CLASSDEF block defines a class that has a constructor and other
-// methods, but it is not an executable command.  Parsing the block
-// makes some changes in the symbol table (inserting the constructor
-// and methods, and adding to the list of known objects) and creates
-// a parse tree containing meta information about the class.
-
-tree_classdef *
-octave_parser::make_classdef (token *tok_val,
-                              tree_classdef_attribute_list *a,
-                              tree_identifier *id,
-                              tree_classdef_superclass_list *sc,
-                              tree_classdef_body *body, token *end_tok,
-                              octave_comment_list *lc)
-{
-  tree_classdef *retval = 0;
-
-  std::string cls_name = id->name ();
-
-  std::string nm = curr_fcn_file_name;
-
-  size_t pos = nm.find_last_of (file_ops::dir_sep_chars ());
-
-  if (pos != std::string::npos)
-    nm = curr_fcn_file_name.substr (pos+1);
-
-  if (nm != cls_name)
-    {
-      bison_error ("invalid classdef definition, the class name must match the file name");
-      return retval;
-    }
-
-  if (end_token_ok (end_tok, token::classdef_end))
-    {
-      octave_comment_list *tc = octave_comment_buffer::get_comment ();
-
-      int l = tok_val->line ();
-      int c = tok_val->column ();
-
-      retval = new tree_classdef (a, id, sc, body, lc, tc, l, c);
-    }
-
-  return retval;
-}
-
-tree_classdef_properties_block *
-octave_parser::make_classdef_properties_block (token *tok_val,
-                                               tree_classdef_attribute_list *a,
-                                               tree_classdef_property_list *plist,
-                                               token *end_tok,
-                                               octave_comment_list *lc)
-{
-  tree_classdef_properties_block *retval = 0;
-
-  if (end_token_ok (end_tok, token::properties_end))
-    {
-      octave_comment_list *tc = octave_comment_buffer::get_comment ();
-
-      int l = tok_val->line ();
-      int c = tok_val->column ();
-
-      retval = new tree_classdef_properties_block (a, plist, lc, tc, l, c);
-    }
-
-  return retval;
-}
-
-tree_classdef_methods_block *
-octave_parser::make_classdef_methods_block (token *tok_val,
-                                            tree_classdef_attribute_list *a,
-                                            tree_classdef_methods_list *mlist,
-                                            token *end_tok,
-                                            octave_comment_list *lc)
-{
-  tree_classdef_methods_block *retval = 0;
-
-  if (end_token_ok (end_tok, token::methods_end))
-    {
-      octave_comment_list *tc = octave_comment_buffer::get_comment ();
-
-      int l = tok_val->line ();
-      int c = tok_val->column ();
-
-      retval = new tree_classdef_methods_block (a, mlist, lc, tc, l, c);
-    }
-
-  return retval;
-}
-
-tree_classdef_events_block *
-octave_parser::make_classdef_events_block (token *tok_val,
-                                           tree_classdef_attribute_list *a,
-                                           tree_classdef_events_list *elist,
-                                           token *end_tok,
-                                           octave_comment_list *lc)
-{
-  tree_classdef_events_block *retval = 0;
-
-  if (end_token_ok (end_tok, token::events_end))
-    {
-      octave_comment_list *tc = octave_comment_buffer::get_comment ();
-
-      int l = tok_val->line ();
-      int c = tok_val->column ();
-
-      retval = new tree_classdef_events_block (a, elist, lc, tc, l, c);
-    }
-
-  return retval;
-}
-
-tree_classdef_enum_block *
-octave_parser::make_classdef_enum_block (token *tok_val,
-                                         tree_classdef_attribute_list *a,
-                                         tree_classdef_enum_list *elist,
-                                         token *end_tok,
-                                         octave_comment_list *lc)
-{
-  tree_classdef_enum_block *retval = 0;
-
-  if (end_token_ok (end_tok, token::enumeration_end))
-    {
-      octave_comment_list *tc = octave_comment_buffer::get_comment ();
-
-      int l = tok_val->line ();
-      int c = tok_val->column ();
-
-      retval = new tree_classdef_enum_block (a, elist, lc, tc, l, c);
-    }
-
-  return retval;
-}
-
-// Make an index expression.
-
-tree_index_expression *
-octave_parser::make_index_expression (tree_expression *expr,
-                                      tree_argument_list *args, char type)
-{
-  tree_index_expression *retval = 0;
-
-  if (args && args->has_magic_tilde ())
-    {
-      bison_error ("invalid use of empty argument (~) in index expression");
-      return retval;
-    }
-
-  int l = expr->line ();
-  int c = expr->column ();
-
-  if (! expr->is_postfix_indexed ()) 
-    expr->set_postfix_index (type);
-
-  if (expr->is_index_expression ())
-    {
-      tree_index_expression *tmp = static_cast<tree_index_expression *> (expr);
-
-      tmp->append (args, type);
-
-      retval = tmp;
-    }
-  else
-    retval = new tree_index_expression (expr, args, l, c, type);
-
-  return retval;
-}
-
-// Make an indirect reference expression.
-
-tree_index_expression *
-octave_parser::make_indirect_ref (tree_expression *expr,
-                                  const std::string& elt)
-{
-  tree_index_expression *retval = 0;
-
-  int l = expr->line ();
-  int c = expr->column ();
-
-  if (! expr->is_postfix_indexed ()) 
-    expr->set_postfix_index ('.');
-
-  if (expr->is_index_expression ())
-    {
-      tree_index_expression *tmp = static_cast<tree_index_expression *> (expr);
-
-      tmp->append (elt);
-
-      retval = tmp;
-    }
-  else
-    retval = new tree_index_expression (expr, elt, l, c);
-
-  curr_lexer->looking_at_indirect_ref = false;
-
-  return retval;
-}
-
-// Make an indirect reference expression with dynamic field name.
-
-tree_index_expression *
-octave_parser::make_indirect_ref (tree_expression *expr, tree_expression *elt)
-{
-  tree_index_expression *retval = 0;
-
-  int l = expr->line ();
-  int c = expr->column ();
-
-  if (! expr->is_postfix_indexed ()) 
-    expr->set_postfix_index ('.');
-
-  if (expr->is_index_expression ())
-    {
-      tree_index_expression *tmp = static_cast<tree_index_expression *> (expr);
-
-      tmp->append (elt);
-
-      retval = tmp;
-    }
-  else
-    retval = new tree_index_expression (expr, elt, l, c);
-
-  curr_lexer->looking_at_indirect_ref = false;
-
-  return retval;
-}
-
-// Make a declaration command.
-
-tree_decl_command *
-octave_parser::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 PERSISTENT:
-      if (curr_fcn_depth > 0)
-        retval = new tree_persistent_command (lst, l, c);
-      else
-        {
-          if (reading_script_file)
-            warning ("ignoring persistent declaration near line %d of file '%s'",
-                     l, curr_fcn_file_full_name.c_str ());
-          else
-            warning ("ignoring persistent declaration near line %d", l);
-        }
-      break;
-
-    default:
-      panic_impossible ();
-      break;
-    }
-
-  return retval;
-}
-
-tree_argument_list *
-octave_parser::validate_matrix_row (tree_argument_list *row)
-{
-  if (row && row->has_magic_tilde ())
-    bison_error ("invalid use of tilde (~) in matrix expression");
-  return row;
-}
-
-// Finish building a matrix list.
-
-tree_expression *
-octave_parser::finish_matrix (tree_matrix *m)
-{
-  tree_expression *retval = m;
-
-  unwind_protect frame;
-
-  frame.protect_var (error_state);
-  frame.protect_var (warning_state);
-
-  frame.protect_var (discard_error_messages);
-  frame.protect_var (discard_warning_messages);
-
-  discard_error_messages = true;
-  discard_warning_messages = true;
-
-  if (m->all_elements_are_constant ())
-    {
-      octave_value tmp = m->rvalue1 ();
-
-      if (! (error_state || warning_state))
-        {
-          tree_constant *tc_retval
-            = new tree_constant (tmp, m->line (), m->column ());
-
-          std::ostringstream buf;
-
-          tree_print_code tpc (buf);
-
-          m->accept (tpc);
-
-          tc_retval->stash_original_text (buf.str ());
-
-          delete m;
-
-          retval = tc_retval;
-        }
-    }
-
-  return retval;
-}
-
-// Finish building a cell list.
-
-tree_expression *
-octave_parser::finish_cell (tree_cell *c)
-{
-  return finish_matrix (c);
-}
-
-void
-octave_parser::maybe_warn_missing_semi (tree_statement_list *t)
-{
-  if (curr_fcn_depth > 0)
-    {
-      tree_statement *tmp = t->back ();
-
-      if (tmp->is_expression ())
-        warning_with_id
-          ("Octave:missing-semicolon",
-           "missing semicolon near line %d, column %d in file '%s'",
-            tmp->line (), tmp->column (), curr_fcn_file_full_name.c_str ());
-    }
-}
-
-tree_statement_list *
-octave_parser::set_stmt_print_flag (tree_statement_list *list, char sep,
-                                    bool warn_missing_semi)
-{
-  tree_statement *tmp = list->back ();
-
-  switch (sep)
-    {
-    case ';':
-      tmp->set_print_flag (false);
-      break;
-
-    case 0:
-    case ',':
-    case '\n':
-      tmp->set_print_flag (true);
-      if (warn_missing_semi)
-        maybe_warn_missing_semi (list);
-      break;
-
-    default:
-      warning ("unrecognized separator type!");
-      break;
-    }
-
-  // Even if a statement is null, we add it to the list then remove it
-  // here so that the print flag is applied to the correct statement.
-
-  if (tmp->is_null_statement ())
-    {
-      list->pop_back ();
-      delete tmp;
-    }
-
-  return list;
-}
-
-tree_statement_list *
-octave_parser::make_statement_list (tree_statement *stmt)
-{
-  return new tree_statement_list (stmt);
-}
-
-tree_statement_list *
-octave_parser::append_statement_list (tree_statement_list *list, char sep,
-                                      tree_statement *stmt,
-                                      bool warn_missing_semi)
-{
-  set_stmt_print_flag (list, sep, warn_missing_semi);
-
-  list->append (stmt);
-
-  return list;
-}
-
-void
-octave_parser::bison_error (const char *s)
-
-{
-  int err_col = curr_lexer->current_input_column - 1;
-
-  std::ostringstream output_buf;
-
-  if (reading_fcn_file || reading_script_file || reading_classdef_file)
-    output_buf << "parse error near line " << curr_lexer->input_line_number
-               << " of file " << curr_fcn_file_full_name;
-  else
-    output_buf << "parse error:";
-
-  if (s && strcmp (s, "parse error") != 0)
-    output_buf << "\n\n  " << s;
-
-  output_buf << "\n\n";
-
-  if (! current_input_line.empty ())
-    {
-      size_t len = current_input_line.length ();
-
-      if (current_input_line[len-1] == '\n')
-        current_input_line.resize (len-1);
-
-      // Print the line, maybe with a pointer near the error token.
-
-      output_buf << ">>> " << current_input_line << "\n";
-
-      if (err_col == 0)
-        err_col = len;
-
-      for (int i = 0; i < err_col + 3; i++)
-        output_buf << " ";
-
-      output_buf << "^";
-    }
-
-  output_buf << "\n";
-
-  std::string msg = output_buf.str ();
-
-  parse_error ("%s", msg.c_str ());
-}
-
-static void
-safe_fclose (FILE *f)
-{
-  // FIXME -- comments at the end of an input file are
-  // discarded (otherwise, they would be appended to the next
-  // statement, possibly from the command line or another file, which
-  // can be quite confusing).
-
-  octave_comment_list *tc = octave_comment_buffer::get_comment ();
-
-  delete tc;
-
-  if (f)
-    fclose (static_cast<FILE *> (f));
-}
-
-static bool
-looks_like_copyright (const std::string& s)
-{
-  bool retval = false;
-
-  if (! s.empty ())
-    {
-      size_t offset = s.find_first_not_of (" \t");
-
-      retval = (s.substr (offset, 9) == "Copyright" || s.substr (offset, 6) == "Author");
-    }
-
-  return retval;
-}
-
-static int
-text_getc (FILE *f)
-{
-  int c = gnulib::getc (f);
-
-  // Convert CRLF into just LF and single CR into LF.
-
-  if (c == '\r')
-    {
-      c = gnulib::getc (f);
-
-      if (c != '\n')
-        {
-          ungetc (c, f);
-          c = '\n';
-        }
-    }
-
-  return c;
-}
-
-class
-stdio_stream_reader : public stream_reader
-{
-public:
-
-  stdio_stream_reader (FILE *f_arg, int& l, int& c)
-    : stream_reader (), f (f_arg), line_num (l), column_num (c)
-  { }
-
-  int getc (void)
-  {
-    char c = ::text_getc (f);
-
-    if (c == '\n')
-      {
-        line_num++;
-        column_num = 0;
-      }
-    else
-      {
-        // FIXME -- try to be smarter about tabs?
-        column_num++;
-      }
-        
-    return c;
-  }
-
-  int ungetc (int c)
-  {
-    if (c == '\n')
-      {   
-        line_num--;
-        column_num = 0;
-      }
-    else
-      {
-        // FIXME -- try to be smarter about tabs?
-        column_num--;
-      }
-
-    return ::ungetc (c, f);
-  }
-
-private:
-
-  FILE *f;
-
-  int& line_num;
-
-  int& column_num;
-
-  // No copying!
-
-  stdio_stream_reader (const  stdio_stream_reader&);
-
-  stdio_stream_reader & operator = (const  stdio_stream_reader&);
-};
-
-static bool
-skip_white_space (stream_reader& reader)
-{
-  int c = 0;
-
-  while ((c = reader.getc ()) != EOF)
-    {
-      switch (c)
-        {
-        case ' ':
-        case '\t':
-        case '\n':
-          break;
-
-        default:
-          reader.ungetc (c);
-          goto done;
-        }
-    }
-
- done:
-
-  return (c == EOF);
-}
-
-static bool
-looking_at_classdef_keyword (FILE *ffile)
-{
-  bool status = false;
-
-  long pos = gnulib::ftell (ffile);
-
-  char buf [10];
-  gnulib::fgets (buf, 10, ffile);
-  size_t len = strlen (buf);
-  if (len > 8 && strncmp (buf, "classdef", 8) == 0
-      && ! (isalnum (buf[8]) || buf[8] == '_'))
-    status = true;
-
-  gnulib::fseek (ffile, pos, SEEK_SET);
-
-  return status;
- }
-
-static std::string
-gobble_leading_white_space (FILE *ffile, bool& eof, int& line_num,
-                            int& column_num)
-{
-  std::string help_txt;
-
-  eof = false;
-
-  // TRUE means we have already cached the help text.
-  bool have_help_text = false;
-
-  std::string txt;
-
-  stdio_stream_reader stdio_reader (ffile, line_num, column_num);
-
-  while (true)
-    {
-      eof = skip_white_space (stdio_reader);
-
-      if (eof)
-        break;
-
-      txt = CURR_LEXER->grab_comment_block (stdio_reader, true, eof);
-
-      if (txt.empty ())
-        break;
-
-      if (! (have_help_text || looks_like_copyright (txt)))
-        {
-          help_txt = txt;
-          have_help_text = true;
-        }
-
-      octave_comment_buffer::append (txt);
-
-      if (eof)
-        break;
-    }
-
-  return help_txt;
-}
-
-static std::string
-gobble_leading_white_space (FILE *ffile, bool& eof)
-{
-  int line_num = 1;
-  int column_num = 1;
-
-  return gobble_leading_white_space (ffile, eof, line_num, column_num);
-}
-
-static bool
-looking_at_function_keyword (FILE *ffile)
-{
-  bool status = false;
-
-  long pos = gnulib::ftell (ffile);
-
-  char buf [10];
-  gnulib::fgets (buf, 10, ffile);
-  size_t len = strlen (buf);
-  if (len > 8 && strncmp (buf, "function", 8) == 0
-      && ! (isalnum (buf[8]) || buf[8] == '_'))
-    status = true;
-
-  gnulib::fseek (ffile, pos, SEEK_SET);
-
-  return status;
-}
-
-static octave_function *
-parse_fcn_file (const std::string& ff, const std::string& dispatch_type,
-                bool require_file, bool force_script, bool autoload,    
-                bool relative_lookup, const std::string& warn_for)
-{
-  unwind_protect frame;
-
-  octave_function *fcn_ptr = 0;
-
-  // Open function file and parse.
-
-  FILE *in_stream = command_editor::get_input_stream ();
-
-  frame.add_fcn (command_editor::set_input_stream, in_stream);
-
-  frame.protect_var (ff_instream);
-
-  frame.protect_var (reading_fcn_file);
-  frame.protect_var (line_editing);
-
-  reading_fcn_file = true;
-  line_editing = false;
-
-  frame.add_fcn (command_history::ignore_entries,
-                 command_history::ignoring_entries ());
-
-  command_history::ignore_entries ();
-
-  FILE *ffile = get_input_from_file (ff, 0);
-
-  frame.add_fcn (safe_fclose, ffile);
-
-  if (ffile)
-    {
-      bool eof;
-
-      // octave_parser constructor sets this for us.
-      frame.protect_var (CURR_LEXER);
-
-      octave_parser *curr_parser = new octave_parser ();
-      frame.add_fcn (octave_parser::cleanup, curr_parser);
-
-      curr_parser->curr_class_name = dispatch_type;
-      curr_parser->autoloading = autoload;
-      curr_parser->fcn_file_from_relative_lookup = relative_lookup;
-
-      std::string help_txt
-        = gobble_leading_white_space
-            (ffile, eof,
-             curr_parser->curr_lexer->input_line_number,
-             curr_parser->curr_lexer->current_input_column);
-
-      if (! help_txt.empty ())
-        help_buf.push (help_txt);
-
-      if (! eof)
-        {
-          std::string file_type;
-
-          frame.protect_var (get_input_from_eval_string);
-          frame.protect_var (reading_fcn_file);
-          frame.protect_var (reading_script_file);
-          frame.protect_var (reading_classdef_file);
-          frame.protect_var (Vecho_executing_commands);
-
-          get_input_from_eval_string = false;
-
-          if (! force_script && looking_at_function_keyword (ffile))
-            {
-              file_type = "function";
-
-              Vecho_executing_commands = ECHO_OFF;
-
-              reading_classdef_file = false;
-              reading_fcn_file = true;
-              reading_script_file = false;
-            }
-          else if (! force_script && looking_at_classdef_keyword (ffile))
-            {
-              file_type = "classdef";
-
-              Vecho_executing_commands = ECHO_OFF;
-
-              reading_classdef_file = true;
-              reading_fcn_file = false;
-              reading_script_file = false;
-            }
-          else
-            {
-              file_type = "script";
-
-              Vecho_executing_commands = ECHO_OFF;
-
-              reading_classdef_file = false;
-              reading_fcn_file = false;
-              reading_script_file = true;
-            }
-
-          // Do this with an unwind-protect cleanup function so that
-          // the forced variables will be unmarked in the event of an
-          // interrupt.
-          symbol_table::scope_id scope = symbol_table::top_scope ();
-          frame.add_fcn (symbol_table::unmark_forced_variables, scope);
-
-          if (! help_txt.empty ())
-            help_buf.push (help_txt);
-
-          if (reading_script_file)
-            curr_parser->curr_lexer->prep_for_script_file ();
-          else if (reading_classdef_file)
-            curr_parser->curr_lexer->prep_for_classdef_file ();
-          else
-            curr_parser->curr_lexer->prep_for_function_file ();
-
-          curr_parser->curr_lexer->parsing_class_method = ! dispatch_type.empty ();
-
-          frame.protect_var (global_command);
-
-          global_command = 0;
-
-          int status = curr_parser->run ();
-
-          // Use an unwind-protect cleanup function so that the
-          // global_command list will be deleted in the event of an
-          // interrupt.
-
-          frame.add_fcn (cleanup_statement_list, &global_command);
-
-          fcn_ptr = curr_parser->primary_fcn_ptr;
-
-          if (status == 0)
-            {
-              if (reading_classdef_file && curr_parser->classdef_object)
-                {
-                  // Convert parse tree for classdef object to
-                  // meta.class info (and stash it in the symbol
-                  // table?).  Return pointer to constructor?
-
-                  if (fcn_ptr)
-                    panic_impossible ();
-
-                  fcn_ptr = curr_parser->classdef_object->make_meta_class ();
-                }
-            }
-          else
-            {
-              error ("parse error while reading %s file %s",
-                     file_type.c_str(), ff.c_str ());
-            }
-        }
-      else
-        {
-          int l = curr_parser->curr_lexer->input_line_number;
-          int c = curr_parser->curr_lexer->current_input_column;
-
-          tree_statement *end_of_script
-            = curr_parser->make_end ("endscript", l, c);
-
-          curr_parser->make_script (0, end_of_script);
-
-          fcn_ptr = curr_parser->primary_fcn_ptr;
-        }
-    }
-  else if (require_file)
-    error ("no such file, '%s'", ff.c_str ());
-  else if (! warn_for.empty ())
-    error ("%s: unable to open file '%s'", warn_for.c_str (), ff.c_str ());
-
-  return fcn_ptr;
-}
-
-std::string
-get_help_from_file (const std::string& nm, bool& symbol_found,
-                    std::string& file)
-{
-  std::string retval;
-
-  file = fcn_file_in_path (nm);
-
-  if (! file.empty ())
-    {
-      symbol_found = true;
-
-      FILE *fptr = gnulib::fopen (file.c_str (), "r");
-
-      if (fptr)
-        {
-          unwind_protect frame;
-          frame.add_fcn (safe_fclose, fptr);
-
-          bool eof;
-          retval = gobble_leading_white_space (fptr, eof);
-
-          if (retval.empty ())
-            {
-              octave_function *fcn = parse_fcn_file (file, "", true,
-                                                     false, false,
-                                                     false, "");
-
-              if (fcn)
-                {
-                  retval = fcn->doc_string ();
-
-                  delete fcn;
-                }
-            }
-        }
-    }
-
-  return retval;
-}
-
-std::string
-get_help_from_file (const std::string& nm, bool& symbol_found)
-{
-  std::string file;
-  return get_help_from_file (nm, symbol_found, file);
-}
-
-std::string
-lookup_autoload (const std::string& nm)
-{
-  std::string retval;
-
-  typedef std::map<std::string, std::string>::const_iterator am_iter;
-
-  am_iter p = autoload_map.find (nm);
-
-  if (p != autoload_map.end ())
-    retval = load_path::find_file (p->second);
-
-  return retval;
-}
-
-string_vector
-autoloaded_functions (void)
-{
-  string_vector names (autoload_map.size ());
-
-  octave_idx_type i = 0;
-  typedef std::map<std::string, std::string>::const_iterator am_iter;
-  for (am_iter p = autoload_map.begin (); p != autoload_map.end (); p++)
-    names[i++] = p->first;
-
-  return names;
-}
-
-string_vector
-reverse_lookup_autoload (const std::string& nm)
-{
-  string_vector names;
-
-  typedef std::map<std::string, std::string>::const_iterator am_iter;
-  for (am_iter p = autoload_map.begin (); p != autoload_map.end (); p++)
-    if (nm == p->second)
-      names.append (p->first);
-
-  return names;
-}
-
-octave_function *
-load_fcn_from_file (const std::string& file_name, const std::string& dir_name,
-                    const std::string& dispatch_type,
-                    const std::string& fcn_name, bool autoload)
-{
-  octave_function *retval = 0;
-
-  unwind_protect frame;
-
-  std::string nm = file_name;
-
-  size_t nm_len = nm.length ();
-
-  std::string file;
-
-  bool relative_lookup = false;
-
-  file = nm;
-
-  if ((nm_len > 4 && nm.substr (nm_len-4) == ".oct")
-      || (nm_len > 4 && nm.substr (nm_len-4) == ".mex")
-      || (nm_len > 2 && nm.substr (nm_len-2) == ".m"))
-    {
-      nm = octave_env::base_pathname (file);
-      nm = nm.substr (0, nm.find_last_of ('.'));
-
-      size_t pos = nm.find_last_of (file_ops::dir_sep_str ());
-      if (pos != std::string::npos)
-        nm = nm.substr (pos+1);
-    }
-
-  relative_lookup = ! octave_env::absolute_pathname (file);
-
-  file = octave_env::make_absolute (file);
-
-  int len = file.length ();
-
-  if (len > 4 && file.substr (len-4, len-1) == ".oct")
-    {
-      if (autoload && ! fcn_name.empty ())
-        nm = fcn_name;
-
-      retval = octave_dynamic_loader::load_oct (nm, file, relative_lookup);
-    }
-  else if (len > 4 && file.substr (len-4, len-1) == ".mex")
-    {
-      // Temporarily load m-file version of mex-file, if it exists,
-      // to get the help-string to use.
-      frame.protect_var (curr_fcn_file_name);
-      frame.protect_var (curr_fcn_file_full_name);
-
-      curr_fcn_file_name = nm;
-      curr_fcn_file_full_name = file.substr (0, len - 2);
-
-      octave_function *tmpfcn = parse_fcn_file (file.substr (0, len - 2),
-                                                dispatch_type, false,
-                                                autoload, autoload,
-                                                relative_lookup, "");
-
-      retval = octave_dynamic_loader::load_mex (nm, file, relative_lookup);
-
-      if (tmpfcn)
-        retval->document (tmpfcn->doc_string ());
-      delete tmpfcn;
-    }
-  else if (len > 2)
-    {
-      // These are needed by yyparse.
-
-      frame.protect_var (curr_fcn_file_name);
-      frame.protect_var (curr_fcn_file_full_name);
-
-      curr_fcn_file_name = nm;
-      curr_fcn_file_full_name = file;
-
-      retval = parse_fcn_file (file, dispatch_type, true, autoload,
-                               autoload, relative_lookup, "");
-    }
-
-  if (retval)
-    {
-      retval->stash_dir_name (dir_name);
-
-      if (retval->is_user_function ())
-        {
-          symbol_table::scope_id id = retval->scope ();
-
-          symbol_table::stash_dir_name_for_subfunctions (id, dir_name);
-        }
-    }
-
-  return retval;
-}
-
-DEFUN (autoload, args, ,
-  "-*- texinfo -*-\n\
-@deftypefn {Built-in Function} {} autoload (@var{function}, @var{file})\n\
-Define @var{function} to autoload from @var{file}.\n\
-\n\
-The second argument, @var{file}, should be an absolute file name or\n\
-a file name in the same directory as the function or script from which\n\
-the autoload command was run.  @var{file} should not depend on the\n\
-Octave load path.\n\
-\n\
-Normally, calls to @code{autoload} appear in PKG_ADD script files that\n\
-are evaluated when a directory is added to the Octave's load path.  To\n\
-avoid having to hardcode directory names in @var{file}, if @var{file}\n\
-is in the same directory as the PKG_ADD script then\n\
-\n\
-@example\n\
-autoload (\"foo\", \"bar.oct\");\n\
-@end example\n\
-\n\
-@noindent\n\
-will load the function @code{foo} from the file @code{bar.oct}.  The above\n\
-when @code{bar.oct} is not in the same directory or uses like\n\
-\n\
-@example\n\
-autoload (\"foo\", file_in_loadpath (\"bar.oct\"))\n\
-@end example\n\
-\n\
-@noindent\n\
-are strongly discouraged, as their behavior might be unpredictable.\n\
-\n\
-With no arguments, return a structure containing the current autoload map.\n\
-@seealso{PKG_ADD}\n\
-@end deftypefn")
-{
-  octave_value retval;
-
-  int nargin = args.length ();
-
-  if (nargin == 0)
-    {
-      Cell func_names (dim_vector (autoload_map.size (), 1));
-      Cell file_names (dim_vector (autoload_map.size (), 1));
-
-      octave_idx_type i = 0;
-      typedef std::map<std::string, std::string>::const_iterator am_iter;
-      for (am_iter p = autoload_map.begin (); p != autoload_map.end (); p++)
-        {
-          func_names(i) = p->first;
-          file_names(i) = p->second;
-
-          i++;
-        }
-
-      octave_map m;
-
-      m.assign ("function", func_names);
-      m.assign ("file", file_names);
-
-      retval = m;
-    }
-  else if (nargin == 2)
-    {
-      string_vector argv = args.make_argv ("autoload");
-
-      if (! error_state)
-        {
-          std::string nm = argv[2];
-
-          if (! octave_env::absolute_pathname (nm))
-            {
-              octave_user_code *fcn = octave_call_stack::caller_user_code ();
-
-              bool found = false;
-
-              if (fcn)
-                {
-                  std::string fname = fcn->fcn_file_name ();
-
-                  if (! fname.empty ())
-                    {
-                      fname = octave_env::make_absolute (fname);
-                      fname = fname.substr (0, fname.find_last_of (file_ops::dir_sep_str ()) + 1);
-
-                      file_stat fs (fname + nm);
-
-                      if (fs.exists ())
-                        {
-                          nm = fname + nm;
-                          found = true;
-                        }
-                    }
-                }
-              if (! found)
-                warning_with_id ("Octave:autoload-relative-file-name",
-                                 "autoload: '%s' is not an absolute file name",
-                                 nm.c_str ());
-            }
-          autoload_map[argv[1]] = nm;
-        }
-    }
-  else
-    print_usage ();
-
-  return retval;
-}
-
-void
-source_file (const std::string& file_name, const std::string& context,
-             bool verbose, bool require_file, const std::string& warn_for)
-{
-  // Map from absolute name of script file to recursion level.  We
-  // use a map instead of simply placing a limit on recursion in the
-  // source_file function so that two mutually recursive scripts
-  // written as
-  //
-  //   foo1.m:
-  //   ------
-  //   foo2
-  //
-  //   foo2.m:
-  //   ------
-  //   foo1
-  //
-  // and called with
-  //
-  //   foo1
-  //
-  // (for example) will behave the same if they are written as
-  //
-  //   foo1.m:
-  //   ------
-  //   source ("foo2.m")
-  //
-  //   foo2.m:
-  //   ------
-  //   source ("foo1.m")
-  //
-  // and called with
-  //
-  //   source ("foo1.m")
-  //
-  // (for example).
-
-  static std::map<std::string, int> source_call_depth;
-
-  std::string file_full_name = file_ops::tilde_expand (file_name);
-
-  file_full_name = octave_env::make_absolute (file_full_name);
-
-  unwind_protect frame;
-
-  frame.protect_var (curr_fcn_file_name);
-  frame.protect_var (curr_fcn_file_full_name);
-
-  curr_fcn_file_name = file_name;
-  curr_fcn_file_full_name = file_full_name;
-
-  if (source_call_depth.find (file_full_name) == source_call_depth.end ())
-    source_call_depth[file_full_name] = -1;
-
-  frame.protect_var (source_call_depth[file_full_name]);
-
-  source_call_depth[file_full_name]++;
-
-  if (source_call_depth[file_full_name] >= Vmax_recursion_depth)
-    {
-      error ("max_recursion_depth exceeded");
-      return;
-    }
-
-  if (! context.empty ())
-    {
-      if (context == "caller")
-        octave_call_stack::goto_caller_frame ();
-      else if (context == "base")
-        octave_call_stack::goto_base_frame ();
-      else
-        error ("source: context must be \"caller\" or \"base\"");
-
-      if (! error_state)
-        frame.add_fcn (octave_call_stack::pop);
-    }
-
-  if (! error_state)
-    {
-      octave_function *fcn = parse_fcn_file (file_full_name, "",
-                                             require_file, true, false,
-                                             false, warn_for);
-
-      if (! error_state)
-        {
-          if (fcn && fcn->is_user_script ())
-            {
-              octave_value_list args;
-
-              if (verbose)
-                {
-                  std::cout << "executing commands from " << file_full_name << " ... ";
-                  reading_startup_message_printed = true;
-                  std::cout.flush ();
-                }
-
-              fcn->do_multi_index_op (0, args);
-
-              if (verbose)
-                std::cout << "done." << std::endl;
-
-              delete fcn;
-            }
-        }
-      else
-        error ("source: error sourcing file '%s'",
-               file_full_name.c_str ());
-    }
-}
-
-DEFUN (mfilename, args, ,
-  "-*- texinfo -*-\n\
-@deftypefn  {Built-in Function} {} mfilename ()\n\
-@deftypefnx {Built-in Function} {} mfilename (\"fullpath\")\n\
-@deftypefnx {Built-in Function} {} mfilename (\"fullpathext\")\n\
-Return the name of the currently executing file.  At the top-level,\n\
-return the empty string.  Given the argument @code{\"fullpath\"},\n\
-include the directory part of the file name, but not the extension.\n\
-Given the argument @code{\"fullpathext\"}, include the directory part\n\
-of the file name and the extension.\n\
-@end deftypefn")
-{
-  octave_value retval;
-
-  int nargin = args.length ();
-
-  if (nargin > 1)
-    {
-      print_usage ();
-      return retval;
-    }
-
-  std::string arg;
-
-  if (nargin == 1)
-    {
-      arg = args(0).string_value ();
-
-      if (error_state)
-        {
-          error ("mfilename: expecting argument to be a character string");
-          return retval;
-        }
-    }
-
-  std::string fname;
-
-  octave_user_code *fcn = octave_call_stack::caller_user_code ();
-
-  if (fcn)
-    {
-      fname = fcn->fcn_file_name ();
-
-      if (fname.empty ())
-        fname = fcn->name ();
-    }
-
-  if (arg == "fullpathext")
-    retval = fname;
-  else
-    {
-      size_t dpos = fname.rfind (file_ops::dir_sep_char ());
-      size_t epos = fname.rfind ('.');
-
-      if (epos <= dpos)
-        epos = std::string::npos;
-
-      fname = (epos != std::string::npos) ? fname.substr (0, epos) : fname;
-
-      if (arg == "fullpath")
-        retval = fname;
-      else
-        retval = (dpos != std::string::npos) ? fname.substr (dpos+1) : fname;
-    }
-
-  return retval;
-}
-
-
-DEFUN (source, args, ,
-  "-*- texinfo -*-\n\
-@deftypefn {Built-in Function} {} source (@var{file})\n\
-Parse and execute the contents of @var{file}.  This is equivalent to\n\
-executing commands from a script file, but without requiring the file to\n\
-be named @file{@var{file}.m}.\n\
-@end deftypefn")
-{
-  octave_value_list retval;
-
-  int nargin = args.length ();
-
-  if (nargin == 1 || nargin == 2)
-    {
-      std::string file_name = args(0).string_value ();
-
-      if (! error_state)
-        {
-          std::string context;
-
-          if (nargin == 2)
-            context = args(1).string_value ();
-
-          if (! error_state)
-            source_file (file_name, context);
-          else
-            error ("source: expecting context to be character string");
-        }
-      else
-        error ("source: expecting file name as argument");
-    }
-  else
-    print_usage ();
-
-  return retval;
-}
-
-// Evaluate an Octave function (built-in or interpreted) and return
-// the list of result values.  NAME is the name of the function to
-// call.  ARGS are the arguments to the function.  NARGOUT is the
-// number of output arguments expected.
-
-octave_value_list
-feval (const std::string& name, const octave_value_list& args, int nargout)
-{
-  octave_value_list retval;
-
-  octave_value fcn = symbol_table::find_function (name, args);
-
-  if (fcn.is_defined ())
-    retval = fcn.do_multi_index_op (nargout, args);
-  else
-    {
-      maybe_missing_function_hook (name);
-      if (! error_state)
-        error ("feval: function '%s' not found", name.c_str ());
-    }
-
-  return retval;
-}
-
-octave_value_list
-feval (octave_function *fcn, const octave_value_list& args, int nargout)
-{
-  octave_value_list retval;
-
-  if (fcn)
-    retval = fcn->do_multi_index_op (nargout, args);
-
-  return retval;
-}
-
-static octave_value_list
-get_feval_args (const octave_value_list& args)
-{
-  return args.slice (1, args.length () - 1, true);
-}
-
-
-// Evaluate an Octave function (built-in or interpreted) and return
-// the list of result values.  The first element of ARGS should be a
-// string containing the name of the function to call, then the rest
-// are the actual arguments to the function.  NARGOUT is the number of
-// output arguments expected.
-
-octave_value_list
-feval (const octave_value_list& args, int nargout)
-{
-  octave_value_list retval;
-
-  int nargin = args.length ();
-
-  if (nargin > 0)
-    {
-      octave_value f_arg = args(0);
-
-      if (f_arg.is_string ())
-        {
-          std::string name = f_arg.string_value ();
-
-          if (! error_state)
-            {
-              octave_value_list tmp_args = get_feval_args (args);
-
-              retval = feval (name, tmp_args, nargout);
-            }
-        }
-      else if (f_arg.is_function_handle ()
-               || f_arg.is_anonymous_function ()
-               || f_arg.is_inline_function ())
-        {
-          const octave_value_list tmp_args = get_feval_args (args);
-
-          retval = f_arg.do_multi_index_op (nargout, tmp_args);
-        }
-      else
-        error ("feval: first argument must be a string, inline function or a function handle");
-    }
-
-  return retval;
-}
-
-DEFUN (feval, args, nargout,
-  "-*- texinfo -*-\n\
-@deftypefn {Built-in Function} {} feval (@var{name}, @dots{})\n\
-Evaluate the function named @var{name}.  Any arguments after the first\n\
-are passed on to the named function.  For example,\n\
-\n\
-@example\n\
-@group\n\
-feval (\"acos\", -1)\n\
-     @result{} 3.1416\n\
-@end group\n\
-@end example\n\
-\n\
-@noindent\n\
-calls the function @code{acos} with the argument @samp{-1}.\n\
-\n\
-The function @code{feval} can also be used with function handles of\n\
-any sort (@pxref{Function Handles}).  Historically, @code{feval} was\n\
-the only way to call user-supplied functions in strings, but\n\
-function handles are now preferred due to the cleaner syntax they\n\
-offer.  For example,\n\
-\n\
-@example\n\
-@group\n\
-@var{f} = @@exp;\n\
-feval (@var{f}, 1)\n\
-    @result{} 2.7183\n\
-@var{f} (1)\n\
-    @result{} 2.7183\n\
-@end group\n\
-@end example\n\
-\n\
-@noindent\n\
-are equivalent ways to call the function referred to by @var{f}.  If it\n\
-cannot be predicted beforehand that @var{f} is a function handle or the\n\
-function name in a string, @code{feval} can be used instead.\n\
-@end deftypefn")
-{
-  octave_value_list retval;
-
-  int nargin = args.length ();
-
-  if (nargin > 0)
-    retval = feval (args, nargout);
-  else
-    print_usage ();
-
-  return retval;
-}
-
-DEFUN (builtin, args, nargout,
-  "-*- texinfo -*-\n\
-@deftypefn {Loadable Function} {[@dots{}]} builtin (@var{f}, @dots{})\n\
-Call the base function @var{f} even if @var{f} is overloaded to\n\
-another function for the given type signature.\n\
-@end deftypefn")
-{
-  octave_value_list retval;
-
-  int nargin = args.length ();
-
-  if (nargin > 0)
-    {
-      const std::string name (args(0).string_value ());
-
-      if (! error_state)
-        {
-          octave_value fcn = symbol_table::builtin_find (name);
-
-          if (fcn.is_defined ())
-            retval = feval (fcn.function_value (), args.splice (0, 1),
-                            nargout);
-          else
-            error ("builtin: lookup for symbol '%s' failed", name.c_str ());
-        }
-      else
-        error ("builtin: function name (F) must be a string");
-    }
-  else
-    print_usage ();
-
-  return retval;
-}
-
-octave_value_list
-eval_string (const std::string& s, bool silent, int& parse_status, int nargout)
-{
-  octave_value_list retval;
-
-  unwind_protect frame;
-
-  // octave_parser constructor sets this for us.
-  frame.protect_var (CURR_LEXER);
-
-  octave_parser *curr_parser = new octave_parser ();
-  frame.add_fcn (octave_parser::cleanup, curr_parser);
-
-  frame.protect_var (get_input_from_eval_string);
-  frame.protect_var (line_editing);
-  frame.protect_var (current_eval_string);
-  frame.protect_var (reading_fcn_file);
-  frame.protect_var (reading_script_file);
-  frame.protect_var (reading_classdef_file);
-
-  get_input_from_eval_string = true;
-  line_editing = false;
-  reading_fcn_file = false;
-  reading_script_file = false;
-  reading_classdef_file = false;
-
-  current_eval_string = s;
-
-  do
-    {
-      curr_parser->reset ();
-
-      frame.protect_var (global_command);
-
-      global_command = 0;
-
-      // Do this with an unwind-protect cleanup function so that the
-      // forced variables will be unmarked in the event of an
-      // interrupt.
-      symbol_table::scope_id scope = symbol_table::top_scope ();
-      frame.add_fcn (symbol_table::unmark_forced_variables, scope);
-
-      parse_status = curr_parser->run ();
-
-      tree_statement_list *command_list = global_command;
-
-      // Unmark forced variables.
-      // Restore previous value of global_command.
-      frame.run (2);
-
-      if (parse_status == 0)
-        {
-          if (command_list)
-            {
-              unwind_protect inner_frame;
-
-              // Use an unwind-protect cleanup function so that the
-              // global_command list will be deleted in the event of an
-              // interrupt.
-
-              inner_frame.add_fcn (cleanup_statement_list, &command_list);
-
-              tree_statement *stmt = 0;
-
-              if (command_list->length () == 1
-                  && (stmt = command_list->front ())
-                  && stmt->is_expression ())
-                {
-                  tree_expression *expr = stmt->expression ();
-
-                  if (silent)
-                    expr->set_print_flag (false);
-
-                  bool do_bind_ans = false;
-
-                  if (expr->is_identifier ())
-                    {
-                      tree_identifier *id
-                        = dynamic_cast<tree_identifier *> (expr);
-
-                      do_bind_ans = (! id->is_variable ());
-                    }
-                  else
-                    do_bind_ans = (! expr->is_assignment_expression ());
-
-                  retval = expr->rvalue (nargout);
-
-                  if (do_bind_ans && ! (error_state || retval.empty ()))
-                    bind_ans (retval(0), expr->print_result ());
-
-                  if (nargout == 0)
-                    retval = octave_value_list ();
-                }
-              else if (nargout == 0)
-                command_list->accept (*current_evaluator);
-              else
-                error ("eval: invalid use of statement list");
-
-              if (error_state
-                  || tree_return_command::returning
-                  || tree_break_command::breaking
-                  || tree_continue_command::continuing)
-                break;
-            }
-          else if (curr_parser->end_of_input)
-            break;
-        }
-    }
-  while (parse_status == 0);
-
-  return retval;
-}
-
-octave_value
-eval_string (const std::string& s, bool silent, int& parse_status)
-{
-  octave_value retval;
-
-  octave_value_list tmp = eval_string (s, silent, parse_status, 1);
-
-  if (! tmp.empty ())
-    retval = tmp(0);
-
-  return retval;
-}
-
-static octave_value_list
-eval_string (const octave_value& arg, bool silent, int& parse_status,
-             int nargout)
-{
-  std::string s = arg.string_value ();
-
-  if (error_state)
-    {
-      error ("eval: expecting std::string argument");
-      return octave_value (-1);
-    }
-
-  return eval_string (s, silent, parse_status, nargout);
-}
-
-void
-cleanup_statement_list (tree_statement_list **lst)
-{
-  if (*lst)
-    {
-      delete *lst;
-      *lst = 0;
-    }
-}
-
-DEFUN (eval, args, nargout,
-  "-*- texinfo -*-\n\
-@deftypefn  {Built-in Function} {} eval (@var{try})\n\
-@deftypefnx {Built-in Function} {} eval (@var{try}, @var{catch})\n\
-Parse the string @var{try} and evaluate it as if it were an Octave\n\
-program.  If that fails, evaluate the optional string @var{catch}.\n\
-The string @var{try} is evaluated in the current context,\n\
-so any results remain available after @code{eval} returns.\n\
-\n\
-The following example makes the variable @var{a} with the approximate\n\
-value 3.1416 available.\n\
-\n\
-@example\n\
-eval (\"a = acos(-1);\");\n\
-@end example\n\
-\n\
-If an error occurs during the evaluation of @var{try} the @var{catch}\n\
-string is evaluated, as the following example shows:\n\
-\n\
-@example\n\
-@group\n\
-eval ('error (\"This is a bad example\");',\n\
-      'printf (\"This error occurred:\\n%s\\n\", lasterr ());');\n\
-     @print{} This error occurred:\n\
-        This is a bad example\n\
-@end group\n\
-@end example\n\
-\n\
-Consider using try/catch blocks instead if you are only using @code{eval}\n\
-as an error-capturing mechanism rather than for the execution of arbitrary\n\
-code strings.\n\
-@seealso{evalin}\n\
-@end deftypefn")
-{
-  octave_value_list retval;
-
-  int nargin = args.length ();
-
-  if (nargin > 0)
-    {
-      unwind_protect frame;
-
-      if (nargin > 1)
-        {
-          frame.protect_var (buffer_error_messages);
-          buffer_error_messages++;
-        }
-
-      int parse_status = 0;
-
-      octave_value_list tmp = eval_string (args(0), nargout > 0,
-                                           parse_status, nargout);
-
-      if (nargin > 1 && (parse_status != 0 || error_state))
-        {
-          error_state = 0;
-
-          // Set up for letting the user print any messages from
-          // errors that occurred in the first part of this eval().
-
-          buffer_error_messages--;
-
-          tmp = eval_string (args(1), nargout > 0, parse_status, nargout);
-
-          if (nargout > 0)
-            retval = tmp;
-        }
-      else if (nargout > 0)
-        retval = tmp;
-    }
-  else
-    print_usage ();
-
-  return retval;
-}
-
-/*
-
-%!shared x
-%! x = 1;
-
-%!assert (eval ("x"), 1)
-%!assert (eval ("x;"))
-%!assert (eval ("x;"), 1);
-
-%!test
-%! y = eval ("x");
-%! assert (y, 1);
-
-%!test
-%! y = eval ("x;");
-%! assert (y, 1);
-
-%!test
-%! eval ("x = 1;")
-%! assert (x,1);
-
-%!test
-%! eval ("flipud = 2;");
-%! assert (flipud, 2);
-
-%!function y = __f ()
-%!  eval ("flipud = 2;");
-%!  y = flipud;
-%!endfunction
-%!assert (__f(), 2)
-
-% bug #35645
-%!test
-%! [a,] = gcd (1,2);
-%! [a,b,] = gcd (1, 2);
-
-*/
-
-DEFUN (assignin, args, ,
-  "-*- texinfo -*-\n\
-@deftypefn {Built-in Function} {} assignin (@var{context}, @var{varname}, @var{value})\n\
-Assign @var{value} to @var{varname} in context @var{context}, which\n\
-may be either @code{\"base\"} or @code{\"caller\"}.\n\
-@seealso{evalin}\n\
-@end deftypefn")
-{
-  octave_value_list retval;
-
-  int nargin = args.length ();
-
-  if (nargin == 3)
-    {
-      std::string context = args(0).string_value ();
-
-      if (! error_state)
-        {
-          unwind_protect frame;
-
-          if (context == "caller")
-            octave_call_stack::goto_caller_frame ();
-          else if (context == "base")
-            octave_call_stack::goto_base_frame ();
-          else
-            error ("assignin: CONTEXT must be \"caller\" or \"base\"");
-
-          if (! error_state)
-            {
-              frame.add_fcn (octave_call_stack::pop);
-
-              std::string nm = args(1).string_value ();
-
-              if (! error_state)
-                {
-                  if (valid_identifier (nm))
-                    symbol_table::varref (nm) = args(2);
-                  else
-                    error ("assignin: invalid variable name in argument VARNAME");
-                }
-              else
-                error ("assignin: VARNAME must be a string");
-            }
-        }
-      else
-        error ("assignin: CONTEXT must be a string");
-    }
-  else
-    print_usage ();
-
-  return retval;
-}
-
-DEFUN (evalin, args, nargout,
-  "-*- texinfo -*-\n\
-@deftypefn  {Built-in Function} {} evalin (@var{context}, @var{try})\n\
-@deftypefnx {Built-in Function} {} evalin (@var{context}, @var{try}, @var{catch})\n\
-Like @code{eval}, except that the expressions are evaluated in the\n\
-context @var{context}, which may be either @code{\"caller\"} or\n\
-@code{\"base\"}.\n\
-@seealso{eval, assignin}\n\
-@end deftypefn")
-{
-  octave_value_list retval;
-
-  int nargin = args.length ();
-
-  if (nargin > 1)
-    {
-      std::string context = args(0).string_value ();
-
-      if (! error_state)
-        {
-          unwind_protect frame;
-
-          if (context == "caller")
-            octave_call_stack::goto_caller_frame ();
-          else if (context == "base")
-            octave_call_stack::goto_base_frame ();
-          else
-            error ("evalin: CONTEXT must be \"caller\" or \"base\"");
-
-          if (! error_state)
-            {
-              frame.add_fcn (octave_call_stack::pop);
-
-              if (nargin > 2)
-                {
-                  frame.protect_var (buffer_error_messages);
-                  buffer_error_messages++;
-                }
-
-              int parse_status = 0;
-
-              octave_value_list tmp = eval_string (args(1), nargout > 0,
-                                                   parse_status, nargout);
-
-              if (nargout > 0)
-                retval = tmp;
-
-              if (nargin > 2 && (parse_status != 0 || error_state))
-                {
-                  error_state = 0;
-
-                  // Set up for letting the user print any messages from
-                  // errors that occurred in the first part of this eval().
-
-                  buffer_error_messages--;
-
-                  tmp = eval_string (args(2), nargout > 0,
-                                     parse_status, nargout);
-
-                  retval = (nargout > 0) ? tmp : octave_value_list ();
-                }
-            }
-        }
-      else
-        error ("evalin: CONTEXT must be a string");
-    }
-  else
-    print_usage ();
-
-  return retval;
-}
-
-DEFUN (__parser_debug_flag__, args, nargout,
-  "-*- texinfo -*-\n\
-@deftypefn {Built-in Function} {@var{old_val} =} __parser_debug_flag__ (@var{new_val}))\n\
-Undocumented internal function.\n\
-@end deftypefn")
-{
-  octave_value retval;
-
-  bool debug_flag = octave_debug;
-
-  retval = set_internal_variable (debug_flag, args, nargout,
-                                  "__parser_debug_flag__");
-
-  octave_debug = debug_flag;
-
-  return retval;
-}
--- a/libinterp/parse-tree/parse.h	Thu Feb 28 02:04:24 2013 -0500
+++ b/libinterp/parse-tree/parse.h	Wed Mar 06 16:43:33 2013 -0500
@@ -83,18 +83,12 @@
 // Nonzero means print parser debugging info (-d).
 extern int octave_debug;
 
-// Buffer for help text snagged from function files.
-extern std::stack<std::string> help_buf;
-
 // TRUE means we are using readline.
 extern bool line_editing;
 
 // TRUE means we printed messages about reading startup files.
 extern bool reading_startup_message_printed;
 
-// TRUE means input is coming from startup file.
-extern bool input_from_startup_file;
-
 extern OCTINTERP_API std::string
 get_help_from_file (const std::string& nm, bool& symbol_found,
                     std::string& file);
@@ -144,7 +138,7 @@
 
 // Global access to currently active lexer.
 // FIXME -- to be removed after more parser+lexer refactoring.
-extern lexical_feedback *CURR_LEXER;
+extern octave_lexer *CURR_LEXER;
 
 class
 octave_parser
@@ -152,25 +146,50 @@
 public:
 
   octave_parser (void)
-    : end_of_input (false), endfunction_found (false),
+    : endfunction_found (false),
+      autoloading (false), fcn_file_from_relative_lookup (false),
+      parsing_subfunctions (false), max_fcn_depth (0),
+      curr_fcn_depth (0), primary_fcn_scope (-1),
+      curr_class_name (), function_scopes (), primary_fcn_ptr (0),
+<<<<<<< local
+      classdef_object (0), curr_lexer (new lexical_feedback ())
+=======
+      stmt_list (0),
+      curr_lexer (new octave_lexer ()), parser_state (0)
+>>>>>>> other
+  {
+    init ();
+  }
+
+  octave_parser (FILE *file)
+    : endfunction_found (false),
       autoloading (false), fcn_file_from_relative_lookup (false),
       parsing_subfunctions (false), max_fcn_depth (0),
       curr_fcn_depth (0), primary_fcn_scope (-1),
       curr_class_name (), function_scopes (), primary_fcn_ptr (0),
-      classdef_object (0), curr_lexer (new lexical_feedback ())
+      stmt_list (0),
+      curr_lexer (new octave_lexer (file)), parser_state (0)
   {
-    CURR_LEXER = curr_lexer;
+    init ();
   }
 
-  ~octave_parser (void)
+  octave_parser (const std::string& eval_string)
+    : endfunction_found (false),
+      autoloading (false), fcn_file_from_relative_lookup (false),
+      parsing_subfunctions (false), max_fcn_depth (0),
+      curr_fcn_depth (0), primary_fcn_scope (-1),
+      curr_class_name (), function_scopes (), primary_fcn_ptr (0),
+      stmt_list (0),
+      curr_lexer (new octave_lexer (eval_string)), parser_state (0)
   {
-    delete curr_lexer;
+    init ();
   }
 
-  void reset (void)
-  {
-    curr_lexer->reset ();
-  }
+  ~octave_parser (void);
+
+  void init (void);
+
+  void reset (void);
 
   int run (void);
 
@@ -396,9 +415,6 @@
   // Generic error messages.
   void bison_error (const char *s);
 
-  // TRUE means that we have encountered EOF on the input stream.
-  bool end_of_input;
-
   // Have we found an explicit end to a function?
   bool endfunction_found;
 
@@ -440,11 +456,20 @@
   // Pointer to the primary user function or user script function.
   octave_function *primary_fcn_ptr;
 
+<<<<<<< local
   // Pointer to the classdef object we just parsed, if any.
   tree_classdef *classdef_object;
+=======
+  // Result of parsing input.
+  tree_statement_list *stmt_list;
+>>>>>>> other
 
   // State of the lexer.
-  lexical_feedback *curr_lexer;
+  octave_lexer *curr_lexer;
+
+  // Internal state of the parser.  Only used if USE_PUSH_PARSER is
+  // defined.
+  void *parser_state;
 
   // For unwind protect.
   static void cleanup (octave_parser *parser) { delete parser; }
--- a/libinterp/parse-tree/pt-check.cc	Thu Feb 28 02:04:24 2013 -0500
+++ b/libinterp/parse-tree/pt-check.cc	Wed Mar 06 16:43:33 2013 -0500
@@ -559,8 +559,8 @@
 void
 tree_checker::gripe (const std::string& msg, int line)
 {
-  if (curr_fcn_file_name.empty ())
+  if (file_name.empty ())
     error ("%s", msg.c_str ());
   else
-    error ("%s: %d: %s", curr_fcn_file_name.c_str (), line, msg.c_str ());
+    error ("%s: %d: %s", file_name.c_str (), line, msg.c_str ());
 }
--- a/libinterp/parse-tree/pt-check.h	Thu Feb 28 02:04:24 2013 -0500
+++ b/libinterp/parse-tree/pt-check.h	Wed Mar 06 16:43:33 2013 -0500
@@ -35,7 +35,7 @@
 public:
 
   tree_checker (void)
-    : do_lvalue_check (false) { }
+    : do_lvalue_check (false), file_name () { }
 
   ~tree_checker (void) { }
 
@@ -127,6 +127,8 @@
 
   bool do_lvalue_check;
 
+  std::string file_name;
+
   void do_decl_command (tree_decl_command&);
 
   void gripe (const std::string& msg, int line);
--- a/liboctave/array/Range.cc	Thu Feb 28 02:04:24 2013 -0500
+++ b/liboctave/array/Range.cc	Wed Mar 06 16:43:33 2013 -0500
@@ -36,14 +36,6 @@
 #include "lo-utils.h"
 #include "Array-util.h"
 
-Range::Range (double b, double i, octave_idx_type n)
-  : rng_base (b), rng_limit (b + (n-1) * i), rng_inc (i),
-    rng_nelem (n), cache ()
-{
-  if (! xfinite (b) || ! xfinite (i))
-    rng_nelem = -2;
-}
-
 bool
 Range::all_elements_are_ints (void) const
 {
@@ -64,17 +56,24 @@
       cache.resize (1, rng_nelem);
       double b = rng_base;
       double increment = rng_inc;
-      for (octave_idx_type i = 0; i < rng_nelem; i++)
-        cache(i) = b + i * increment;
+      if (rng_nelem > 0)
+        {
+          // The first element must always be *exactly* the base.
+          // E.g, -0 would otherwise become +0 in the loop (-0 + 0*increment).
+          cache(0) = b; 
+          for (octave_idx_type i = 1; i < rng_nelem; i++)
+            cache(i) = b + i * increment;
+        }
 
       // On some machines (x86 with extended precision floating point
       // arithmetic, for example) it is possible that we can overshoot
       // the limit by approximately the machine precision even though
       // we were very careful in our calculation of the number of
-      // elements.
+      // elements.  The tests need equality (>= rng_limit or <= rng_limit)
+      // to have expressions like -5:1:-0 result in a -0 endpoint.
 
-      if ((rng_inc > 0 && cache(rng_nelem-1) > rng_limit)
-          || (rng_inc < 0 && cache(rng_nelem-1) < rng_limit))
+      if ((rng_inc > 0 && cache(rng_nelem-1) >= rng_limit)
+          || (rng_inc < 0 && cache(rng_nelem-1) <= rng_limit))
         cache(rng_nelem-1) = rng_limit;
     }
 
@@ -87,16 +86,71 @@
   if (i < 0 || i >= rng_nelem)
     gripe_index_out_of_range (1, 1, i+1, rng_nelem);
 
-  return rng_base + rng_inc * i;
+  if (i == 0)
+    return rng_base;
+  else if (i < rng_nelem - 1) 
+    return rng_base + i * rng_inc;
+  else
+    {
+      double end = rng_base + i * rng_inc;
+      if ((rng_inc > 0 && end >= rng_limit)
+          || (rng_inc < 0 && end <= rng_limit))
+        return rng_limit;
+      else
+        return end;
+    }
 }
 
-struct _rangeidx_helper
+double
+Range::elem (octave_idx_type i) const
+{
+#if defined (BOUNDS_CHECKING)
+  return checkelem (i);
+#else
+  if (i == 0)
+    return rng_base;
+  else if (i < rng_nelem - 1) 
+    return rng_base + i * rng_inc;
+  else
+    {
+      double end = rng_base + i * rng_inc;
+      if ((rng_inc > 0 && end >= rng_limit)
+          || (rng_inc < 0 && end <= rng_limit))
+        return rng_limit;
+      else
+        return end;
+    }
+#endif
+}
+
+// Helper class used solely for idx_vector.loop () function call
+class __rangeidx_helper
 {
-  double *array, base, inc;
-  _rangeidx_helper (double *a, double b, double i)
-    : array (a), base (b), inc (i) { }
+ public:
+  __rangeidx_helper (double *a, double b, double i, double l, octave_idx_type n)
+    : array (a), base (b), inc (i), limit (l), nmax (n-1) { }
+
   void operator () (octave_idx_type i)
-    { *array++ = base + i * inc; }
+    {
+      if (i == 0)
+        *array++ = base;
+      else if (i < nmax) 
+        *array++ = base + i * inc;
+      else
+        {
+          double end = base + i * inc;
+          if ((inc > 0 && end >= limit) || (inc < 0 && end <= limit))
+            *array++ = limit;
+          else
+            *array++ = end;
+        }
+    }
+
+ private:
+
+  double *array, base, inc, limit;
+  octave_idx_type nmax;
+
 };
 
 Array<double>
@@ -119,19 +173,22 @@
       octave_idx_type il = i.length (n);
 
       // taken from Array.cc.
-
       if (n != 1 && rd.is_vector ())
         rd = dim_vector (1, il);
 
       retval.clear (rd);
 
-      i.loop (n, _rangeidx_helper (retval.fortran_vec (), rng_base, rng_inc));
+      // idx_vector loop across all values in i,
+      // executing __rangeidx_helper (i) for each i
+      i.loop (n, __rangeidx_helper (retval.fortran_vec (),
+                                    rng_base, rng_inc, rng_limit, rng_nelem));
     }
 
   return retval;
 }
 
 // NOTE: max and min only return useful values if nelem > 0.
+//       do_minmax_body() in max.cc avoids calling Range::min/max if nelem == 0.
 
 double
 Range::min (void) const
@@ -146,8 +203,7 @@
           retval = rng_base + (rng_nelem - 1) * rng_inc;
 
           // See the note in the matrix_value method above.
-
-          if (retval < rng_limit)
+          if (retval <= rng_limit)
             retval = rng_limit;
         }
 
@@ -166,8 +222,7 @@
           retval = rng_base + (rng_nelem - 1) * rng_inc;
 
           // See the note in the matrix_value method above.
-
-          if (retval > rng_limit)
+          if (retval >= rng_limit)
             retval = rng_limit;
         }
       else
@@ -268,7 +323,7 @@
   if (dim == 1)
     {
       if (mode == ASCENDING)
-          retval.sort_internal (sidx, true);
+        retval.sort_internal (sidx, true);
       else if (mode == DESCENDING)
         retval.sort_internal (sidx, false);
     }
@@ -281,10 +336,10 @@
 sortmode
 Range::is_sorted (sortmode mode) const
 {
-  if (rng_nelem > 1 && rng_inc < 0)
+  if (rng_nelem > 1 && rng_inc > 0)
+    mode = (mode == DESCENDING) ? UNSORTED : ASCENDING;
+  else if (rng_nelem > 1 && rng_inc < 0)
     mode = (mode == ASCENDING) ? UNSORTED : DESCENDING;
-  else if (rng_nelem > 1 && rng_inc > 0)
-    mode = (mode == DESCENDING) ? UNSORTED : ASCENDING;
   else
     mode = mode ? mode : ASCENDING;
 
@@ -298,12 +353,15 @@
   double increment = a.inc ();
   octave_idx_type num_elem = a.nelem ();
 
-  for (octave_idx_type i = 0; i < num_elem-1; i++)
-    os << b + i * increment << " ";
+  if (num_elem > 1)
+    {
+      // First element must be the base *exactly* (-0).
+      os << b << " ";
+      for (octave_idx_type i = 1; i < num_elem-1; i++)
+        os << b + i * increment << " ";
+    }
 
-  // Prevent overshoot.  See comment in the matrix_value method
-  // above.
-
+  // Prevent overshoot.  See comment in the matrix_value method above.
   os << (increment > 0 ? a.max () : a.min ()) << "\n";
 
   return os;
@@ -502,7 +560,7 @@
             n_elt++;
         }
 
-      retval = (n_elt >= std::numeric_limits<octave_idx_type>::max () - 1) ? -1 : n_elt;
+      retval = (n_elt < std::numeric_limits<octave_idx_type>::max () - 1) ? n_elt : -1;
     }
 
   return retval;
--- a/liboctave/array/Range.h	Thu Feb 28 02:04:24 2013 -0500
+++ b/liboctave/array/Range.h	Wed Mar 06 16:43:33 2013 -0500
@@ -50,7 +50,13 @@
       rng_nelem (nelem_internal ()), cache () { }
 
   // For operators' usage (to preserve element count).
-  Range (double b, double i, octave_idx_type n);
+  Range (double b, double i, octave_idx_type n)
+    : rng_base (b), rng_limit (b + (n-1) * i), rng_inc (i),
+      rng_nelem (n), cache ()
+    {
+      if (! xfinite (b) || ! xfinite (i))
+        rng_nelem = -2;
+    }
 
   double base (void) const { return rng_base; }
   double limit (void) const { return rng_limit; }
@@ -80,14 +86,7 @@
 
   double checkelem (octave_idx_type i) const;
 
-  double elem (octave_idx_type i) const
-    {
-#if defined (BOUNDS_CHECKING)
-      return checkelem (i);
-#else
-      return rng_base + rng_inc * i;
-#endif
-    }
+  double elem (octave_idx_type i) const;
 
   Array<double> index (const idx_vector& i) const;
 
--- a/m4/acinclude.m4	Thu Feb 28 02:04:24 2013 -0500
+++ b/m4/acinclude.m4	Wed Mar 06 16:43:33 2013 -0500
@@ -1405,6 +1405,62 @@
   AC_PROG_YACC
   case "$YACC" in
     bison*)
+    AC_CACHE_CHECK([syntax of bison push/pull declaration],
+                   [octave_cv_bison_push_pull_decl_style], [
+      style="dash underscore"
+      quote="noquote quote"
+      for s in $style; do
+        for q in $quote; do
+          if test $s = "dash"; then
+            def="%define api.push-pull"
+          else
+            def="%define api.push_pull"
+          fi
+          if test $q = "quote"; then
+            def="$def \"both\""
+          else
+            def="$def both"
+          fi
+          cat << EOF > conftest.yy
+$def
+%start input
+%%
+input:;
+%%
+EOF
+          $YACC conftest.yy > /dev/null 2>&1
+          ac_status=$?
+          if test $ac_status -eq 0; then
+            if test $q = noquote; then
+              q=
+            fi
+            octave_cv_bison_push_pull_decl_style="$s $q"
+            break
+          fi
+        done
+        if test $ac_status -eq 0; then
+          break
+        fi
+      done
+      rm -f conftest.yy y.tab.h y.tab.c
+      ])
+    ;;
+  esac
+
+  AC_SUBST(BISON_PUSH_PULL_DECL_STYLE, $octave_cv_bison_push_pull_decl_style)
+
+  if test -z "$octave_cv_bison_push_pull_decl_style"; then
+    YACC=
+    warn_bison_push_pull_decl_style="
+
+I wasn't able to find a suitable style for declaring a push-pull
+parser in a bison input file so I'm disabling bison.
+"
+    OCTAVE_CONFIGURE_WARNING([warn_bison_push_pull_decl_style])
+  fi
+
+  case "$YACC" in
+    bison*)
     ;;
     *)
       YACC='$(top_srcdir)/build-aux/missing bison'
--- a/scripts/general/celldisp.m	Thu Feb 28 02:04:24 2013 -0500
+++ b/scripts/general/celldisp.m	Wed Mar 06 16:43:33 2013 -0500
@@ -17,7 +17,8 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} celldisp (@var{c}, @var{name})
+## @deftypefn  {Function File} {} celldisp (@var{c})
+## @deftypefnx {Function File} {} celldisp (@var{c}, @var{name})
 ## Recursively display the contents of a cell array.  By default the values
 ## are displayed with the name of the variable @var{c}.  However, this name
 ## can be replaced with the variable @var{name}.  For example:
@@ -44,12 +45,13 @@
 ## This is ugly, but seems to be what matlab does..
 
 function celldisp (c, name)
+
   if (nargin < 1 || nargin > 2)
     print_usage ();
   endif
 
   if (! iscell (c))
-    error ("celldisp: argument must be a cell array");
+    error ("celldisp: C must be a cell array");
   endif
 
   if (nargin == 1)
@@ -83,7 +85,7 @@
 %! c = {1, 2, {31, 32}};
 %! celldisp (c, "b")
 
+## Test input validation
 %!error celldisp ()
 %!error celldisp ({}, "name", 1)
-%!error celldisp (1)
-
+%!error <C must be a cell array> celldisp (1)
--- a/scripts/general/num2str.m	Thu Feb 28 02:04:24 2013 -0500
+++ b/scripts/general/num2str.m	Wed Mar 06 16:43:33 2013 -0500
@@ -24,8 +24,9 @@
 ## optional second argument may either give the number of significant
 ## digits (@var{precision}) to be used in the output or a format
 ## template string (@var{format}) as in @code{sprintf} (@pxref{Formatted
-## Output}).  @code{num2str} can also handle complex numbers.  For
-## example:
+## Output}).  @code{num2str} can also handle complex numbers.
+##
+## Examples:
 ##
 ## @example
 ## @group
@@ -50,11 +51,17 @@
 ## @end group
 ## @end example
 ##
+## Notes:
+##
+## For Matlab compatibility, leading spaces are stripped before returning
+## the string.
+##
 ## The @code{num2str} function is not very flexible.  For better control
 ## over the results, use @code{sprintf} (@pxref{Formatted Output}).
-## Note that for complex @var{x}, the format string may only contain one
-## output conversion specification and nothing else.  Otherwise, you
-## will get unpredictable results.
+##
+## For complex @var{x}, the format string may only contain one
+## output conversion specification and nothing else.  Otherwise, results
+## will be unpredictable.
 ## @seealso{sprintf, int2str, mat2str}
 ## @end deftypefn
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/miscellaneous/citation.m	Wed Mar 06 16:43:33 2013 -0500
@@ -0,0 +1,51 @@
+## Copyright (C) 2013 Carnë Draug
+##
+## This file is part of Octave.
+##
+## Octave 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 3 of the License, or (at
+## your option) any later version.
+##
+## Octave 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 Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {Command} {} citation
+## @deftypefnx {Command} {} citation @var{package}
+## Display instructions to cite GNU Octave and packages in publications.
+##
+## When called without an argument, displays information on how to cite the core
+## GNU Octave system in publications.  When given a package name @var{package},
+## display information on to cite it.  However, note that some packages may not
+## have instructions on how to cite them.
+##
+## The GNU Octave developers and its active community of package authors have
+## invested a lot of time and effort in creating GNU Octave as it is today.
+## Please give credit where credit is due and cite GNU Octave and its packages
+## when you use them.
+##
+## @end deftypefn
+
+## Author: Carnë Draug <carandraug+dev@gmail.com>
+## Idea and documentation from R's citation() (also under GPL)
+
+function citation (package = "octave")
+
+  if (nargin > 1)
+    print_usage ();
+  else
+    display_info_file ("citation", package, "CITATION");
+  endif
+
+endfunction
+
+%!error citation (1, 2)
+%!error <citation: PACKAGE must be a string> citation (1)
+%!error <citation: package .* is not installed> citation ("__NOT_A_VALID_PKG_NAME__")
--- a/scripts/miscellaneous/module.mk	Thu Feb 28 02:04:24 2013 -0500
+++ b/scripts/miscellaneous/module.mk	Wed Mar 06 16:43:33 2013 -0500
@@ -1,6 +1,7 @@
 FCN_FILE_DIRS += miscellaneous
 
 miscellaneous_PRIVATE_FCN_FILES = \
+  miscellaneous/private/display_info_file.m \
   miscellaneous/private/__xzip__.m
 
 miscellaneous_FCN_FILES = \
@@ -10,6 +11,7 @@
   miscellaneous/bunzip2.m \
   miscellaneous/bzip2.m \
   miscellaneous/cast.m \
+  miscellaneous/citation.m \
   miscellaneous/comma.m \
   miscellaneous/compare_versions.m \
   miscellaneous/computer.m \
--- a/scripts/miscellaneous/news.m	Thu Feb 28 02:04:24 2013 -0500
+++ b/scripts/miscellaneous/news.m	Wed Mar 06 16:43:33 2013 -0500
@@ -17,8 +17,8 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} news
-## @deftypefnx {Function File} {} news (@var{package})
+## @deftypefn  {Command} {} news
+## @deftypefnx {Command} {} news @var{package}
 ## Display the current NEWS file for Octave or an installed package.
 ##
 ## When called without an argument, display the NEWS file for Octave.
@@ -30,42 +30,13 @@
 
   if (nargin > 1)
     print_usage ();
-  elseif (! ischar (package))
-    error ("news: PACKAGE must be a string");
+  else
+    display_info_file ("news", package, "NEWS");
   endif
 
-  if (strcmpi (package, "octave"))
-    octetcdir = octave_config_info ("octetcdir");
-    newsfile  = fullfile (octetcdir, "NEWS");
-  else
-    installed = pkg ("list");
-    names     = cellfun (@(x) x.name, installed, "UniformOutput", false);
-    ## we are nice and let the user use any case on the package name
-    pos = strcmpi (names, package);
-    if (!any (pos))
-      error ("Package '%s' is not installed.", package);
-    endif
-    newsfile = fullfile (installed{pos}.dir, "packinfo", "NEWS");
-  endif
-
-  if (! exist (newsfile, "file"))
-    if (strcmpi (package, "octave"))
-      error ("news: unable to locate NEWS file");
-    else
-      error ("news: unable to locate NEWS file for package %s", package);
-    endif
-  endif
-
-  fid = fopen (newsfile, "r");
-  while (ischar (line = fgets (fid)))
-    puts (line);
-  endwhile
-  fclose (fid);
-
 endfunction
 
 
 %!error news (1, 2)
-%!error <PACKAGE must be a string> news (1)
-%!error <Package .* is not installed> news ("__NOT_A_VALID_PKG_NAME__")
-
+%!error <news: PACKAGE must be a string> news (1)
+%!error <news: package .* is not installed> news ("__NOT_A_VALID_PKG_NAME__")
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/miscellaneous/private/display_info_file.m	Wed Mar 06 16:43:33 2013 -0500
@@ -0,0 +1,59 @@
+## Copyright (C) 2013 Carnë Draug
+##
+## This file is part of Octave.
+##
+## Octave 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 3 of the License, or (at
+## your option) any later version.
+##
+## Octave 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 Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## news() and citation() are very much alike. They both do the same thing, just
+## for different files. This function does all the work.
+
+function display_info_file (func, package, file)
+
+  if (nargin != 3)
+    print_usage ();
+  endif
+
+  if (! ischar (package))
+    error ("%s: PACKAGE must be a string", func);
+  endif
+
+  if (strcmpi (package, "octave"))
+    octetcdir = octave_config_info ("octetcdir");
+    filepath  = fullfile (octetcdir, file);
+  else
+    installed = pkg ("list");
+    names     = cellfun (@(x) x.name, installed, "UniformOutput", false);
+    pos       = strcmpi (names, package);
+    if (! any (pos))
+      error ("%s: package '%s' is not installed.", func, package);
+    endif
+    filepath = fullfile (installed{pos}.dir, "packinfo", file);
+  endif
+
+  if (! exist (filepath, "file"))
+    if (strcmpi (package, "octave"))
+      error ("%s: broken installation -- unable to locate %s file", func, file);
+    else
+      error ("%s: unable to locate %s file for package %s", func, file, package);
+    endif
+  endif
+
+  fid = fopen (filepath, "r");
+  while (ischar (line = fgets (fid)))
+    puts (line);
+  endwhile
+  fclose (fid);
+
+endfunction
--- a/scripts/pkg/pkg.m	Thu Feb 28 02:04:24 2013 -0500
+++ b/scripts/pkg/pkg.m	Wed Mar 06 16:43:33 2013 -0500
@@ -423,7 +423,7 @@
         local_packages = prefix;
         global_packages = archprefix;
       elseif (length (files) >= 1 && nargout <= 2 && ischar (files{1}))
-        prefix = files{1};
+        prefix = tilde_expand (files{1});
         if (! exist (prefix, "dir"))
           [status, msg, msgid] = mkdir (prefix);
           if (status == 0)
@@ -434,7 +434,7 @@
         local_packages = prefix = canonicalize_file_name (prefix);
         user_prefix = true;
         if (length (files) >= 2 && ischar (files{2}))
-          archprefix = files{2};
+          archprefix = tilde_expand (files{2});
           if (! exist (archprefix, "dir"))
             [status, msg, msgid] = mkdir (archprefix);
             if (status == 0)
--- a/scripts/pkg/private/build.m	Thu Feb 28 02:04:24 2013 -0500
+++ b/scripts/pkg/private/build.m	Wed Mar 06 16:43:33 2013 -0500
@@ -35,7 +35,7 @@
     endif
   endif
   [builddir, status] = canonicalize_file_name (builddir);
-  if (! status)
+  if (status != 0)
     error ("cannot find directory %s", builddir);
   endif
   installdir = fullfile (builddir, "install");
--- a/scripts/pkg/private/copy_files.m	Thu Feb 28 02:04:24 2013 -0500
+++ b/scripts/pkg/private/copy_files.m	Wed Mar 06 16:43:33 2013 -0500
@@ -105,6 +105,7 @@
   packinfo_copy_file ("DESCRIPTION", "required", packdir, packinfo, desc, octfiledir);
   packinfo_copy_file ("COPYING", "required", packdir, packinfo, desc, octfiledir);
 
+  packinfo_copy_file ("CITATION", "optional", packdir, packinfo, desc, octfiledir);
   packinfo_copy_file ("NEWS", "optional", packdir, packinfo, desc, octfiledir);
   packinfo_copy_file ("ONEWS", "optional", packdir, packinfo, desc, octfiledir);
   packinfo_copy_file ("ChangeLog", "optional", packdir, packinfo, desc, octfiledir);
--- a/scripts/plot/__gnuplot_drawnow__.m	Thu Feb 28 02:04:24 2013 -0500
+++ b/scripts/plot/__gnuplot_drawnow__.m	Wed Mar 06 16:43:33 2013 -0500
@@ -296,13 +296,18 @@
     if (! __gnuplot_has_feature__ ("has_termoption_dashed"))
       ## If "set termoption dashed" isn't available add "dashed" option
       ## to the "set terminal ..." command, if it is supported.
-      if (any (strcmpi (term, {"aqua", "cgm", "eepic", "emf", "epslatex", \
-                               "fig", "pcl5", "mp", "next", "openstep", "pdf", \
-                               "pdfcairo", "pngcairo", "postscript", \
-                               "pslatex", "pstext", "svg", "tgif", "x11"})))
+      if (any (strcmp (term, {"aqua", "cgm", "eepic", "emf", "epslatex", \
+                              "fig", "pcl5", "mp", "next", "openstep", "pdf", \
+                              "pdfcairo", "pngcairo", "postscript", \
+                              "pslatex", "pstext", "svg", "tgif", "x11"})))
         term_str = [term_str " dashed"];
       endif
     end
+    if (any (strcmp (term, {"aqua", "wxt"})))
+      term_str = [term_str, " ", "dashlength 1"];
+    elseif (any (strcmp (term, {"epslatex", "postscript", "pslatex"})))
+      term_str = [term_str, " ", "dashlength 2"];
+    endif
 
     ## Work around the gnuplot feature of growing the x11 window and
     ## flickering window (x11, windows, & wxt) when the mouse and
--- a/scripts/plot/printd.m	Thu Feb 28 02:04:24 2013 -0500
+++ b/scripts/plot/printd.m	Wed Mar 06 16:43:33 2013 -0500
@@ -20,9 +20,11 @@
 
 ## -*- texinfo -*-
 ## @deftypefn  {Function File} {} printd (@var{obj}, @var{filename})
+## @deftypefnx {Function File} {@var{out_file} =} printd (@dots{})
 ##
 ## Convert any object acceptable to @code{disp} into the format
-## selected by the suffix of @var{filename}.
+## selected by the suffix of @var{filename}.  If the return argument
+## @var{out_file} is given, the name of the created file is returned.
 ##
 ## This function is intended to facilitate manipulation of the output
 ## of functions such as @code{stemleaf}.
@@ -32,7 +34,7 @@
 ## Author: Michael D. Godfrey <michaeldgodfrey@gmail.com>
 ## Description: Convert objects into other file formats.
 
-function printd (obj, filename)
+function pr_out = printd (obj, filename)
   ## Convert any object acceptable to disp() into various display formats.
   ## obj is the input object.
   ## filename is the output file (with required suffix).
@@ -79,19 +81,31 @@
   endswitch
   fclose (pf);
   delete (tempf);
-  printf ("%s file %s written\n", opt, filename);
+  pr_out =  sprintf ("%s file %s written\n", opt, filename);
 endfunction
 
 %!demo
-%!  r2 = ["stem step: 10, data: unsorted.\nHinges:    lo: 12, hi: 42\n";...
-%! "   1 | 22118";"   2 | 28";"   3 | 98";"   4 | 244";"   5 | 2"];
+%! r2 = char (
+%! "stem step: 10, data: unsorted.",
+%! "Hinges:    lo: 12, hi: 42"     ,
+%! "   1 | 22118"                  ,
+%! "   2 | 28"                     ,
+%! "   3 | 98"                     ,
+%! "   4 | 244"                    ,
+%! "   5 | 2"                      );
 %! printd (r2, "test_p.txt");
 %! system ("cat test_p.txt");
 %! delete ("test_p.txt");
 
 %!test
-%! r2 = ["stem step: 10, data: unsorted.\nHinges:    lo: 12, hi: 42\n";...
-%! "   1 | 22118";"   2 | 28";"   3 | 98";"   4 | 244";"   5 | 2"];
+%! r2 = char (
+%! "stem step: 10, data: unsorted.",
+%! "Hinges:    lo: 12, hi: 42"     ,
+%! "   1 | 22118"                  ,
+%! "   2 | 28"                     ,
+%! "   3 | 98"                     ,
+%! "   4 | 244"                    ,
+%! "   5 | 2"                      );
 %! printd (r2, "test_p.txt");
 %! r4 = fileread ("test_p.txt");
 %! delete ("test_p.txt");
--- a/scripts/plot/stemleaf.m	Thu Feb 28 02:04:24 2013 -0500
+++ b/scripts/plot/stemleaf.m	Wed Mar 06 16:43:33 2013 -0500
@@ -20,48 +20,82 @@
 
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} stemleaf (@var{x})
-## @deftypefnx {Function File} {@var{plot} =} stemleaf (@var{x}, @var{opt})
-##
+## @deftypefn  {Function File} {} stemleaf (@var{x}, @var{caption})
+## @deftypefnx {Function File} {} stemleaf (@var{x}, @var{caption}, @var{stem_sz})
+## @deftypefnx {Function File} {@var{plotstr} =} stemleaf (@dots{})
 ## Compute and display a stem and leaf plot of the vector @var{x}.
 ##
-## The @var{x} vector is converted to integer by @var{x} = @code{fix} (@var{x}). 
-## If an output argument is provided, the plot is returned as
-## an array of strings.  The first element is the heading
-## followed by an element for each stem.
-## The default stem step is 10.  
-## The @var{x} vector should be integers.  It will be treated so that
-## the last digit is the leaf value and the other digits are
-## the stems.
-## The leaf digits are not sorted.  If sorted leaf values
-## are wanted, use @code{sort} (@var{x}) before calling @code{stemleaf} (@var{x}).
-## The stem and leaf plot is described in: Ch. 3,
-## Exploratory Data Analysis by J. W. Tukey, Addison-Wesley, 1977.
+## The input @var{x} should be a vector of integers.  Any non-integer values
+## will be converted to integer by @code{@var{x} = fix (@var{x})}.  By default
+## each element of @var{x} will be plotted with the last digit of the element
+## as a leaf value and the remaining digits as the stem.  For example, 123
+## will be plotted with the stem @samp{12} and the leaf @samp{3}.  The second
+## argument, @var{caption}, should be a character array which provides a
+## description of the data.  It is included as a heading for the output.
+##
+## The optional input @var{stem_sz} sets the width of each stem.
+## The stem width is determined by @code{10^(@var{stem_sz} + 1)}.
+## The default stem width is 10.
+##
+## The output of @code{stemleaf} is composed of two parts: a
+## "Fenced Letter Display," followed by the stem-and-leaf plot itself.
+## The Fenced Letter Display is described in @cite{Exploratory Data Analysis}.
+## Briefly, the entries are as shown:
+##
+## @example
+## @group
+##
+##         Fenced Letter Display
+##   #% nx|___________________          nx = numel (x)
+##   M% mi|       md         |          mi median index, md median
+##   H% hi|hl              hu|   hs     hi lower hinge index, hl,hu hinges, hs h_spread
+##   1    |x(1)         x(nx)|          x(1), x(nx) first and last data value
+##              _______   
+##        ______|step |_______          step 1.5*h_spread
+##       f|ifl            ifh|          inner fence, lower and higher
+##        |nfl            nfh|          # data points within fences
+##       F|ofl            ofh|          outer fence, lower and higher
+##        |nFl            nFh|          # data points outside outer fences
+## @end group
+## @end example
+##
+## The stem-and-leaf plot shows on each line the stem value followed by the
+## string made up of the leaf digits.  If the @var{stem_sz} is not 1 the
+## successive leaf values are separated by ",".
+##
+## With no return argument, the plot is immediately displayed.  If an output
+## argument is provided, the plot is returned as an array of strings. 
+##
+## The leaf digits are not sorted.  If sorted leaf values are desired, use
+## @code{@var{xs} = sort (@var{x})} before calling @code{stemleaf (@var{xs})}.
+##
+## The stem and leaf plot and associated displays are described in: 
+## Ch. 3, @cite{Exploratory Data Analysis} by J. W. Tukey, Addison-Wesley, 1977.
 ## @seealso{hist, printd}
 ## @end deftypefn
 
 ## Author: Michael D. Godfrey <michaeldgodfrey@gmail.com>
 ## Description: Compute stem and leaf plot
 
-function varargout = stemleaf (x, stem_unit)
-  ## Compute and display a stem and leaf plot of the vector x. The x
-  ## vector is converted to integer by x = fix(x). If an output argument
+function plotstr = stemleaf (x, caption, stem_sz)
+  ## Compute and display a stem and leaf plot of the vector x.  The x
+  ## vector is converted to integer by x = fix(x).  If an output argument
   ## is provided, the plot is returned as an array of strings.  The
   ## first element is the heading followed by an element for each stem.
   ##
-  ## The default stem step is 10.  If stem_unit is provided the stem
-  ## step is set to: 10^(stem_unit+1) The x vector should be integers.
+  ## The default stem step is 10.  If stem_sz is provided the stem
+  ## step is set to: 10^(stem_sz+1).  The x vector should be integers.
   ## It will be treated so that the last digit is the leaf value and the
   ## other digits are the stems.
   ##
   ## When we first implemented stem and leaf plots in the early 1960's
   ## there was some discussion about sorting vs. leaving the leaf
-  ## entries in the original order in the data. We decided in favor or
-  ## sorting the leaves for most purposes. This is the choice
+  ## entries in the original order in the data.  We decided in favor of
+  ## sorting the leaves for most purposes.  This is the choice
   ## implemented in the SNAP/IEDA system that was written at that time.
   ##
-  ## SNAP/IEDA and particularly its stem and leaf plotting were further
-  ## developed by Hale Trotter, David Hoagland (at Princeton and MIT)
+  ## SNAP/IEDA, and particularly its stem and leaf plotting, were further
+  ## developed by Hale Trotter, David Hoagland (at Princeton and MIT),
   ## and others.
   ##
   ## Tukey, in EDA, generally uses unsorted leaves.  In addition, he
@@ -72,13 +106,13 @@
   ##
   ## I doubt if providing other options is worthwhile.  The code can
   ## quite easily be modified to provide specific display results.  Or,
-  ## the returned output string can be edited. The returned output is an
+  ## the returned output string can be edited.  The returned output is an
   ## array of strings with each row containing a line of the plot
   ## preceded by the lines of header text as the first row.  This
   ## facilitates annotation.
   ##
   ## Note that the code has some added complexity due to the need to
-  ## distinguish both + and - 0 stems. The +- stem values are essential
+  ## distinguish both + and - 0 stems.  The +- stem values are essential
   ## for all plots which span 0. After dealing with +-0 stems, the added
   ## complexity of putting +- data values in the correct stem is minor,
   ## but the sign of 0 leaves must be checked.  And, the cases where the
@@ -87,232 +121,473 @@
   ## The fact that IEEE floating point defines +- 0 helps make this
   ## easier.
   ##
-  ##
   ## Michael D. Godfrey   January 2013
 
-  ## More could be implemented for better data scaling. And, of course,
+  ## More could be implemented for better data scaling.  And, of course,
   ## other options for the kinds of plots described by Tukey could be
-  ## provided. This may best be left to users.
+  ## provided.  This may best be left to users.
 
-  if (nargin >= 2)
-    stem_step = 10^(stem_unit+1);
-  else
-    stem_step = 10;
+  if (nargin < 2 || nargin > 3)
+    print_usage ();
   endif
-  if (any (x == int32 (x)) == 0)
-    printf ('Input vector truncated to integer values.\n')
-    x = fix (x);
+
+  if (! isvector (x))
+    error ("stemleaf: X must be a vector");
   endif
 
-  ## Avoid use of int32 due to:
+  if (isinteger (x))
+    ## Avoid use of integers because rounding rules do not use fix():
+    ## Example: floor (int32 (-44)/10) == -4, floor (int32 (-46)/10) = -5 !!!
+    x = single (x);
+  elseif (isfloat (x))
+    xint = fix (x);
+    if (any (x != xint))
+      warning ("stemleaf: X truncated to integer values");
+      x = xint;
+    endif
+  else
+    error ("stemleaf: X must be a numeric vector");
+  endif
 
-  ##  floor (int32 (-44)/10) == -4 and floor (int32 (-46)/10) = -5 !!!
-  ##  x  = sort (fix (x));  % User can decide about sorting x.
-  ##  x  = fix (x);
-  ##  %Adjust scale if too small.
-  ##  while any(abs((fix(x) - x)) >= abs(x/100))
-  ##    x =10*x;
-  ##  endwhile
+  if (! ischar (caption))
+    error ("stemleaf: CAPTION must be a character array");
+  endif
+
+  if (nargin == 2)
+    stem_step = 10;
+  else
+    if (isscalar (stem_sz) && stem_sz >= 0 && isreal (stem_sz))
+      stem_sz = fix (stem_sz);
+      stem_step = 10^(stem_sz+1);
+    else
+      error ("stemleaf: STEM_SZ must be a real integer >= 0");
+    endif
+  endif
 
   ## Note that IEEE 754 states that -+ 0 should compare equal. This has
   ## led to C sort (and therefore Octave) treating them as equal.  Thus,
-  ## sort([ -1 0 -0 1]) yields: -1 0 -0 1. and, sort([-1 -0 0 1])
-  ## yields: -1 -0 0 1. This means that stem-and-leaf plotting cannot
+  ## sort([-1 0 -0 1]) yields [-1 0 -0 1], and sort([-1 -0 0 1])
+  ## yields: [-1 -0 0 1].  This means that stem-and-leaf plotting cannot
   ## rely on sort to order the data as needed for display.
+  ## This also applies to min()/max() so these routines can't be relied
+  ## upon if the max or min is -+ 0.
+
+  ## Compute hinges and fences based on ref: EDA pgs. 33 and 44.
+  ## Note that these outlier estimates are meant to be "distribution free".
 
-  if (all((sort(x) == x)) == 1)
-    hsort = 'sorted.';
-  else
-    hsort = 'unsorted.';
-  endif
-  nx = max (size (x));
+  nx = numel (x);
+  xs = sort (x);                # Note that sort preserves -0
+  mdidx = fix ((nx + 1)/2);     # median index
+  hlidx = fix ((mdidx + 1)/2);  # lower hinge index
+  huidx = fix (nx + 1 - hlidx); # upper hinge index
+  md = xs(mdidx);               # median
+  hl = xs(hlidx);               # lower hinge
+  hu = xs(huidx);               # upper hinge
+  h_spread = hu - hl;           # h_spread: difference between hinges
+  step = 1.5*h_spread;          # step: 1.5 * h_spread
+  i_fence_l = hl - step;        # inner fences: outside hinges + step
+  o_fence_l = hl - 2*step;      # outer fences: outside hinges + 2*step
+  i_fence_h = hu + step;
+  o_fence_h = hu + 2*step;
+  n_out_l   = sum (x<i_fence_l) - sum (x<o_fence_l);
+  n_out_h   = sum (x>i_fence_h) - sum (x>o_fence_h);
+  n_far_l   = sum (x<o_fence_l);
+  n_far_h   = sum (x>o_fence_h);
+
+  # display table similar to that on pg. 33
+  plot_out = sprintf ("       Data: %s", caption);
+  plot_out = [plot_out; sprintf(" ")];
+  plot_out = [plot_out; sprintf("         Fenced Letter Display")];
+  plot_out = [plot_out; sprintf(" ")];
+  plot_out = [plot_out; sprintf("     #%3d|___________________", nx)];
+  plot_out = [plot_out; sprintf("     M%3d|       %5d      |", mdidx, md)];
+  plot_out = [plot_out; sprintf("     H%3d|%5d        %5d|   %d", hlidx, hl, hu, h_spread)];
+  plot_out = [plot_out; sprintf("     1   |%5d        %5d|", xs(1), xs(nx))];
+  plot_out = [plot_out; sprintf("               _______")];   
+  plot_out = [plot_out; sprintf("         ______|%5d|_______",step)];
+  plot_out = [plot_out; sprintf("        f|%5d        %5d|", i_fence_l, i_fence_h)];
+  plot_out = [plot_out; sprintf("         |%5d        %5d|  out", n_out_l, n_out_h)];
+  plot_out = [plot_out; sprintf("        F|%5d        %5g|", o_fence_l, o_fence_h)];
+  plot_out = [plot_out; sprintf("         |%5d        %5d|  far",n_far_l,n_far_h)];
+  plot_out = [plot_out; " "];
+
   ## Determine stem values
-  if (min(x) < 0)
-    if (signbit(max(x)) == 0)     # max is positive
-      stems = [fix(min(x)/stem_step)-1 : -1 -0];
-      stems = [stems 0 : fix(max(x)/stem_step)+1 ];
-    else
-      if (max(x) < 0)
-        stems = [(fix(min(x)/stem_step)-1) : fix(max(x)/stem_step)];
+  min_x = min (x);
+  max_x = max (x);
+  if (min_x > 0)      # all stems > 0
+    stems = [fix(min(x)/stem_step) : (fix(max(x)/stem_step)+1)];
+  elseif (max_x < 0)  # all stems < 0
+    stems = [(fix(min_x/stem_step)-1) : fix(max_x/stem_step)];
+  elseif (min_x < 0 && max_x > 0)  # range crosses 0
+    stems = [(fix(min_x/stem_step)-1) : -0, 0 : fix(max_x/stem_step)+1 ];
+  else   # one endpoint is a zero which may be +0 or -0
+    if (min_x == 0)
+      if (any (x == 0 & signbit (x)))
+        min_x = -0;
       else
-        stems = [(fix(min(x)/stem_step)-1) : -1 -0];
-        stems = [stems 0 : fix(max(x)/stem_step)];
+        min_x = +0;
       endif
     endif
-  else                            # All stems are > 0
-    stems = [fix(min(x)/stem_step) : fix(max(x)/stem_step) + 1];
-  endif
-  ##stems
-  ##x
-  nstems = max(size(stems));
-  ## compute hinges at +- 1.5 * quartiles
-  ## this requires sorted data!
-  xs = sort (x);                   # Note that sort preserves -0
-  threeh = 1.5;
-  two    = 2.0;
-  j  = idivide(nx, 4, "fix") + 1;  # Use F95 truncation.
-  k  = nx - j + 1;
-  hl = xs (j);
-  hu = xs (k);
-  if ( (nx + 1) ==  (4 * j) ) 
-    hl = (xs (j + 1) + hl) / two;
-    hu = (xs (k - 1) + hu) / two;
+    if (max_x == 0)
+      if (any (x == 0 & ! signbit (x)))
+        max_x = +0;
+      else
+        max_x = -0;
+      endif
+    endif
+    stems = [];
+    if (signbit (min_x))
+      stems = [(fix(min_x/stem_step)-1) : -0];
+    endif
+    if (! signbit (max_x))
+      stems = [stems, 0 : fix(max_x/stem_step)+1 ];
+    endif
   endif
 
-  ##     ::::::::  determine h-spread (dh) and fences  ::::::::
-  dh = hu - hl;
-  fu = hu + threeh * dh;
-  fl = hl - threeh * dh;
-
-  ##     ::::::::  find value adjacent to lower fence  ::::::::
-  for i = 1:j
-    if ( xs (i) >= fl ) 
-      continue; 
-    endif
-  endfor
-  ilow = i;
-  xlo = xs (ilow);
-
-  ##     :::::::: find value adjacent to upper fence  ::::::::
-  for  i = 1:j
-    if ( xs (nx -i + 1) <= fu )
-      continue;
-    endif
-  endfor
-
-  ihi = nx - i + 1;
-  xhi = xs (ihi);
-
-  ## Heading for output:
-  plot_out = "";
-  plot_out = [plot_out sprintf("stem step: %i, data: %s\nHinges:    lo: %g, hi: %g\n",
-                               stem_step, hsort, xlo, xhi)];
-
-  ## This may appear to be a good place to use vectorization using the
-  ## stem and data arrays but the necessary special case treatment of 0
-  ## and -0 seems to result in little reduction of complexity, and since
-  ## this algorithm is for small data vectors only there would be
-  ## practically no performance improvement.
-
+  ## Vectorized version provided by Rik Wehbring (rik@octave.org)
   ## Determine leaves for each stem:
-  for kx = 2:nstems
-    line_out = "";
-    steml    = "";
-    ## Build a string of leaf digits for stem(kx) if stem(kx) <= 0, or
-    ## stem(kx-1) if stem(kx) > 0
+  new_line  = 1;
+  for kx = 2: numel (stems)
 
-    ## stems -+ 0 have to be handled as special cases.
-    for xi = 1:nx
-      if(signbit(stems(kx)) != 0)
-        t1 = ((x(xi) <= stems(kx)*10) && (x(xi) > (stems(kx-1)*10)));
-      else
-        t1 = ((x(xi) < stems(kx)*10) && (x(xi) >= (stems(kx-1)*10)));
-      endif
-      ## Special tests for stem -+ 0
-      if ((stems(kx) == 0) && signbit(stems(kx)) && (x(xi) == 0)) && !signbit(x(xi))
-        t1 = 0;
-      endif
-      if ((stems(kx-1) == 0) && !signbit(stems(kx-1)) && (x(xi) == 0)) && signbit(x(xi))
-        t1 = 0;
-      endif
-      ## Create line as a string
-      if t1
-        if (stems(kx) <= 0)
-          xz =  abs (x(xi) - stems(kx)*10);
-        else
-          xz =  abs (x(xi) - stems(kx-1)*10);
-        endif
-        if ((stems(kx) == 0) && signbit(stems(kx)))
-          steml = [steml sprintf("%d", abs(x(xi) - stems(kx)*10))];
-        else
-          steml = [steml sprintf("%d", xz)];
-        endif
-      endif    %  t1
-    endfor    % xi = 1:nx
-
-    ## Set correct -0
-    if ((stems(kx) == 0) && signbit(stems(kx)))
-      line_out = [line_out sprintf("  -0 | %s",  steml)];  % -0 stem.
+    stem_sign = signbit (stems(kx));
+    if (stems(kx) <= 0)
+      idx = ((x <= stems(kx)*stem_step) & (x > (stems(kx-1)*stem_step))
+              & (signbit (x) == stem_sign));
+      xlf = abs (x(idx) - stems(kx)*stem_step);
     else
-      if( stems(kx) < 0)
-        line_out = [line_out sprintf("%4d | %s", stems(kx), steml)];
-      else
-        if stems(kx) > 0
-          line_out = [line_out sprintf("%4d | %s", stems(kx-1), steml)];
+      idx = ((x < stems(kx)*stem_step) & (x >= (stems(kx-1)*stem_step))
+              & (signbit (x) == stem_sign));
+      xlf = abs (x(idx) - stems(kx-1)*stem_step);
+    endif
+    ## Convert leaves to a string
+    if (stem_step == 10)
+      lf_str = sprintf ("%d", xlf);
+    else
+      lf_str = "";
+      if (! isempty (xlf))
+        lf_str = sprintf ("%d", xlf(1));
+        if (numel (xlf) > 1)
+          lf_str = [lf_str sprintf(",%d", xlf(2:end))];
         endif
       endif
     endif
-    plot_out = [plot_out; line_out];
-  endfor    % kx = 2:nstems
+
+    ## Set correct -0
+    if (stems(kx) == 0 && signbit (stems(kx)))
+      line = sprintf ("  -0 | %s",  lf_str);  # -0 stem.
+    elseif (stems(kx) < 0)
+      line = sprintf ("%4d | %s", stems(kx), lf_str);
+    elseif (stems(kx) > 0)
+      line = sprintf ("%4d | %s", stems(kx-1), lf_str);
+    else
+      line = "";
+    endif
+
+    if (! isempty (lf_str) || stems(kx) == 0 || stems(kx-1) == 0)
+      plot_out = [plot_out; line];
+      new_line = 1;
+    else
+      if (new_line == 1) 
+        plot_out = [plot_out; "     :"];  # just print one : if no leaves
+        new_line = 0;
+      endif
+    endif
+
+  endfor    # kx = 2: numel (stems)
+
   if (nargout == 0)
-    rows = size (plot_out)(1);
-    cols = size (plot_out)(2);
-    for k = 1:rows
-      printf("%s\n", plot_out(k,1:cols));
-    endfor
+    disp (plot_out);
   else
-    varargout{1} = plot_out;
+    plotstr = plot_out;
   endif
+
 endfunction
 
+
 %!demo
 %! ## Unsorted plot:
 %! x = [-22 12 -28 52  39 -2 12 10 11 11 42 38 44 18 44];
-%! stemleaf (x, 0);
+%! stemleaf (x, "Unsorted plot");
 
 %!demo
 %! ## Sorted leaves:
 %! x = [-22 12 -28 52  39 -2 12 10 11 11 42 38 44 18 44];
-%! y = sort(x);
-%! stemleaf (y, 0);
+%! y = sort (x);
+%! stemleaf (y, "Sorted leaves");
 
 %!demo
-%! ## More data (sorted)
-%! x = [-22 12 -28 52  39 -2 12 10 11 11 42 38 44 18 44 37 113 124 37 48 127 36 29 31 125 139 131 115 105 132 104 123 35 113 122 42 117 119 58 109 23 105 63 27 44 105 99 41 128 121 116 125 32 61 37 127 29 113 121 58 114 126 53 114 96 25 109 7 31 141 46 -13 71 43 117 116 27 7 68 40 31 115 124 42 128 52 71 118 117 38 27 106 33 117 116 111 40 119 47 105 57 122 109 124 115 43 120 43 27 27 18 28 48 125 107 114 34 133 45 120 30 127 31 116 146 21 23 30 10 20 21 30 0 100 110 1 20 0 ];
-%! y = sort(x);
-%! stemleaf (y, 0);
+%! ## Sorted leaves (large dataset):
+%! x = [-22 12 -28 52  39 -2 12 10 11 11 42 38 44 18 44 37 113 124 37 48 127  \
+%!      36 29 31 125 139 131 115 105 132 104 123 35 113 122 42 117 119 58 109 \
+%!      23 105 63 27 44 105 99 41 128 121 116 125 32 61 37 127 29 113 121 58  \
+%!      114 126 53 114 96 25 109 7 31 141 46 -13 71 43 117 116 27 7 68 40 31  \
+%!      115 124 42 128 52 71 118 117 38 27 106 33 117 116 111 40 119 47 105 57\
+%!      122 109 124 115 43 120 43 27 27 18 28 48 125 107 114 34 133 45 120 30 \
+%!      127 31 116 146 21 23 30 10 20 21 30 0 100 110 1 20 0];
+%! y = sort (x);
+%! stemleaf (y, "Sorted leaves (large dataset)");
+
+%!demo
+%! ## Gaussian leaves:
+%! x = fix (30 * randn (300,1));
+%! stemleaf (x);
 
 %!test
 %! ## test minus to plus
-%! x = [-22 12 -28 52  39 -2 12 10 11 11 42 38 44 18 44 37 113 124 37 48 127 36 29 31 125 139 131 115 105 132 104 123 35 113 122 42 117 119 58 109 23 105 63 27 44 105 99 41 128 121 116 125 32 61 37 127 29 113 121 58 114 126 53 114 96 25 109 7 31 141 46 -13 71 43 117 116 27 7 68 40 31 115 124 42 128 52 71 118 117 38 27 106 33 117 116 111 40 119 47 105 57 122 109 124 115 43 120 43 27 27 18 28 48 125 107 114 34 133 45 120 30 127 31 116 146 21 23 30 10 20 21 30 0 100 110 1 20 0 ];
-%! x = sort(x);
-%! r2 = ["stem step: 10, data: sorted.\nHinges:    lo: 30, hi: 116\n";...
-%! "  -2 | 82";"  -1 | 3";"  -0 | 2";"   0 | 00177";...
-%! "   1 | 00112288";"   2 | 001133577777899";...
-%! "   3 | 000111123456777889";"   4 | 00122233344456788";...
-%! "   5 | 223788";"   6 | 138";"   7 | 11";"   8 | ";...
-%! "   9 | 69";"  10 | 04555567999";"  11 | 0133344455566667777899";...
-%! "  12 | 0011223444555677788";"  13 | 1239";"  14 | 16"];
-%! rx = stemleaf (x, 0);
-%! assert(r2, rx);
+%! x = [-22 12 -28 52  39 -2 12 10 11 11 42 38 44 18 44 37 113 124 37 48 127  \
+%!      36 29 31 125 139 131 115 105 132 104 123 35 113 122 42 117 119 58 109 \
+%!      23 105 63 27 44 105 99 41 128 121 116 125 32 61 37 127 29 113 121 58  \
+%!      114 126 53 114 96 25 109 7 31 141 46 -13 71 43 117 116 27 7 68 40 31  \
+%!      115 124 42 128 52 71 118 117 38 27 106 33 117 116 111 40 119 47 105 57\
+%!      122 109 124 115 43 120 43 27 27 18 28 48 125 107 114 34 133 45 120 30 \
+%!      127 31 116 146 21 23 30 10 20 21 30 0 100 110 1 20 0];
+%! x = sort (x);
+%! rexp = char (
+%! "       Data: test minus to plus"    ,
+%! " "                                  ,
+%! "         Fenced Letter Display"     ,
+%! " "                                  ,
+%! "     #138|___________________"      ,     
+%! "     M 69|          52      |"      ,     
+%! "     H 35|   30          116|   86" ,
+%! "     1   |  -28          146|"      ,
+%! "               _______"             ,
+%! "         ______|  129|_______"      ,
+%! "        f|  -99          245|"      ,     
+%! "         |    0            0|  out" ,
+%! "        F| -228          374|"      ,
+%! "         |    0            0|  far" ,
+%! " "                                  ,
+%! "  -2 | 82"                          ,
+%! "  -1 | 3"                           ,
+%! "  -0 | 2"                           ,
+%! "   0 | 00177"                       ,
+%! "   1 | 00112288"                    ,
+%! "   2 | 001133577777899"             ,
+%! "   3 | 000111123456777889"          ,
+%! "   4 | 00122233344456788"           ,
+%! "   5 | 223788"                      ,
+%! "   6 | 138"                         ,
+%! "   7 | 11"                          ,
+%! "     : "                            ,
+%! "   9 | 69"                          ,
+%! "  10 | 04555567999"                 ,
+%! "  11 | 0133344455566667777899"      ,
+%! "  12 | 0011223444555677788"         ,
+%! "  13 | 1239"                        ,
+%! "  14 | 16"                          );
+%! r = stemleaf (x, "test minus to plus", 0);
+%! assert (r, rexp);
+
 %!test
 %! ## positive values above 0
-%! x = [22 12 28 52  39 12 11 11 42 38 44 18 44 ];
-%! r2 = ["stem step: 10, data: unsorted.\nHinges:    lo: 12, hi: 42\n";...
-%! "   1 | 22118";"   2 | 28";"   3 | 98";"   4 | 244";"   5 | 2"];
-%! rx = stemleaf (x, 0);
-%! assert(r2, rx);
+%! x = [5 22 12 28 52 39 12 11 11 42 38 44 18 44];
+%! rexp = char (
+%! "       Data: positive values above 0",
+%! " "                                   ,
+%! "         Fenced Letter Display"      ,
+%! " "                                   ,
+%! "     # 14|___________________"       ,     
+%! "     M  7|          22      |"       ,     
+%! "     H  4|   12           42|   30"  ,
+%! "     1   |    5           52|"       ,
+%! "               _______"              ,
+%! "         ______|   45|_______"       ,
+%! "        f|  -33           87|"       ,     
+%! "         |    0            0|  out"  ,
+%! "        F|  -78          132|"       ,
+%! "         |    0            0|  far"  ,
+%! " "                                   ,
+%! "   0 | 5"                            ,
+%! "   1 | 22118"                        ,
+%! "   2 | 28"                           ,
+%! "   3 | 98"                           ,
+%! "   4 | 244"                          ,
+%! "   5 | 2"                            );
+%! r = stemleaf (x, "positive values above 0");
+%! assert (r, rexp);
+
 %!test
 %! ## negative values below 0
-%! x = [22 12 28 52  39 12 11 11 42 38 44 18 44];
+%! x = [5 22 12 28 52 39 12 11 11 42 38 44 18 44];
 %! x = -x;
-%! r2 = ["stem step: 10, data: unsorted.\nHinges:    lo: -42, hi: -12\n";...
-%! "  -5 | 2";"  -4 | 244";"  -3 | 98";"  -2 | 28";"  -1 | 22118"];
-%! rx = stemleaf (x, 0);
-%! assert(r2, rx);
+%! rexp = char (
+%! "       Data: negative values below 0",
+%! " "                                   ,
+%! "         Fenced Letter Display"      ,
+%! " "                                   ,
+%! "     # 14|___________________"       ,     
+%! "     M  7|         -28      |"       ,     
+%! "     H  4|  -42          -12|   30"  ,
+%! "     1   |  -52           -5|"       ,
+%! "               _______"              ,
+%! "         ______|   45|_______"       ,
+%! "        f|  -87           33|"       ,     
+%! "         |    0            0|  out"  ,
+%! "        F| -132           78|"       ,
+%! "         |    0            0|  far"  ,
+%! " "                                   ,
+%! "  -5 | 2"                            ,
+%! "  -4 | 244"                          ,
+%! "  -3 | 98"                           ,
+%! "  -2 | 28"                           ,
+%! "  -1 | 22118"                        ,
+%! "  -0 | 5"                            );
+%! r = stemleaf (x, "negative values below 0");
+%! assert (r, rexp);
+
 %!test
 %! ## positive values from 0
-%! x = [22 12 28 52  39 2 12 0 11 11 42 38 44 18 44];
-%! r2 = ["stem step: 10, data: unsorted.\nHinges:    lo: 11, hi: 42\n";...
-%! "   0 | 20";"   1 | 22118";"   2 | 28";"   3 | 98";"   4 | 244";"   5 | 2"];
-%! rx = stemleaf (x, 0);
-%! assert(r2, rx);
+%! x = [22 12 28 52 39 2 12 0 11 11 42 38 44 18 44];
+%! rexp = char (
+%! "       Data: positive values from 0",
+%! " "                                  ,
+%! "         Fenced Letter Display"     ,
+%! " "                                  ,
+%! "     # 15|___________________"      ,     
+%! "     M  8|          22      |"      ,     
+%! "     H  4|   11           42|   31" ,
+%! "     1   |    0           52|"      ,
+%! "               _______"             ,
+%! "         ______|   46|_______"      ,
+%! "        f|  -35           88|"      ,     
+%! "         |    0            0|  out" ,
+%! "        F|  -82          135|"      ,
+%! "         |    0            0|  far" ,
+%! " "                                  ,
+%! "   0 | 20"                          ,
+%! "   1 | 22118"                       ,
+%! "   2 | 28"                          ,
+%! "   3 | 98"                          ,
+%! "   4 | 244"                         ,
+%! "   5 | 2"                           );
+%! r = stemleaf (x, "positive values from 0");
+%! assert (r, rexp);
+
 %!test
 %! ## negative values from 0
-%! x = [22 12 28 52  39 2 12 0 11 11 42 38 44 18 44];
+%! x = [22 12 28 52 39 2 12 0 11 11 42 38 44 18 44];
 %! x = -x;
-%! r2 = ["stem step: 10, data: unsorted.\nHinges:    lo: -42, hi: -11\n";...
-%! "  -5 | 2";"  -4 | 244";"  -3 | 98";"  -2 | 28";"  -1 | 22118";"  -0 | 20"];
-%! rx = stemleaf (x, 0);
-%! assert(r2, rx);
+%! rexp = char (
+%! "       Data: negative values from 0",
+%! " "                                  ,
+%! "         Fenced Letter Display"     ,
+%! " "                                  ,
+%! "     # 15|___________________"      ,     
+%! "     M  8|         -22      |"      ,     
+%! "     H  4|  -42          -11|   31" ,
+%! "     1   |  -52            0|"      ,
+%! "               _______"             ,
+%! "         ______|   46|_______"      ,
+%! "        f|  -88           35|"      ,     
+%! "         |    0            0|  out" ,
+%! "        F| -135           82|"      ,
+%! "         |    0            0|  far" ,
+%! " "                                  ,
+%! "  -5 | 2"                           ,
+%! "  -4 | 244"                         ,
+%! "  -3 | 98"                          ,
+%! "  -2 | 28"                          ,
+%! "  -1 | 22118"                       ,
+%! "  -0 | 20"                          );
+%! r = stemleaf (x, "negative values from 0");
+%! assert (r, rexp);
+
+%!test
+%! ## both +0 and -0 present
+%! x = [-9 -7 -0 0 -0];
+%! rexp = char (
+%! "       Data: both +0 and -0 present",
+%! " "                                  ,
+%! "         Fenced Letter Display"     ,
+%! " "                                  ,
+%! "     #  5|___________________"      ,     
+%! "     M  3|           0      |"      ,     
+%! "     H  2|   -7            0|   7"  ,
+%! "     1   |   -9            0|"      ,
+%! "               _______"             ,
+%! "         ______|   10|_______"      ,
+%! "        f|  -17           10|"      ,     
+%! "         |    0            0|  out" ,
+%! "        F|  -28           21|"      ,
+%! "         |    0            0|  far" ,
+%! " "                                  ,
+%! "  -0 | 9700"                        ,
+%! "   0 | 0"                           );
+%! r = stemleaf (x, "both +0 and -0 present");
+%! assert (r, rexp);
 
+%!test
+%! ## both <= 0 and -0 present
+%! x = [-9 -7 0 -0];
+%! rexp = char (
+%! "       Data: both <= 0 and -0 present",
+%! " "                                    ,
+%! "         Fenced Letter Display"       ,
+%! " "                                    ,
+%! "     #  4|___________________"        ,     
+%! "     M  2|          -7      |"        ,     
+%! "     H  1|   -9            0|   9"    ,
+%! "     1   |   -9            0|"        ,
+%! "               _______"               ,
+%! "         ______|   13|_______"        ,
+%! "        f|  -22           13|"        ,     
+%! "         |    0            0|  out"   ,
+%! "        F|  -36           27|"        ,
+%! "         |    0            0|  far"   ,
+%! " "                                    ,
+%! "  -0 | 970"                           ,
+%! "   0 | 0"                             );
+%! r = stemleaf (x, "both <= 0 and -0 present");
+%! assert (r, rexp);
+
+%!test
+%! ##   Example from EDA: Chevrolet Prices pg. 30
+%! x = [150 250 688 695 795 795 895 895 895 1099 1166 1333 1499 1693 1699 1775 1995];
+%! rexp = char (
+%! "       Data: Chevrolet Prices EDA pg.30",
+%! " "                                      ,
+%! "         Fenced Letter Display"         ,
+%! " "                                      ,
+%! "     # 17|___________________"          ,          
+%! "     M  9|         895      |"          ,
+%! "     H  5|  795         1499|   704"    ,
+%! "     1   |  150         1995|"          ,
+%! "               _______"                 ,
+%! "         ______| 1056|_______"          ,
+%! "        f| -261         2555|"          ,
+%! "         |    0            0|  out"     ,
+%! "        F|-1317         3611|"          ,
+%! "         |    0            0|  far"     ,
+%! " "                                      ,
+%! "   1 | 50"                              ,
+%! "   2 | 50"                              ,
+%! "     :"                                 ,
+%! "   6 | 88,95"                           ,
+%! "   7 | 95,95"                           ,
+%! "   8 | 95,95,95"                        ,
+%! "     :"                                 ,
+%! "  10 | 99"                              ,
+%! "  11 | 66"                              ,
+%! "     :"                                 ,
+%! "  13 | 33"                              ,
+%! "  14 | 99"                              ,
+%! "     :"                                 ,
+%! "  16 | 93,99"                           ,
+%! "  17 | 75"                              ,
+%! "     :"                                 ,
+%! "  19 | 95"                              );
+%! r = stemleaf (x, "Chevrolet Prices EDA pg.30", 1);
+%! assert (r, rexp);
+
+## Test input validation
+%!error stemleaf ()
+%!error stemleaf (1, 2, 3, 4)
+%!error <X must be a vector> stemleaf (ones (2,2), "")
+%!warning <X truncated to integer values> tmp = stemleaf ([0 0.5 1],"");
+%!error <X must be a numeric vector> stemleaf ("Hello World", "data")
+%!error <CAPTION must be a character array> stemleaf (1, 2)
+%!error <STEM_SZ must be a real integer> stemleaf (1, "", ones (2,2))
+%!error <STEM_SZ must be a real integer> stemleaf (1, "", -1)
+%!error <STEM_SZ must be a real integer> stemleaf (1, "", 1+i)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/testfun/__have_feature__.m	Wed Mar 06 16:43:33 2013 -0500
@@ -0,0 +1,34 @@
+## Copyright (C) 2013 John W. Eaton
+##
+## This file is part of Octave.
+##
+## Octave 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 3 of the License, or (at
+## your option) any later version.
+##
+## Octave 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 Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {Function File} {} __have_feature__ (feature)
+## Undocumented internal function.
+## @end deftypefn
+
+function retval = __have_feature__ (feature)
+  features = octave_config_info ("features");
+  if (iscellstr (feature))
+    retval = (all (isfield (features, feature))
+              && cellfun (@(x) features.(x), feature));
+  elseif (ischar (feature))
+    retval = isfield (features, feature) && features.(feature);
+  else
+    retval = false;
+  endif
+endfunction
--- a/scripts/testfun/test.m	Thu Feb 28 02:04:24 2013 -0500
+++ b/scripts/testfun/test.m	Wed Mar 06 16:43:33 2013 -0500
@@ -463,15 +463,16 @@
       ## Strip comment any comment from testif line before looking for features
       __feat_line = strtok (__code(1:__e), '#%'); 
       __feat = regexp (__feat_line, '\w+', 'match');
-      __have_feat = strfind (octave_config_info ("DEFS"), __feat); 
-      if (any (cellfun ("isempty", __have_feat)))
+      __feat = strrep (__feat, "HAVE_", "");
+      __have_feat = __have_feature__ (__feat);
+      if (__have_feat)
+        __istest = 1;
+        __code = __code(__e + 1 : end);
+      else
         __xskip++;
         __istest = 0;
         __code = ""; # Skip the code.
         __msg = sprintf ("%sskipped test\n", __signal_skip);
-      else
-        __istest = 1;
-        __code = __code(__e + 1 : end);
       endif
 
 ### TEST
@@ -679,19 +680,6 @@
   endif
 endfunction
 
-### Test for test for missing features
-%!testif OCTAVE_SOURCE
-%! ## This test should be run
-%! assert (true);
-
-### Disable this test to avoid spurious skipped test for "make check"
-% !testif HAVE_FOOBAR
-% ! ## missing feature. Fail if this test is run
-% ! error ("Failed missing feature test");
-
-### Test for a known failure
-%!xtest error ("This test is known to fail")
-
 ### example from toeplitz
 %!shared msg1,msg2
 %! msg1="C must be a vector";
--- a/test/classes/classes.tst	Thu Feb 28 02:04:24 2013 -0500
+++ b/test/classes/classes.tst	Wed Mar 06 16:43:33 2013 -0500
@@ -309,13 +309,13 @@
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 %% Test overloaded vertcat() for the Snork class
-%% See bug #38170 (http://savannah.gnu.org/bugs/?38170)
+%% See bug #38128 (http://savannah.gnu.org/bugs/?38128)
 %!test   s = [s1; s2];  assert (isa (s, 'Snork') && isequal (s.gick, [x1; x2]));
 %!xtest  s = [s1; x2];  assert (isa (s, 'Snork') && isequal (s.gick, [x1; x2]));
 %!xtest  s = [x1; s2];  assert (isa (s, 'Snork') && isequal (s.gick, [x1; x2]));
 
 %% Test overloaded horzcat() for the Snork class
-%% See bug #38170 (http://savannah.gnu.org/bugs/?38170)
+%% See bug #38128 (http://savannah.gnu.org/bugs/?38128)
 %!test   s = [s1 s2];  assert (isa (s, 'Snork') && isequal (s.gick, [x1 x2]));
 %!xtest  s = [s1 x2];  assert (isa (s, 'Snork') && isequal (s.gick, [x1 x2]));
 %!xtest  s = [x1 s2];  assert (isa (s, 'Snork') && isequal (s.gick, [x1 x2]));
--- a/test/range.tst	Thu Feb 28 02:04:24 2013 -0500
+++ b/test/range.tst	Wed Mar 06 16:43:33 2013 -0500
@@ -72,3 +72,38 @@
 %!assert ([ r ; uint32(z)          ], uint32(expect))
 %!assert ([ r ; uint64(z)          ], uint64(expect))
 
+## Test corner cases of ranges (base and limit)
+
+%!shared r, rrev, rneg
+%! r = -0:3;
+%! rrev = 3:-1:-0;
+%! rneg = -3:-0;
+
+%!assert (full (r), [-0 1 2 3])
+%!assert (signbit (full (r)), logical ([1 0 0 0]))
+%!assert (r(1), -0)
+%!assert (signbit (r(1)), true)
+%!assert (signbit (r(1:2)), logical ([1 0]))
+%!assert (signbit (r(2:-1:1)), logical ([0 1]))
+%!assert (signbit (r([2 1 1 3])), logical ([0 1 1 0]))
+
+%!assert (full (rrev), [3 2 1 -0])
+%!assert (signbit (full (rrev)), logical ([0 0 0 1]))
+%!assert (rrev(4), -0)
+%!assert (signbit (rrev(4)), true)
+%!assert (signbit (rrev(3:4)), logical ([0 1]))
+%!assert (signbit (rrev(4:-1:3)), logical ([1 0]))
+%!assert (signbit (rrev([1 4 4 2])), logical ([0 1 1 0]))
+
+%!assert (min (r), -0)
+%!assert (signbit (min (r)), true)
+%!assert (min (rrev), -0)
+%!assert (signbit (min (rrev)), true)
+
+%!assert (max (rneg), -0)
+%!assert (signbit (max (rneg)), true)
+
+%!assert (sort (r, "descend"), [3 2 1 -0])
+%!assert (signbit (sort (r, "descend")), logical ([0 0 0 1]))
+%!assert (signbit (sort (rrev, "ascend")), logical ([1 0 0 0]))
+