changeset 16155:0259254a3ccc classdef

maint: periodic merge of default to classdef * lex.h, lex.ll, parse.h, oct-parse.yy: Resolve conflicts by adapting classdef changes to new octave_parser and lexical_feedback classes.
author John W. Eaton <jwe@octave.org>
date Thu, 28 Feb 2013 02:04:24 -0500
parents fc3cb570ac46 (current diff) aa5e1e8dce66 (diff)
children a8f9eb92fa6e
files libinterp/Makefile.am libinterp/interp-core/pt-jit.cc libinterp/interpfcn/symtab.cc libinterp/octave-value/ov-usr-fcn.cc libinterp/octave-value/ov.cc libinterp/octave.cc libinterp/parse-tree/lex.h libinterp/parse-tree/lex.ll libinterp/parse-tree/oct-parse.yy libinterp/parse-tree/parse.h libinterp/parse-tree/pt-id.cc libinterp/parse-tree/pt-id.h libinterp/parse-tree/token.h test/classes/classes.tst test/classes/module.mk
diffstat 87 files changed, 3423 insertions(+), 3162 deletions(-) [+]
line wrap: on
line diff
--- a/.hgsubstate	Mon Feb 11 15:45:26 2013 -0500
+++ b/.hgsubstate	Thu Feb 28 02:04:24 2013 -0500
@@ -1,1 +1,1 @@
-0eef0a2a05e22ac8ef2aad06dda200f7def83396 gnulib-hg
+c75939cb6254833830cdbeaf84e666360a34ccf1 gnulib-hg
--- a/.hgtags	Mon Feb 11 15:45:26 2013 -0500
+++ b/.hgtags	Thu Feb 28 02:04:24 2013 -0500
@@ -74,3 +74,4 @@
 faefa1bea8ddae3cab170afdeab68d3d15c4e623 ss-3-7-2
 0000000000000000000000000000000000000000 ss-3-7-2
 23a7661e529ae9bfc91693618f8c314c31f695ca ss-3-7-2
+cc5a7d1233f3acea85648baeb754fc0e8f225225 rc-3-6-4-2
--- a/bootstrap.conf	Mon Feb 11 15:45:26 2013 -0500
+++ b/bootstrap.conf	Thu Feb 28 02:04:24 2013 -0500
@@ -36,6 +36,7 @@
   floorf
   fnmatch
   fopen
+  fpucw
   fseek
   ftell
   getcwd
--- a/build-aux/common.mk	Mon Feb 11 15:45:26 2013 -0500
+++ b/build-aux/common.mk	Thu Feb 28 02:04:24 2013 -0500
@@ -3,12 +3,15 @@
 AWK = @AWK@
 export AWK
 
-SED = @SED@
-export SED
+GREP = @GREP@
+export GREP
 
 FIND = @FIND@
 export FIND
 
+SED = @SED@
+export SED
+
 PERL = @PERL@
 export PERL
 
@@ -113,7 +116,7 @@
 DEPEND_FLAGS = @DEPEND_FLAGS@
 DEPEND_EXTRA_SED_PATTERN = @DEPEND_EXTRA_SED_PATTERN@
 INCLUDE_DEPS = @INCLUDE_DEPS@
-# ifeq ($(INCLUDE_DEPS),false)
+# ifeq ($(INCLUDE_DEPS),no)
 #   omit_deps = true;
 # endif
 
@@ -278,9 +281,9 @@
 
 ## Order matters, at least on some systems (Cygwin, for example).
 SPARSE_XLIBS = \
-    $(CHOLMOD_LIBS) $(UMFPACK_LIBS) \
-    $(AMD_LIBS) $(CAMD_LIBS) $(COLAMD_LIBS) \
-    $(CCOLAMD_LIBS) $(CXSPARSE_LIBS)
+  $(CHOLMOD_LIBS) $(UMFPACK_LIBS) \
+  $(AMD_LIBS) $(CAMD_LIBS) $(COLAMD_LIBS) \
+  $(CCOLAMD_LIBS) $(CXSPARSE_LIBS)
 
 TERM_LIBS = @TERM_LIBS@
 
@@ -696,42 +699,13 @@
   -e "s|%AWK%|${AWK}|g" \
   -e "s|%FIND%|${FIND}|g" \
   -e "s|%SED%|${SED}|g" \
-  -e "s|%library_path_var%|${library_path_var}|g" \
-  -e "s|%liboctinterp%|${SHLPRE}octinterp.${SHLEXT}|g" \
-  -e "s|%liboctave%|${SHLPRE}octave.${SHLEXT}|g" \
-  -e "s|%ldpreloadsep%|${ldpreloadsep}|g" \
-  -e "s|%srcdir%|${srcdir}|" \
-  -e "s|%top_srcdir%|${top_srcdir}|" \
   -e "s|%abs_top_srcdir%|${abs_top_srcdir}|" \
   -e "s|%builddir%|$(shell pwd)|" > $@-t
 $(simple_move_if_change_rule)
 endef
 
-define do_script_install
-$(top_srcdir)/build-aux/mkinstalldirs $(DESTDIR)$(fcnfiledir)/$(script_sub_dir)
-for f in $(FCN_FILES); do \
-  fbase=`basename $$f`; \
-  rm -f $(DESTDIR)$(fcnfiledir)/$(script_sub_dir)/$$fbase; \
-  $(INSTALL_DATA) $$f $(DESTDIR)$(fcnfiledir)/$(script_sub_dir)/$$fbase; \
-done
-$(top_srcdir)/mkpkgadd $(DESTDIR)$(fcnfiledir)/$(script_sub_dir) > $(DESTDIR)$(fcnfiledir)/$(script_sub_dir)/PKG_ADD.t
-if [ -n "`cat $(DESTDIR)$(fcnfiledir)/$(script_sub_dir)/PKG_ADD.t`" ]; then \
-  $(INSTALL_DATA) $(DESTDIR)$(fcnfiledir)/$(script_sub_dir)/PKG_ADD.t $(DESTDIR)$(fcnfiledir)/$(script_sub_dir)/PKG_ADD ; \
-else \
-  rm -f $(DESTDIR)$(fcnfiledir)/$(script_sub_dir)/PKG_ADD.t ; \
-fi
-endef
-
-define do_script_uninstall
-for f in $(FCN_FILES_NO_DIR); \
-  do rm -f $(DESTDIR)$(fcnfiledir)/$(script_sub_dir)/$$f; \
-done
-rm -f $(DESTDIR)$(fcnfiledir)/$(script_sub_dir)/PKG_ADD
--rmdir $(DESTDIR)$(fcnfiledir)/$(script_sub_dir)
-endef
-
 define test-file-commands
-( echo "## DO NOT EDIT!  Generated automatically from $(<F) by Make."; grep '^%!' $< ) > $@-t
+( echo "## DO NOT EDIT!  Generated automatically from $(<F) by Make."; $(GREP) '^%!' $< ) > $@-t
 mv $@-t $@
 endef
 
--- a/build-aux/find-files-with-tests.sh	Mon Feb 11 15:45:26 2013 -0500
+++ b/build-aux/find-files-with-tests.sh	Thu Feb 28 02:04:24 2013 -0500
@@ -1,6 +1,7 @@
 #! /bin/sh
 
 set -e
+GREP=${GREP:-grep}
 SED=${SED:-sed}
 
 srcdir="$1"
@@ -13,7 +14,7 @@
   else
     file="$srcdir/$arg"
   fi
-  if [ "`grep -l '^%!' $file`" ]; then
+  if [ "`$GREP -l '^%!' $file`" ]; then
     echo "$file" | $SED "s,\\$srcdir/,,";
   fi
 done
--- a/configure.ac	Mon Feb 11 15:45:26 2013 -0500
+++ b/configure.ac	Thu Feb 28 02:04:24 2013 -0500
@@ -97,6 +97,7 @@
 
 ## Programs used in Makefiles.
 AC_PROG_AWK
+AC_PROG_GREP
 OCTAVE_PROG_FIND
 OCTAVE_PROG_SED
 OCTAVE_PROG_PERL
@@ -180,24 +181,24 @@
 ### matrix classes.  This slows down some operations a bit, so it is turned off
 ### by default.
 
-BOUNDS_CHECKING=false
+BOUNDS_CHECKING=no
 AC_ARG_ENABLE([bounds-check],
   [AS_HELP_STRING([--enable-bounds-check],
     [enable bounds checking for indexing in internal array classes])],
-  [if test "$enableval" = yes; then BOUNDS_CHECKING=true; fi], [])
-if $BOUNDS_CHECKING; then
+  [if test "$enableval" = yes; then BOUNDS_CHECKING=yes; fi], [])
+if test $BOUNDS_CHECKING = yes; then
   AC_DEFINE(BOUNDS_CHECKING, 1, [Define to 1 to use internal bounds checking.])
 fi
 
 ### Use Octave's built-in memory allocator rather than straightforward malloc.
 ### Disabled by default.
 
-USE_OCTAVE_ALLOCATOR=false
+USE_OCTAVE_ALLOCATOR=no
 AC_ARG_ENABLE([octave-allocator],
   [AS_HELP_STRING([--enable-octave-allocator],
     [use the obsolete octave_allocator class for many of Octave's objects (mostly octave_value types).  You probably do NOT want to enable this feature.])],
-  [if test "$enableval" = yes; then USE_OCTAVE_ALLOCATOR=true; fi], [])
-if $USE_OCTAVE_ALLOCATOR; then
+  [if test "$enableval" = yes; then USE_OCTAVE_ALLOCATOR=yes; fi], [])
+if test $USE_OCTAVE_ALLOCATOR = yes; then
   AC_DEFINE(USE_OCTAVE_ALLOCATOR, 1,
     [Define to 1 to use octave_allocator class.])
 fi
@@ -206,12 +207,12 @@
 ### for thread-safe behavior but incurs a significant slowdown, and is thus
 ### disabled by default.
 
-USE_ATOMIC_REFCOUNT=false
+USE_ATOMIC_REFCOUNT=no
 AC_ARG_ENABLE([atomic-refcount],
   [AS_HELP_STRING([--enable-atomic-refcount],
     [use atomic operations for internal reference counting.  This is required for thread-safe behavior but does not by itself make Octave internals thread safe.])],
-  [if test "$enableval" = yes; then USE_ATOMIC_REFCOUNT=true; fi], [])
-if $USE_ATOMIC_REFCOUNT; then
+  [if test "$enableval" = yes; then USE_ATOMIC_REFCOUNT=yes; fi], [])
+if test $USE_ATOMIC_REFCOUNT = yes; then
   AC_DEFINE(USE_ATOMIC_REFCOUNT, 1,
     [Define to 1 to use atomic operations for reference counting.])
 fi
@@ -232,13 +233,13 @@
 
 ### If possible, use a 64-bit integer type for array dimensions and indexing.
 
-USE_64_BIT_IDX_T=false
+USE_64_BIT_IDX_T=no
 OCTAVE_IDX_TYPE=int
 AC_ARG_ENABLE(64,
   [AS_HELP_STRING([--enable-64],
     [(EXPERIMENTAL) use 64-bit integers for array dimensions and indexing])],
-  [if test "$enableval" = yes; then USE_64_BIT_IDX_T=true; fi], [])
-if $USE_64_BIT_IDX_T; then
+  [if test "$enableval" = yes; then USE_64_BIT_IDX_T=yes; fi], [])
+if test $USE_64_BIT_IDX_T = yes; then
   AC_CHECK_SIZEOF([void *])
   AC_CHECK_SIZEOF([int])
   AC_CHECK_SIZEOF([long])
@@ -251,18 +252,18 @@
     else
       warn_64_bit="no suitable type found for octave_idx_type so disabling 64-bit features"
       OCTAVE_CONFIGURE_WARNING([warn_64_bit])
-      USE_64_BIT_IDX_T=false
+      USE_64_BIT_IDX_T=no
     fi
   else
     warn_64_bit="pointers are not 64-bits wide; disabling 64-bit features"
     OCTAVE_CONFIGURE_WARNING([warn_64_bit])
-    USE_64_BIT_IDX_T=false
+    USE_64_BIT_IDX_T=no
   fi
 fi
 AC_SUBST(OCTAVE_IDX_TYPE)
 AC_DEFINE_UNQUOTED(OCTAVE_IDX_TYPE, [$OCTAVE_IDX_TYPE],
   [Define to the type of octave_idx_type (64 or 32 bit signed integer).])
-if $USE_64_BIT_IDX_T; then
+if test $USE_64_BIT_IDX_T = yes; then
   AC_DEFINE(USE_64_BIT_IDX_T, 1,
     [Define to 1 if using 64-bit integers for array dimensions and indexing.])
 fi
@@ -350,7 +351,7 @@
 ### Determine the compiler flag necessary to create dependencies
 
 ## Assume GCC.
-INCLUDE_DEPS=true
+INCLUDE_DEPS=yes
 DEPEND_FLAGS="-M"
 DEPEND_EXTRA_SED_PATTERN=""
 if test "$GCC" != yes; then
@@ -363,11 +364,11 @@
     ;;
     *-*-mingw*)
       if test $have_msvc = no; then
-        INCLUDE_DEPS=false
+        INCLUDE_DEPS=no
       fi
     ;;
     *)
-      INCLUDE_DEPS=false
+      INCLUDE_DEPS=no
     ;;
   esac
 fi
@@ -466,12 +467,12 @@
 ### Test whether the compiler supports OpenMP.  This is experimental so disable
 ### it by default.  Enable it with the flag --enable-openmp.
 
-USE_OPENMP=false
+USE_OPENMP=no
 AC_ARG_ENABLE([openmp],
   [AS_HELP_STRING([--enable-openmp],
     [(EXPERIMENTAL) use OpenMP SMP multi-threading])],
-  [if test "$enableval" = yes; then USE_OPENMP=true; fi], [])
-if $USE_OPENMP; then
+  [if test "$enableval" = yes; then USE_OPENMP=yes; fi], [])
+if test $USE_OPENMP = yes; then
   case $host_os in
     mingw* | cygwin* | *-gnu*)
       OCTAVE_CHECK_OPENMP(-fopenmp)
@@ -538,18 +539,18 @@
 AC_F77_DUMMY_MAIN
 AC_F77_WRAPPERS
 
-F77_TOLOWER=true
-F77_APPEND_UNDERSCORE=true
-F77_APPEND_EXTRA_UNDERSCORE=true
+F77_TOLOWER=yes
+F77_APPEND_UNDERSCORE=yes
+F77_APPEND_EXTRA_UNDERSCORE=yes
 
 case $ac_cv_f77_mangling in
-  "upper case") F77_TOLOWER=false ;;
+  "upper case") F77_TOLOWER=no ;;
 esac
 case $ac_cv_f77_mangling in
-  "no underscore") F77_APPEND_UNDERSCORE=false ;;
+  "no underscore") F77_APPEND_UNDERSCORE=no ;;
 esac
 case $ac_cv_f77_mangling in
-  "no extra underscore") F77_APPEND_EXTRA_UNDERSCORE=false ;;
+  "no extra underscore") F77_APPEND_EXTRA_UNDERSCORE=no ;;
 esac
 
 case $canonical_host_type in
@@ -593,7 +594,7 @@
 
 OCTAVE_CHECK_SIZEOF_FORTRAN_INTEGER
 if test $octave_cv_sizeof_fortran_integer = no; then
-  if $USE_64_BIT_IDX_T; then
+  if test $USE_64_BIT_IDX_T = yes; then
     case $F77 in
       *gfortran*)
         case $F77_INTEGER_8_FLAG in
@@ -703,12 +704,12 @@
 
 ### Check for the LLVM library
 
-build_jit=false
+build_jit=no
 AC_ARG_ENABLE([jit],
   [AS_HELP_STRING([--enable-jit],
     [(EXPERIMENTAL) enable JIT compiler])],
   [if test "$enableval" = yes; then
-     build_jit=true
+     build_jit=yes
    fi],
   [])
 
@@ -717,7 +718,7 @@
 LLVM_LDFLAGS=
 LLVM_LIBS=
 
-if test $build_jit = true; then
+if test $build_jit = yes; then
 
   ## Find llvm-config program from environment variable or by searching
   AC_ARG_VAR([LLVM_CONFIG], [path to llvm-config utility])
@@ -763,7 +764,7 @@
   if test -z "$warn_llvm"; then
     AC_DEFINE(HAVE_LLVM, 1, [Define to 1 if LLVM is available.])
   else
-    build_jit=false
+    build_jit=no
     LLVM_CPPFLAGS=
     LLVM_CXXFLAGS=
     LLVM_LDFLAGS=
@@ -816,16 +817,16 @@
 
 ## Check for the multithreaded FFTW library.
 ## Fallback to singlethreaded if not found or disabled
-build_fftw_threads=true
+build_fftw_threads=yes
 AC_ARG_ENABLE([fftw-threads],
   [AS_HELP_STRING([--disable-fftw-threads],
     [disable Multi-threaded FFTW])],
   [if test "$enableval" = no; then
-     build_fftw_threads=false
+     build_fftw_threads=no
    fi],
   [])
 
-if test $build_fftw_threads = true; then
+if test $build_fftw_threads = yes; then
   OCTAVE_CHECK_FFTW_THREADS(fftw3, fftw_plan_with_nthreads)
   OCTAVE_CHECK_FFTW_THREADS(fftw3f, fftwf_plan_with_nthreads)
 fi
@@ -861,18 +862,18 @@
 if test -z "$warn_curl"; then
   ## Additional check on cURL library that was found
   AC_CACHE_CHECK([for CURLOPT_DIRLISTONLY in curl/curl.h],
-    [octave_cv_header_define_curlopt_dirlistonly],
+    [octave_cv_curl_has_curlopt_dirlistonly],
     [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
       #include <curl/curl.h>
       ]], [[
       curl_easy_setopt ((CURL*)NULL, CURLOPT_DIRLISTONLY, 0);
       ]])],
-      [octave_cv_header_define_curlopt_dirlistonly=no],
-      [octave_cv_header_define_curlopt_dirlistonly=yes])
+      [octave_cv_curl_has_curlopt_dirlistonly=yes],
+      [octave_cv_curl_has_curlopt_dirlistonly=no])
     ])
-  if test $octave_cv_header_define_curlopt_dirlistonly = yes; then
+  if test $octave_cv_curl_has_curlopt_dirlistonly = no; then
     AC_DEFINE(CURLOPT_DIRLISTONLY, CURLOPT_FTPLISTONLY,
-      [Define to the legacy option name if using an older version of cURL.])]
+      [Define to the legacy option name if using an older version of cURL.])
   fi
 fi
 LIBS="$save_LIBS"
@@ -977,24 +978,24 @@
 
 ### Check for list of libraries needed for native graphics renderer.
 
-native_graphics=true
+native_graphics=yes
 warn_freetype=""
 
-check_opengl=false
+check_opengl=no
 AC_ARG_WITH([opengl],
   [AS_HELP_STRING([--without-opengl],
     [don't use OpenGL libraries, disable native graphics])],
   [if test x"$withval" = x"no"; then
-     native_graphics=false
+     native_graphics=no
      warn_opengl="--without-opengl specified.  Native graphics will be disabled."
      OCTAVE_CONFIGURE_WARNING([warn_opengl])
    else
-     check_opengl=true
+     check_opengl=yes
    fi],
-  [check_opengl=true])
+  [check_opengl=yes])
 
 ## Check for OpenGL library
-if $check_opengl; then
+if test $check_opengl = yes; then
   OCTAVE_CHECK_LIB_OPENGL
 fi
 
@@ -1002,8 +1003,8 @@
 GRAPHICS_CFLAGS=
 
 if test -z "$OPENGL_LIBS"; then
-  if $check_opengl; then
-    native_graphics=false
+  if test $check_opengl = yes; then
+    native_graphics=no
     warn_fltk_opengl="OpenGL libs (GL and GLU) not found.  Native graphics will be disabled."
     OCTAVE_CONFIGURE_WARNING([warn_fltk_opengl])
   fi
@@ -1030,7 +1031,7 @@
 
   if test -n "$warn_freetype"; then
     OCTAVE_CONFIGURE_WARNING([warn_freetype])
-    native_graphics=false
+    native_graphics=no
   fi
 
   ## Check for fontconfig library
@@ -1047,7 +1048,7 @@
   fi
 
   if test -n "$warn_fontconfig"; then
-    native_graphics=false
+    native_graphics=no
     OCTAVE_CONFIGURE_WARNING([warn_fontconfig])
   fi
 
@@ -1085,7 +1086,7 @@
   warn_fltk_opengl=""
 
   if test "$FLTK_CONFIG" = no; then
-    native_graphics=false
+    native_graphics=no
     warn_fltk_config="FLTK config script not found.  Native graphics will be disabled."
     OCTAVE_CONFIGURE_WARNING([warn_fltk_config])
   else
@@ -1121,7 +1122,7 @@
       GRAPHICS_CFLAGS="$FLTK_CFLAGS"
       GRAPHICS_LIBS="$FLTK_LDFLAGS"
     else
-      native_graphics=false
+      native_graphics=no
       OCTAVE_CONFIGURE_WARNING([warn_fltk_opengl])
     fi
   fi
@@ -1154,15 +1155,15 @@
 LT_INIT([disable-static dlopen win32-dll])
 
 if test x"$enable_shared" = x"yes"; then
-  SHARED_LIBS=true
+  SHARED_LIBS=yes
 else
-  SHARED_LIBS=false
+  SHARED_LIBS=no
 fi
 
 if test x"$enable_static" = x"yes"; then
-  STATIC_LIBS=true
+  STATIC_LIBS=yes
 else
-  STATIC_LIBS=false
+  STATIC_LIBS=no
 fi
 
 XTRA_CRUFT_SH_LDFLAGS=
@@ -1244,7 +1245,7 @@
 fi
 
 if test $ax_blas_f77_func_ok = no; then
-  if $USE_64_BIT_IDX_T && test $ax_blas_integer_size_ok = no; then
+  if test $USE_64_BIT_IDX_T = yes && test $ax_blas_integer_size_ok = no; then
     ## Attempt to be more informative.
     AC_MSG_ERROR([BLAS doesn't seem to support 64-bit integers.  This is incompatible with --enable-64.])
   else
@@ -1432,13 +1433,13 @@
   [AS_HELP_STRING([--disable-dl],
     [disable loading of dynamically linked modules])],
   [case $enableval in
-     yes) ENABLE_DYNAMIC_LINKING=true ;;
-     no) ENABLE_DYNAMIC_LINKING=false ;;
+     yes) ENABLE_DYNAMIC_LINKING=yes ;;
+     no) ENABLE_DYNAMIC_LINKING=no ;;
      *) AC_MSG_ERROR([bad value $enableval for --enable-dl]) ;;
    esac],
-  [ENABLE_DYNAMIC_LINKING=true])
-
-if ! $STATIC_LIBS && ! $SHARED_LIBS; then
+  [ENABLE_DYNAMIC_LINKING=no])
+
+if test $STATIC_LIBS = no && test $SHARED_LIBS = no; then
   AC_MSG_ERROR([You can't disable building both static AND shared libraries!])
 fi
 
@@ -1472,7 +1473,7 @@
 OCTGRAPHICS_DLL_DEFS=
 library_path_var=LD_LIBRARY_PATH
 ldpreloadsep=" "
-BUILD_COMPILED_AUX_PROGRAMS=false
+BUILD_COMPILED_AUX_PROGRAMS=no
 case $canonical_host_type in
   *-*-386bsd* | *-*-netbsd*)
     SH_LD=ld
@@ -1525,7 +1526,7 @@
     ldpreloadsep=":"
   ;;
   *-*-mingw*)
-    BUILD_COMPILED_AUX_PROGRAMS=true
+    BUILD_COMPILED_AUX_PROGRAMS=yes
     if test $have_msvc = yes; then
       DL_LDFLAGS="-shared"
       CPICFLAG=
@@ -1545,7 +1546,6 @@
       fi
       NO_OCT_FILE_STRIP=true
       library_path_var=PATH
-      NO_OCT_FILE_STRIP=true
       ## Extra compilation flags.
       CRUFT_DLL_DEFS="-DCRUFT_DLL"
       OCTAVE_DLL_DEFS="-DOCTAVE_DLL"
@@ -1567,7 +1567,7 @@
   ;;
 
   *-*-msdosmsvc)
-    BUILD_COMPILED_AUX_PROGRAMS=true
+    BUILD_COMPILED_AUX_PROGRAMS=yes
     DL_LDFLAGS="-shared"
     CPICFLAG=
     CXXPICFLAG=
@@ -1586,7 +1586,6 @@
     fi
     NO_OCT_FILE_STRIP=true
     library_path_var=PATH
-    NO_OCT_FILE_STRIP=true
     ## Extra compilation flags.
     CRUFT_DLL_DEFS="-DCRUFT_DLL"
     OCTAVE_DLL_DEFS="-DOCTAVE_DLL"
@@ -1666,7 +1665,7 @@
 esac
 
 AM_CONDITIONAL([AMCOND_BUILD_COMPILED_AUX_PROGRAMS],
-  [test x$BUILD_COMPILED_AUX_PROGRAMS = xtrue])
+  [test $BUILD_COMPILED_AUX_PROGRAMS = yes])
 
 AC_MSG_NOTICE([defining FPICFLAG to be $FPICFLAG])
 AC_MSG_NOTICE([defining CPICFLAG to be $CPICFLAG])
@@ -1745,13 +1744,13 @@
   [AS_HELP_STRING([--enable-link-all-dependencies],
     [link Octave and its shared libraries with all dependencies, not just those immediately referenced (should not be needed on most systems)])],
   [case $enableval in
-     yes) link_all_deps=true ;;
-     no)  link_all_deps=false ;;
+     yes) link_all_deps=yes ;;
+     no)  link_all_deps=no ;;
      *) AC_MSG_ERROR([bad value $enableval for --enable-link-all-depenencies])
      ;;
    esac],
-  [link_all_deps=false])
-AM_CONDITIONAL([AMCOND_LINK_ALL_DEPS], [test $link_all_deps = true])
+  [link_all_deps=no])
+AM_CONDITIONAL([AMCOND_LINK_ALL_DEPS], [test $link_all_deps = yes])
 
 ## Dynamic linking is now enabled only if we are building shared
 ## libs and some API for dynamic linking has been detected.
@@ -1762,35 +1761,35 @@
 LD_CXX='$(CXX)'
 RDYNAMIC_FLAG=
 DL_API_MSG=""
-dlopen_api=false
-shl_load_api=false
-loadlibrary_api=false
-dyld_api=false
-
-if $SHARED_LIBS || $ENABLE_DYNAMIC_LINKING; then
+dlopen_api=no
+shl_load_api=no
+loadlibrary_api=no
+dyld_api=no
+
+if test $SHARED_LIBS = yes || test $ENABLE_DYNAMIC_LINKING = yes; then
 
   case $lt_cv_dlopen in
     dlopen)
-      dlopen_api=true
+      dlopen_api=yes
       DL_API_MSG="(dlopen)"
       AC_DEFINE(HAVE_DLOPEN_API, 1,
         [Define to 1 if your system has dlopen, dlsym, dlerror, and dlclose for dynamic linking.])
       OCTAVE_CXX_FLAG([-rdynamic], [RDYNAMIC_FLAG=-rdynamic])
     ;;
     shl_load)
-      shl_load_api=true
+      shl_load_api=yes
       DL_API_MSG="(shl_load)"
       AC_DEFINE(HAVE_SHL_LOAD_API, 1,
         [Define to 1 if your system has shl_load and shl_findsym for dynamic linking.])
     ;;
     LoadLibrary)
-      loadlibrary_api=true
+      loadlibrary_api=yes
       DL_API_MSG="(LoadLibrary)"
       AC_DEFINE(HAVE_LOADLIBRARY_API, 1,
         [Define to 1 if your system has LoadLibrary for dynamic linking.])
     ;;
     dyld)
-      dyld_api=true
+      dyld_api=yes
       DL_API_MSG="(dyld)"
       AC_DEFINE(HAVE_DYLD_API, 1,
         [Define to 1 if your system has dyld for dynamic linking.])
@@ -1801,21 +1800,25 @@
   AC_SUBST(DL_LIBS)
 
   ## Disable dynamic linking if capability is not present.
-  if $dlopen_api || $shl_load_api || $loadlibrary_api || $dyld_api; then
-    :  # some form of dynamic linking present
+  if test $dlopen_api = yes \
+      || test $shl_load_api = yes \
+      || test $loadlibrary_api = yes \
+      || test $dyld_api = yes; then
+    # some form of dynamic linking present
+    ENABLE_DYNAMIC_LINKING=yes
   else
-    ENABLE_DYNAMIC_LINKING=false
+    ENABLE_DYNAMIC_LINKING=no
   fi
 fi
 
-if $ENABLE_DYNAMIC_LINKING; then
+if test $ENABLE_DYNAMIC_LINKING = yes; then
   AC_DEFINE(ENABLE_DYNAMIC_LINKING, 1, [Define to 1 if using dynamic linking.])
 fi
 
 AM_CONDITIONAL([AMCOND_ENABLE_DYNAMIC_LINKING],
-  [test x"$ENABLE_DYNAMIC_LINKING" = x"true"])
-
-if $SHARED_LIBS; then
+  [test $ENABLE_DYNAMIC_LINKING = yes])
+
+if test $SHARED_LIBS = yes; then
   LIBOCTINTERP="-loctinterp$SHLLINKEXT"
   LIBOCTAVE="-loctave$SHLLINKEXT"
 else
@@ -1895,8 +1898,8 @@
 ## C headers
 
 dnl Use multiple AC_CHECKs to avoid line continuations '\' in list
-AC_CHECK_HEADERS([curses.h direct.h dlfcn.h floatingpoint.h grp.h])
-AC_CHECK_HEADERS([ieeefp.h inttypes.h locale.h memory.h ncurses.h])
+AC_CHECK_HEADERS([curses.h direct.h dlfcn.h floatingpoint.h fpu_control.h])
+AC_CHECK_HEADERS([grp.h ieeefp.h inttypes.h locale.h memory.h ncurses.h])
 AC_CHECK_HEADERS([poll.h pthread.h pwd.h sunmath.h sys/ioctl.h])
 AC_CHECK_HEADERS([sys/param.h sys/poll.h sys/resource.h ])
 AC_CHECK_HEADERS([sys/select.h sys/utsname.h termcap.h])
@@ -2211,17 +2214,17 @@
 
 GXX_EXTRA_FLAGS="-Wall -W -Wshadow -Wold-style-cast -Wformat -Wpointer-arith -Wwrite-strings -Wcast-align -Wcast-qual"
 
-try_extra_warning_flags=true
+try_extra_warning_flags=yes
 
 AC_ARG_ENABLE([extra-warning-flags],
   [AS_HELP_STRING([--disable-extra-warning-flags],
     [don't add -Wall, -W, -Wshadow, and -Wold-style-cast options to CFLAGS and CXXFLAGS])],
   [if test "$enableval" = no; then
-     try_extra_warning_flags=false
+     try_extra_warning_flags=no
    fi],
   [])
 
-if $try_extra_warning_flags; then
+if test $try_extra_warning_flags = yes; then
   for flag in $GCC_EXTRA_FLAGS; do
     OCTAVE_CC_FLAG([$flag], [
       WARN_CFLAGS="$WARN_CFLAGS $flag";
@@ -2238,17 +2241,17 @@
 
 GXX_STRICT_FLAGS="-Wconversion -Weffc++"
 
-try_strict_warning_flags=false
+try_strict_warning_flags=no
 
 AC_ARG_ENABLE([strict-warning-flags],
   [AS_HELP_STRING([--enable-strict-warning-flags],
     [add extra strict warning options to CFLAGS and CXXFLAGS])],
   [if test "$enableval" = yes; then
-     try_strict_warning_flags=true
+     try_strict_warning_flags=yes
    fi],
   [])
 
-if $try_strict_warning_flags; then
+if test $try_strict_warning_flags = yes; then
   for flag in $GCC_STRICT_FLAGS; do
     OCTAVE_CC_FLAG([$flag], [
       WARN_CFLAGS="$WARN_CFLAGS $flag";
@@ -2266,12 +2269,12 @@
 
 ### Check for Java.
 
-build_java=true
+build_java=yes
 AC_ARG_ENABLE([java],
   [AS_HELP_STRING([--disable-java],
     [disable Java interface])],
   [if test "$enableval" = no; then
-     build_java=false
+     build_java=no
    fi],
   [])
 
@@ -2302,10 +2305,10 @@
 JAVA_LIBS=
 
 ## Fake loop so that "break" can be used to skip code blocks.
-while test $build_java = true
+while test $build_java = yes
 do
   ## Unset build_java.  Variable is set only if all configuration tests pass.
-  build_java=false
+  build_java=no
 
   ## Warn if JAVA_HOME is unset.  It is *strongly* advised to specify JAVA_HOME.
   if test -z "$JAVA_HOME"; then
@@ -2384,7 +2387,7 @@
   ## the required paths to compile and link against JDK.
   case $host_os in
     msdosmsvc)
-      build_java=true
+      build_java=yes
       JAVA_LIBS=-ladvapi32
       AC_DEFINE(HAVE_JAVA, 1,
         [Define to 1 if Java is available and is at least version 1.5])
@@ -2392,7 +2395,7 @@
     ;;
     mingw*)
       if test $have_msvc = yes; then
-        build_java=true
+        build_java=yes
         JAVA_LIBS=-ladvapi32
         AC_DEFINE(HAVE_JAVA, 1,
           [Define to 1 if Java is available and is at least version 1.5])
@@ -2509,11 +2512,11 @@
 
   ## Verify jni.h include file exists.
   JNI_PATH=`echo $JAVA_CPPFLAGS | sed -e 's/-I//g'`
-  have_jni=false
+  have_jni=no
   for dir in $JNI_PATH; do 
-    if test -f "${dir}/jni.h"; then have_jni=true; break; fi
+    if test -f "${dir}/jni.h"; then have_jni=yes; break; fi
   done
-  if test $have_jni = true; then
+  if test $have_jni = yes; then
     AC_MSG_RESULT([$dir])
   else
     AC_MSG_RESULT([not found])
@@ -2522,13 +2525,13 @@
   fi
 
   ## Passed all configuration tests.  A workable Java installation was found.
-  build_java=true
+  build_java=yes
   AC_DEFINE(HAVE_JAVA, 1,
     [Define to 1 if Java is available and is at least version 1.5])
   break
 done
 
-AM_CONDITIONAL([AMCOND_HAVE_JAVA], [test $build_java = true])
+AM_CONDITIONAL([AMCOND_HAVE_JAVA], [test $build_java = yes])
 AC_SUBST(JAVA)
 AC_SUBST(JAVAC)
 AC_SUBST(JAR)
@@ -2982,15 +2985,15 @@
 
 OCTAVE_CONFIGURE_WARNING_SUMMARY
 
-if $ENABLE_DYNAMIC_LINKING; then
-  if test $SHARED_LIBS = false; then
+if test $ENABLE_DYNAMIC_LINKING = yes; then
+  if test $SHARED_LIBS = no; then
     AC_MSG_WARN([You used --enable-dl but not --enable-shared.])
     AC_MSG_WARN([Are you sure that is what you want to do?])
     warn_msg_printed=true
   fi
 fi
 
-if $USE_64_BIT_IDX_T; then
+if test $USE_64_BIT_IDX_T = yes; then
   AC_MSG_WARN([])
   AC_MSG_WARN([You used the EXPERIMENTAL --enable-64 option.])
   AC_MSG_WARN([Are you sure that is what you want to do?])
@@ -3007,7 +3010,7 @@
   warn_msg_printed=true
 fi
 
-if $USE_OPENMP; then
+if test $USE_OPENMP = yes; then
   AC_MSG_WARN([])
   AC_MSG_WARN([You used the EXPERIMENTAL --enable-openmp option.])
   AC_MSG_WARN([Are you sure that is what you want to do?])
@@ -3020,7 +3023,7 @@
   warn_msg_printed=true
 fi
 
-if test $native_graphics = false; then
+if test $native_graphics != yes; then
   AC_MSG_WARN([])
   AC_MSG_WARN([I didn't find the necessary libraries to compile native])
   AC_MSG_WARN([graphics.  It isn't necessary to have native graphics,])
@@ -3031,7 +3034,7 @@
 fi
 
 if test -n "$warn_gnuplot"; then
-  if $native_graphics; then
+  if test $native_graphics = yes; then
     AC_MSG_WARN([])
     AC_MSG_WARN([I didn't find gnuplot.  Plotting commands will use the])
     AC_MSG_WARN([native graphics toolkit.])
@@ -3055,7 +3058,7 @@
   warn_msg_printed=true
 fi
 
-if $USE_ATOMIC_REFCOUNT; then
+if test $USE_ATOMIC_REFCOUNT = yes; then
   AC_MSG_WARN([])
   AC_MSG_WARN([Using atomic reference counting.])
   AC_MSG_WARN([This feature allows access to Octave data safely from])
@@ -3063,7 +3066,7 @@
   AC_MSG_WARN([results in a small performance penalty in the Octave])
   AC_MSG_WARN([interpreter.])
   AC_MSG_WARN([])
-  if $USE_OCTAVE_ALLOCATOR; then
+  if test $USE_OCTAVE_ALLOCATOR = yes; then
     AC_MSG_WARN([Thread-safe behavior is not guaranteed unless you also])
     AC_MSG_WARN([disable the use of the octave_allocator class.])
     AC_MSG_WARN([])
--- a/doc/interpreter/contributors.in	Mon Feb 11 15:45:26 2013 -0500
+++ b/doc/interpreter/contributors.in	Thu Feb 28 02:04:24 2013 -0500
@@ -10,6 +10,7 @@
 Alexander Barth
 David Bateman
 Heinz Bauschke
+Julien Bect
 Roman Belov
 Karl Berry
 David Billinghurst
--- a/doc/interpreter/octave.texi	Mon Feb 11 15:45:26 2013 -0500
+++ b/doc/interpreter/octave.texi	Thu Feb 28 02:04:24 2013 -0500
@@ -90,7 +90,8 @@
 @sp 2
 @multitable @columnfractions 0.4 0.025 0.65
 @item
-@flushright @image{octave_logo,2.1in} @end flushright
+@flushright @image{octave_logo,2.1in}
+@end flushright
 @tab
 @c this is a spacer column
 @tab
@@ -497,6 +498,9 @@
 * Plot Annotations::            
 * Multiple Plots on One Page::  
 * Multiple Plot Windows::       
+* Use of axis@comma{} line@comma{} and patch Functions::
+* Manipulation of Plot Windows::
+* Use of the @code{interpreter} Property::
 * Printing and Saving Plots::              
 * Interacting with Plots::      
 * Test Plotting Functions::     
--- a/doc/interpreter/plot.txi	Mon Feb 11 15:45:26 2013 -0500
+++ b/doc/interpreter/plot.txi	Thu Feb 28 02:04:24 2013 -0500
@@ -62,6 +62,9 @@
 * Plot Annotations::            
 * Multiple Plots on One Page::  
 * Multiple Plot Windows::       
+* Use of axis@comma{} line@comma{} and patch Functions::
+* Manipulation of Plot Windows::
+* Use of the @code{interpreter} Property::
 * Printing and Saving Plots::              
 * Interacting with Plots::      
 * Test Plotting Functions::     
@@ -517,8 +520,9 @@
 the second a cosine wave.  Figure numbers must be positive integers.
 
 @DOCSTRING(figure)
-@subsection Use of @code{axis},  @code{line}, and @code{patch} functions
-@cindex use of @code{axis},  @code{line}, and @code{patch} functions
+
+@node Use of axis@comma{} line@comma{} and patch Functions
+@subsection Use of axis@comma{} line@comma{} and patch Functions
 
 You can create axes, line, and patch objects directly using the
 @code{axes}, @code{line}, and @code{patch} functions.  These objects
@@ -532,8 +536,8 @@
 
 @DOCSTRING(surface)
 
-@subsection Manipulation of plot windows
-@cindex manipulation of plot windows
+@node Manipulation of Plot Windows
+@subsection Manipulation of Plot Windows
 
 By default, Octave refreshes the plot window when a prompt is printed,
 or when waiting for input.  The
@@ -591,8 +595,8 @@
 
 @DOCSTRING(closereq)
 
+@node Use of the @code{interpreter} Property
 @subsection Use of the @code{interpreter} Property
-@cindex use of the @code{interpreter} property
 
 All text objects, including titles, labels, legends, and text, include
 the property 'interpreter', this property determines the manner in which
@@ -2573,15 +2577,15 @@
 A character indicating a plot marker to be place at each data point, or
 @code{"none"}, meaning no markers should be displayed.
 
-@itemx markeredgecolor
+@item markeredgecolor
 The color of the edge around the marker, or @code{"auto"}, meaning that
 the edge color is the same as the face color.  @xref{Colors}.
 
-@itemx markerfacecolor
+@item markerfacecolor
 The color of the marker, or @code{"none"} to indicate that the marker
 should not be filled.  @xref{Colors}.
 
-@itemx markersize
+@item markersize
 A number specifying the size of the marker.  The default is 1.  A value
 of 2 is twice as large as the default, etc.
 @end table
--- a/doc/interpreter/tips.txi	Mon Feb 11 15:45:26 2013 -0500
+++ b/doc/interpreter/tips.txi	Thu Feb 28 02:04:24 2013 -0500
@@ -296,20 +296,20 @@
 When choosing variable names try to adhere to the following guidelines.
 
 @table @asis
-@item 
-vectors : x,y,z,t,w
+@item vectors :
+x,y,z,t,w
 
-@item
-matrices : A,B,M
+@item matrices :
+A,B,M
 
-@item
-strings : @nospell{str},s
+@item strings :
+@nospell{str},s
 
-@item
-filenames : @nospell{fname}
+@item filenames :
+@nospell{fname}
 
-@item
-cells,@nospell{cellstrs} : c,@nospell{cstr}
+@item cells,@nospell{cellstrs} :
+c,@nospell{cstr}
 @end table
 
 @item
--- a/libgui/src/files-dockwidget.cc	Mon Feb 11 15:45:26 2013 -0500
+++ b/libgui/src/files-dockwidget.cc	Thu Feb 28 02:04:24 2013 -0500
@@ -36,7 +36,7 @@
 #include <QHeaderView>
 
 files_dock_widget::files_dock_widget (QWidget *p)
-  : QDockWidget (p)
+  : octave_dock_widget (p)
 {
   setObjectName ("FilesDockWidget");
   setWindowIcon (QIcon(":/actions/icons/logo.png"));
@@ -114,11 +114,6 @@
     completer = new QCompleter (_file_system_model, this);
   _current_directory->setCompleter (completer);
 
-  connect (this, SIGNAL (visibilityChanged (bool)),
-           this, SLOT (handle_visibility_changed (bool)));
-  // topLevelChanged is emitted when floating property changes (floating = true)
-  connect (this, SIGNAL (topLevelChanged(bool)), this, SLOT(top_level_changed(bool)));
-
   setFocusProxy (_current_directory);
 }
 
@@ -203,28 +198,3 @@
   //if (settings.value ("showHiddenFiles").toBool ())
   // TODO: React on option for hidden files.
 }
-
-void
-files_dock_widget::handle_visibility_changed (bool visible)
-{
-  if (visible)
-    emit active_changed (true);
-}
-
-void
-files_dock_widget::closeEvent (QCloseEvent *e)
-{
-  emit active_changed (false);
-  QDockWidget::closeEvent (e);
-}
-
-// slot for signal that is emitted when floating property changes
-void
-files_dock_widget::top_level_changed (bool floating)
-{
-  if(floating)
-    {
-      setWindowFlags(Qt::Window);  // make a window from the widget when floating
-      show();                      // make it visible again since setWindowFlags hides it
-    }
-}
--- a/libgui/src/files-dockwidget.h	Mon Feb 11 15:45:26 2013 -0500
+++ b/libgui/src/files-dockwidget.h	Thu Feb 28 02:04:24 2013 -0500
@@ -35,14 +35,14 @@
 #include <QAction>
 #include <QTreeView>
 
-#include <QDockWidget>
 #include <QLineEdit>
+#include "octave-dock-widget.h"
 
 /**
    \class files_dock_widget
    \brief Dock widget to display files in the current directory.
 */
-class files_dock_widget : public QDockWidget
+class files_dock_widget : public octave_dock_widget
 {
   Q_OBJECT
   public:
@@ -51,6 +51,7 @@
   ~files_dock_widget ();
 
 public slots:
+
   /** Slot for handling a change in directory via double click. */
   void item_double_clicked (const QModelIndex & index);
 
@@ -68,12 +69,6 @@
   /** Tells the widget to react on changed settings. */
   void notice_settings ();
 
-  /** Slot to steer changing visibility from outside. */
-  void handle_visibility_changed (bool visible);
-
-  /** Slot when floating property changes */
-  void top_level_changed (bool floating);
-
 signals:
   /** Emitted, whenever the user requested to open a file. */
   void open_file (const QString& fileName);
@@ -81,11 +76,7 @@
   /** Emitted, whenever the currently displayed directory changed. */
   void displayed_directory_changed (const QString& directory);
 
-  /** Custom signal that tells if a user has clicke away that dock widget. */
-  void active_changed (bool active);
-
 protected:
-  void closeEvent (QCloseEvent *event);
 
 private:
   // TODO: Add toolbar with buttons for navigating the path, creating dirs, etc
--- a/libgui/src/history-dockwidget.cc	Mon Feb 11 15:45:26 2013 -0500
+++ b/libgui/src/history-dockwidget.cc	Thu Feb 28 02:04:24 2013 -0500
@@ -37,7 +37,7 @@
 #include "octave-link.h"
 
 history_dock_widget::history_dock_widget (QWidget * p)
-  : QDockWidget (p)
+  : octave_dock_widget (p)
 {
   setObjectName ("HistoryDockWidget");
   construct ();
@@ -71,26 +71,15 @@
 
   widget ()->setLayout (vbox_layout);
 
-  connect (_filter_line_edit,
-           SIGNAL (textEdited (QString)),
-           &_sort_filter_proxy_model,
-           SLOT (setFilterWildcard (QString)));
-
-  connect (_history_list_view,
-           SIGNAL (doubleClicked (QModelIndex)),
-           this,
-           SLOT (handle_double_click (QModelIndex)));
+  connect (_filter_line_edit, SIGNAL (textEdited (QString)),
+           &_sort_filter_proxy_model, SLOT (setFilterWildcard (QString)));
 
-  connect (this,
-           SIGNAL (visibilityChanged (bool)),
-           this,
-           SLOT (handle_visibility_changed (bool)));
+  connect (_history_list_view, SIGNAL (doubleClicked (QModelIndex)),
+           this, SLOT (handle_double_click (QModelIndex)));
 
-  // topLevelChanged is emitted when floating property changes (floating = true)
-  connect (this, SIGNAL (topLevelChanged(bool)), this, SLOT(top_level_changed(bool)));
-
-  _update_history_model_timer.setInterval (200);
-  _update_history_model_timer.setSingleShot (true);
+  _update_event_enabled = true;
+  _update_history_model_timer.setInterval (500);
+  _update_history_model_timer.setSingleShot (false);
 
   connect (&_update_history_model_timer,
            SIGNAL (timeout ()),
@@ -142,16 +131,13 @@
 }
 
 void
-history_dock_widget::handle_visibility_changed (bool visible)
-{
-  if (visible)
-    emit active_changed (true);
-}
-
-void
 history_dock_widget::request_history_model_update ()
 {
-  octave_link::post_event (this, &history_dock_widget::update_history_callback);
+  if (_update_event_enabled)
+    {
+      _update_event_enabled = false;  // no more update until this one is processed
+      octave_link::post_event (this, &history_dock_widget::update_history_callback);
+    }
 }
 
 void
@@ -161,24 +147,6 @@
 }
 
 void
-history_dock_widget::closeEvent (QCloseEvent *e)
-{
-  emit active_changed (false);
-  QDockWidget::closeEvent (e);
-}
-
-// slot for signal that is emitted when floating property changes
-void
-history_dock_widget::top_level_changed (bool floating)
-{
-  if(floating)
-    {
-      setWindowFlags(Qt::Window);  // make a window from the widget when floating
-      show();                      // make it visible again since setWindowFlags hides it
-    }
-}
-
-void
 history_dock_widget::update_history_callback (void)
 {
   static bool scroll_window = false;
@@ -218,7 +186,7 @@
       _history_list_view->scrollToBottom ();
     }
 
-  // Post a new update event in a given time. This prevents flooding the
-  // event queue.
-  _update_history_model_timer.start ();
+  // update is processed, re-enable further updates events triggered by timer
+    _update_event_enabled = true;
+
 }
--- a/libgui/src/history-dockwidget.h	Mon Feb 11 15:45:26 2013 -0500
+++ b/libgui/src/history-dockwidget.h	Thu Feb 28 02:04:24 2013 -0500
@@ -23,25 +23,22 @@
 #ifndef HISTORYDOCKWIDGET_H
 #define HISTORYDOCKWIDGET_H
 
-#include <QDockWidget>
 #include <QLineEdit>
 #include <QListView>
 #include <QSortFilterProxyModel>
 #include <QStringListModel>
 #include <QTimer>
+#include "octave-dock-widget.h"
 
-class history_dock_widget : public QDockWidget
+class history_dock_widget : public octave_dock_widget
 {
   Q_OBJECT
   public:
   history_dock_widget (QWidget *parent = 0);
 
 public slots:
-  void handle_visibility_changed (bool visible);
   void request_history_model_update ();
   void reset_model ();
-  /** Slot when floating property changes */
-  void top_level_changed (bool floating);
 
 signals:
   void information (const QString& message);
@@ -49,10 +46,8 @@
   /** Emitted, whenever the user double-clicked a command in the history. */
   void command_double_clicked (const QString& command);
 
-  /** Custom signal that tells if a user has clicked away that dock widget. */
-  void active_changed (bool active);
 protected:
-  void closeEvent (QCloseEvent *event);
+
 private slots:
   void handle_double_click (QModelIndex modelIndex);
   void handle_contextmenu_copy(bool flag);
@@ -71,6 +66,7 @@
   QTimer _update_history_model_timer;
 
   void update_history_callback (void);
+  bool _update_event_enabled;
 };
 
 #endif // HISTORYDOCKWIDGET_H
--- a/libgui/src/m-editor/file-editor-interface.h	Mon Feb 11 15:45:26 2013 -0500
+++ b/libgui/src/m-editor/file-editor-interface.h	Thu Feb 28 02:04:24 2013 -0500
@@ -23,22 +23,19 @@
 #ifndef FILEEDITORINTERFACE_H
 #define FILEEDITORINTERFACE_H
 
-#include <QDockWidget>
 #include <QMenu>
 #include <QToolBar>
+#include "octave-dock-widget.h"
 
-class file_editor_interface : public QDockWidget
+class file_editor_interface : public octave_dock_widget
 {
   Q_OBJECT
 
   public:
   file_editor_interface (QWidget *p)
-    : QDockWidget (p)
+    : octave_dock_widget (p)
   {
     setObjectName ("FileEditor");
-
-    connect (this, SIGNAL (visibilityChanged (bool)), this,
-             SLOT (handle_visibility_changed (bool)));
   }
 
   virtual ~file_editor_interface () { }
@@ -56,22 +53,12 @@
   virtual void request_open_file () = 0;
   virtual void request_open_file (const QString& fileName) = 0;
 
-signals:
-  void active_changed (bool active);
+//signals:
 
-protected:
-  void closeEvent (QCloseEvent *e)
-  {
-    emit active_changed (false);
-    QDockWidget::closeEvent (e);
-  }
+//protected:
 
-protected slots:
-  void handle_visibility_changed (bool visible)
-  {
-    if (visible)
-      emit active_changed (true);
-  }
+//protected slots:
+
 };
 
 #endif // FILEEDITORINTERFACE_H
--- a/libgui/src/m-editor/file-editor.cc	Mon Feb 11 15:45:26 2013 -0500
+++ b/libgui/src/m-editor/file-editor.cc	Thu Feb 28 02:04:24 2013 -0500
@@ -517,17 +517,6 @@
   emit fetab_settings_changed ();
 }
 
-// slot for signal that is emitted when floating property changes
-void
-file_editor::top_level_changed (bool floating)
-{
-  if(floating)
-    {
-      setWindowFlags(Qt::Window);  // make a window from the widget when floating
-      show();                      // make it visible again since setWindowFlag hides it
-    }
-}
-
 void
 file_editor::construct ()
 {
@@ -751,8 +740,6 @@
            SIGNAL (tabCloseRequested (int)), this, SLOT (handle_tab_close_request (int)));
   connect (_tab_widget,
            SIGNAL (currentChanged(int)), this, SLOT (active_tab_changed (int)));
-  // topLevelChanged is emitted when floating property changes (floating = true)
-  connect (this, SIGNAL (topLevelChanged(bool)), this, SLOT(top_level_changed(bool)));
 
   resize (500, 400);
   setWindowIcon (QIcon(":/actions/icons/logo.png"));
--- a/libgui/src/m-editor/file-editor.h	Mon Feb 11 15:45:26 2013 -0500
+++ b/libgui/src/m-editor/file-editor.h	Thu Feb 28 02:04:24 2013 -0500
@@ -123,9 +123,6 @@
   void handle_mru_add_file (const QString& file_name);
   void check_conflict_save (const QString& fileName, bool remove_on_success);
 
-  /** Slot when floating property changes */
-  void top_level_changed (bool floating);
-
   /** Tells the editor to react on changed settings. */
   void notice_settings ();
 
--- a/libgui/src/module.mk	Mon Feb 11 15:45:26 2013 -0500
+++ b/libgui/src/module.mk	Thu Feb 28 02:04:24 2013 -0500
@@ -73,7 +73,8 @@
   src/moc-workspace-view.cc \
   src/octave-adapter/moc-octave-main-thread.cc \
   src/qtinfo/moc-parser.cc \
-  src/qtinfo/moc-webinfo.cc
+  src/qtinfo/moc-webinfo.cc \
+  src/moc-octave-dock-widget.cc
 
 octave_gui_RC = src/qrc-resource.cc
 
@@ -86,6 +87,7 @@
 BUILT_SOURCES += $(octave_gui_UI_H)
 
 noinst_HEADERS += \
+  src/octave-dock-widget.h \
   src/documentation-dockwidget.h \
   src/files-dockwidget.h \
   src/history-dockwidget.h \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/octave-dock-widget.h	Thu Feb 28 02:04:24 2013 -0500
@@ -0,0 +1,81 @@
+/*
+
+Copyright (C) 2012-2013 Richard Crozier
+
+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/>.
+
+*/
+
+#ifndef OCTAVEDOCKWIDGET_H
+#define OCTAVEDOCKWIDGET_H
+
+#include <QDockWidget>
+//#include <QMenu>
+//#include <QToolBar>
+
+class octave_dock_widget : public QDockWidget
+{
+  Q_OBJECT
+
+  public:
+  octave_dock_widget (QWidget *p)
+    : QDockWidget (p)
+  {
+    connect (this, SIGNAL (visibilityChanged (bool)),
+             this, SLOT (handle_visibility_changed (bool)));
+
+    connect (this, SIGNAL (topLevelChanged(bool)),
+             this, SLOT(top_level_changed(bool)));
+  }
+
+  virtual ~octave_dock_widget () { }
+
+signals:
+  /** Custom signal that tells if a user has clicked away
+   *  that dock widget, i.e the active dock widget has
+   *  changed. */
+  virtual void active_changed (bool active);
+
+protected:
+  virtual void closeEvent (QCloseEvent *e)
+  {
+    emit active_changed (false);
+    QDockWidget::closeEvent (e);
+  }
+
+protected slots:
+
+  /** Slot to steer changing visibility from outside. */
+  virtual void handle_visibility_changed (bool visible)
+  {
+    if (visible)
+      emit active_changed (true);
+  }
+
+  /** Slot when floating property changes */
+  virtual void top_level_changed (bool floating)
+  {
+    if(floating)
+      {
+        setWindowFlags(Qt::Window);  // make a window from the widget when floating
+        show();                      // make it visible again since setWindowFlags hides it
+      }
+  }
+
+};
+
+#endif // OCTAVEDOCKWIDGET_H
--- a/libgui/src/terminal-dockwidget.cc	Mon Feb 11 15:45:26 2013 -0500
+++ b/libgui/src/terminal-dockwidget.cc	Thu Feb 28 02:04:24 2013 -0500
@@ -27,7 +27,7 @@
 #include "terminal-dockwidget.h"
 
 terminal_dock_widget::terminal_dock_widget (QTerminal *terminal, QWidget *p)
-  : QDockWidget (p)
+  : octave_dock_widget (p)
 {
   setObjectName ("TerminalDockWidget");
   setWindowIcon (QIcon(":/actions/icons/logo.png"));
@@ -39,27 +39,3 @@
   connect (this, SIGNAL (topLevelChanged(bool)), this, SLOT(top_level_changed(bool)));
 }
 
-void
-terminal_dock_widget::closeEvent (QCloseEvent *e)
-{
-  emit active_changed (false);
-  QDockWidget::closeEvent (e);
-}
-
-void
-terminal_dock_widget::handle_visibility_changed (bool visible)
-{
-  if (visible)
-    emit active_changed (true);
-}
-
-// slot for signal that is emitted when floating property changes
-void
-terminal_dock_widget::top_level_changed (bool floating)
-{
-  if(floating)
-    {
-      setWindowFlags(Qt::Window);  // make a window from the widget when floating
-      show();                      // make it visible again since setWindowFlags hides it
-    }
-}
--- a/libgui/src/terminal-dockwidget.h	Mon Feb 11 15:45:26 2013 -0500
+++ b/libgui/src/terminal-dockwidget.h	Thu Feb 28 02:04:24 2013 -0500
@@ -23,25 +23,21 @@
 #ifndef TERMINALDOCKWIDGET_H
 #define TERMINALDOCKWIDGET_H
 
-#include <QDockWidget>
 #include "QTerminal.h"
+#include "octave-dock-widget.h"
 
-class terminal_dock_widget : public QDockWidget
+class terminal_dock_widget : public octave_dock_widget
 {
   Q_OBJECT
   public:
   terminal_dock_widget (QTerminal *terminal, QWidget *parent = 0);
 
 signals:
-  void active_changed (bool active);
 
 public slots:
-  void handle_visibility_changed (bool visible);
-  /** Slot when floating property changes */
-  void top_level_changed (bool floating);
 
 protected:
-  void closeEvent (QCloseEvent *event);
+
 };
 
 
--- a/libgui/src/workspace-model.cc	Mon Feb 11 15:45:26 2013 -0500
+++ b/libgui/src/workspace-model.cc	Thu Feb 28 02:04:24 2013 -0500
@@ -1,3 +1,4 @@
+
 /*
 
 Copyright (C) 2011-2012 Jacob Dawid
@@ -51,8 +52,9 @@
           this,
           SLOT (request_update_workspace()));
 
+  _update_event_enabled = true;
   _update_workspace_model_timer.setInterval (500);
-  _update_workspace_model_timer.setSingleShot (true);
+  _update_workspace_model_timer.setSingleShot (false);
   _update_workspace_model_timer.start ();
 }
 
@@ -64,7 +66,11 @@
 void
 workspace_model::request_update_workspace ()
 {
-  octave_link::post_event (this, &workspace_model::update_workspace_callback);
+  if (_update_event_enabled)
+    {
+      _update_event_enabled = false;  // no more update until this one is processed
+      octave_link::post_event (this, &workspace_model::update_workspace_callback);
+    }
 }
 
 QModelIndex
@@ -222,8 +228,7 @@
   endResetModel();
   emit model_changed();
 
-  // Post a new event in a given time.
-  // This prevents flooding the event queue when no events are being processed.
-  _update_workspace_model_timer.start ();
+  // update is processed, re-enable further updates events triggered by timer
+  _update_event_enabled = true;
+
 }
-
--- a/libgui/src/workspace-model.h	Mon Feb 11 15:45:26 2013 -0500
+++ b/libgui/src/workspace-model.h	Thu Feb 28 02:04:24 2013 -0500
@@ -140,6 +140,8 @@
 
 private:
 
+  bool _update_event_enabled;
+
   void update_workspace_callback (void);
 
   /** Timer for periodically updating the workspace model from the current
--- a/libinterp/Makefile.am	Mon Feb 11 15:45:26 2013 -0500
+++ b/libinterp/Makefile.am	Thu Feb 28 02:04:24 2013 -0500
@@ -356,7 +356,9 @@
   DOCSTRINGS \
   $(BUILT_NODISTFILES) \
   $(OCT_FILES) \
-  $(OCT_STAMP_FILES)
+  $(OCT_STAMP_FILES) \
+  $(TST_FILES)
 
 MAINTAINERCLEANFILES = \
   $(BUILT_DISTFILES)
+
--- a/libinterp/corefcn/mappers.cc	Mon Feb 11 15:45:26 2013 -0500
+++ b/libinterp/corefcn/mappers.cc	Thu Feb 28 02:04:24 2013 -0500
@@ -1882,7 +1882,10 @@
 DEFUNX ("signbit", Fsignbit, args, ,
     "-*- texinfo -*-\n\
 @deftypefn {Mapping Function} {} signbit (@var{x})\n\
-Return a nonzero value if the value of @var{x} has its sign bit set.\n\
+Return logical true if the value of @var{x} has its sign bit set.\n\
+Otherwise return logical false.  This behavior is consistent with the other\n\
+logical functions. See@ref{Logical Values}.  The behavior differs from the\n\
+C language function which returns non-zero if the sign bit is set.\n\
 \n\
 This is not the same as @code{x < 0.0}, because IEEE 754 floating point\n\
 allows zero to be signed.  The comparison @code{-0.0 < 0.0} is false,\n\
@@ -1891,8 +1894,9 @@
 @end deftypefn")
 {
   octave_value retval;
-  if (args.length () == 1)
+  if (args.length () == 1) {
     retval = args(0).xsignbit ();
+    retval = (retval != 0); }
   else
     print_usage ();
 
--- a/libinterp/interp-core/dynamic-ld.cc	Mon Feb 11 15:45:26 2013 -0500
+++ b/libinterp/interp-core/dynamic-ld.cc	Thu Feb 28 02:04:24 2013 -0500
@@ -197,109 +197,6 @@
     instance->do_display ();
 }
 
-class
-octave_mex_file_list
-{
-public:
-
-  typedef std::list<octave_shlib>::iterator iterator;
-  typedef std::list<octave_shlib>::const_iterator const_iterator;
-
-  static void append (const octave_shlib& shl);
-
-  static void remove (octave_shlib& shl, octave_shlib::close_hook cl_hook = 0);
-
-private:
-
-  octave_mex_file_list (void) : file_list () { }
-
-  ~octave_mex_file_list (void) { }
-
-  void do_append (const octave_shlib& shl);
-
-  void do_remove (octave_shlib& shl, octave_shlib::close_hook cl_hook = 0);
-
-  static octave_mex_file_list *instance;
-
-  static void cleanup_instance (void) { delete instance; instance = 0; }
-
-  static bool instance_ok (void);
-
-  // List of libraries we have loaded.
-  std::list<octave_shlib> file_list;
-
-  // No copying!
-
-  octave_mex_file_list (const octave_mex_file_list&);
-
-  octave_mex_file_list& operator = (const octave_mex_file_list&);
-};
-
-octave_mex_file_list *octave_mex_file_list::instance = 0;
-
-void
-octave_mex_file_list::do_append (const octave_shlib& shl)
-{
-  file_list.push_back (shl);
-}
-
-void
-octave_mex_file_list::do_remove (octave_shlib& shl,
-                                 octave_shlib::close_hook cl_hook)
-{
-  for (iterator p = file_list.begin (); p != file_list.end (); p++)
-    {
-      if (*p == shl)
-        {
-          // Erase first to avoid potentially invalidating the pointer by the
-          // following hooks.
-          file_list.erase (p);
-
-          shl.close (cl_hook);
-
-          break;
-        }
-    }
-}
-
-bool
-octave_mex_file_list::instance_ok (void)
-{
-  bool retval = true;
-
-  if (! instance)
-    {
-      instance = new octave_mex_file_list ();
-
-      if (instance)
-        singleton_cleanup_list::add (cleanup_instance);
-    }
-
-  if (! instance)
-    {
-      ::error ("unable to create shared library list object!");
-
-      retval = false;
-    }
-
-  return retval;
-}
-
-void
-octave_mex_file_list::append (const octave_shlib& shl)
-{
-  if (instance_ok ())
-    instance->do_append (shl);
-}
-
-void
-octave_mex_file_list::remove (octave_shlib& shl,
-                              octave_shlib::close_hook cl_hook)
-{
-  if (instance_ok ())
-    instance->do_remove (shl, cl_hook);
-}
-
 octave_dynamic_loader *octave_dynamic_loader::instance = 0;
 
 bool octave_dynamic_loader::doing_load = false;
@@ -444,8 +341,6 @@
 
           bool have_fmex = false;
 
-          octave_mex_file_list::append (mex_file);
-
           function = mex_file.search (fcn_name, mex_mangler);
 
           if (! function)
@@ -513,7 +408,7 @@
       retval = shl.remove (fcn_name);
 
       if (shl.number_of_functions_loaded () == 0)
-        octave_mex_file_list::remove (shl);
+        octave_shlib_list::remove (shl);
     }
 
   return retval;
--- a/libinterp/interp-core/oct-stream.h	Mon Feb 11 15:45:26 2013 -0500
+++ b/libinterp/interp-core/oct-stream.h	Thu Feb 28 02:04:24 2013 -0500
@@ -371,12 +371,6 @@
 
   virtual std::ostream *output_stream (void) { return 0; }
 
-  // If the derived class is locale-aware, it must implement this function 
-  // in order to set a new locale. By default, this function avoids messing 
-  // with locales and ignores its input argument.
-  virtual std::locale imbue ( const std::locale &)
-    { return std::locale::classic (); }
-
   // Return TRUE if this stream is open.
 
   bool is_open (void) const { return open_state; }
@@ -619,23 +613,7 @@
   {
     return rep ? rep->output_stream () : 0;
   }
-  
-  std::locale imbue (const std::locale & loc )
-    {
-      if (!rep) return std::locale::classic ();
-      
-      std::istream *is = rep->input_stream ();
-      std::ostream *os = rep->output_stream ();
-      
-      if (os) 
-        {
-          if (is)
-            (void) is->imbue (loc);
-          return os->imbue (loc);
-        }
-      return is ? is->imbue (loc) : std::locale::classic ();
-    }
-  
+
   void clearerr (void) { if (rep) rep->clearerr (); }
 
 private:
--- a/libinterp/interp-core/pt-jit.cc	Mon Feb 11 15:45:26 2013 -0500
+++ b/libinterp/interp-core/pt-jit.cc	Thu Feb 28 02:04:24 2013 -0500
@@ -36,12 +36,12 @@
 #include "symtab.h"
 #include "variables.h"
 
+#ifdef HAVE_LLVM
+
 static bool Venable_jit_debugging = false;
 
 static bool Venable_jit_compiler = true;
 
-#ifdef HAVE_LLVM
-
 #include <llvm/Analysis/CallGraph.h>
 #include <llvm/Analysis/Passes.h>
 #include <llvm/Analysis/Verifier.h>
--- a/libinterp/interpfcn/data.cc	Mon Feb 11 15:45:26 2013 -0500
+++ b/libinterp/interpfcn/data.cc	Thu Feb 28 02:04:24 2013 -0500
@@ -4729,7 +4729,17 @@
     }
 
   if (nargin == 3)
-    npoints = args(2).idx_type_value ();
+    {
+      // Apparently undocumented Matlab.  If the third arg is an empty
+      // numeric value, the number of points defaults to 1.
+
+      octave_value arg_3 = args(2);
+
+      if (arg_3.is_numeric_type () && arg_3.is_empty ())
+        npoints = 1;
+      else
+        npoints = arg_3.idx_type_value ();
+    }
 
   if (! error_state)
     {
@@ -4770,6 +4780,8 @@
 
 %assert (linspace ([1, 2; 3, 4], 5, 6), linspace (1, 5, 6))
 
+%assert (linspace (0, 1, []), 1)
+
 %!error linspace ()
 %!error linspace (1, 2, 3, 4)
 */
--- a/libinterp/interpfcn/dirfns.cc	Mon Feb 11 15:45:26 2013 -0500
+++ b/libinterp/interpfcn/dirfns.cc	Thu Feb 28 02:04:24 2013 -0500
@@ -556,9 +556,9 @@
 Within a pattern\n\
 \n\
 @table @code\n\
-@itemx *\n\
+@item *\n\
 matches any string, including the null string,\n\
-@itemx ?\n\
+@item ?\n\
 matches any single character, and\n\
 \n\
 @item [@dots{}]\n\
--- a/libinterp/interpfcn/file-io.cc	Mon Feb 11 15:45:26 2013 -0500
+++ b/libinterp/interpfcn/file-io.cc	Thu Feb 28 02:04:24 2013 -0500
@@ -43,9 +43,7 @@
 
 #include <iostream>
 #include <limits>
-#include <locale>
 #include <stack>
-#include <stdexcept>
 #include <vector>
 
 #include <fcntl.h>
@@ -646,23 +644,23 @@
 The parameter @var{arch} is a string specifying the default data format\n\
 for the file.  Valid values for @var{arch} are:\n\
 \n\
-@table @asis\n\
-@samp{native}\n\
+@table @samp\n\
+@item native\n\
 The format of the current machine (this is the default).\n\
 \n\
-@samp{ieee-be}\n\
+@item ieee-be\n\
 IEEE big endian format.\n\
 \n\
-@samp{ieee-le}\n\
+@item ieee-le\n\
 IEEE little endian format.\n\
 \n\
-@samp{vaxd}\n\
+@item vaxd\n\
 VAX D floating format.\n\
 \n\
-@samp{vaxg}\n\
+@item vaxg\n\
 VAX G floating format.\n\
 \n\
-@samp{cray}\n\
+@item cray\n\
 Cray floating format.\n\
 @end table\n\
 \n\
@@ -1087,7 +1085,7 @@
 DEFUN (fscanf, args, ,
   "-*- texinfo -*-\n\
 @deftypefn  {Built-in Function} {[@var{val}, @var{count}, @var{errmsg}] =} fscanf (@var{fid}, @var{template}, @var{size})\n\
-@deftypefnx {Built-in Function} {[@var{v1}, @var{v2}, @dots{}, @var{count}] =} fscanf (@var{fid}, @var{template}, @var{locale})\n\
+@deftypefnx {Built-in Function} {[@var{v1}, @var{v2}, @dots{}, @var{count}, @var{errmsg}] =} fscanf (@var{fid}, @var{template}, \"C\")\n\
 In the first form, read from @var{fid} according to @var{template},\n\
 returning the result in the matrix @var{val}.\n\
 \n\
@@ -1126,10 +1124,7 @@
 with each conversion specifier in @var{template} corresponding to a\n\
 single scalar return value.  This form is more `C-like', and also\n\
 compatible with previous versions of Octave.  The number of successful\n\
-conversions is returned in @var{count}.  It permits to explicitly\n\
-specify a locale to take into account language specific features, \n\
-such as decimal separator.  This operation restores the previous locales\n\
-setting at the end of the conversion.\n\
+conversions is returned in @var{count}\n\
 @ifclear OCTAVE_MANUAL\n\
 \n\
 See the Formatted Input section of the GNU Octave manual for a\n\
@@ -1151,25 +1146,7 @@
       if (! error_state)
         {
           if (args(1).is_string ())
-            {
-              std::locale oldloc;
-              try
-                {
-                  // Use args(2) val as the new locale setting. Keep
-                  // old val for restoring afterwards.
-                  oldloc = 
-                    os.imbue (std::locale (args(2).string_value ().c_str ()));
-
-                }
-              catch (std::runtime_error)
-                {
-                  // Display a warning if the specified locale is unknown
-                  warning ("fscanf: invalid locale. Try 'locale -a' for a list of supported values.");
-                  oldloc = std::locale::classic ();
-                }
-              retval = os.oscanf (args(1), who);
-              os.imbue (oldloc);
-            }
+            retval = os.oscanf (args(1), who);
           else
             ::error ("%s: format TEMPLATE must be a string", who.c_str ());
         }
@@ -1237,7 +1214,7 @@
 DEFUN (sscanf, args, ,
   "-*- texinfo -*-\n\
 @deftypefn  {Built-in Function} {[@var{val}, @var{count}, @var{errmsg}, @var{pos}] =} sscanf (@var{string}, @var{template}, @var{size})\n\
-@deftypefnx {Built-in Function} {[@var{v1}, @var{v2}, @dots{}, @var{count}] =} sscanf (@var{string}, @var{template}, @var{locale})\n\
+@deftypefnx {Built-in Function} {[@var{v1}, @var{v2}, @dots{}, @var{count}, @var{errmsg}] =} sscanf (@var{string}, @var{template}, \"C\")\n\
 This is like @code{fscanf}, except that the characters are taken from the\n\
 string @var{string} instead of from a stream.  Reaching the end of the\n\
 string is treated as an end-of-file condition.  In addition to the values\n\
@@ -1262,22 +1239,8 @@
 
           if (os.is_valid ())
             {
-              if (args(1).is_string ()) 
-                {
-                  // Use args(2) val as the new locale setting. As the os
-                  // object is short lived, we don't need to restore
-                  // locale afterwards.
-                  try
-                    {  
-                      os.imbue (std::locale (args(2).string_value ().c_str ()));
-                    }
-                  catch (std::runtime_error)
-                    {
-                      // Display a warning if the specified locale is unknown
-                      warning ("sscanf: invalid locale. Try 'locale -a' for a list of supported values.");
-                    }
-                  retval = os.oscanf (args(1), who);
-                }              
+              if (args(1).is_string ())
+                retval = os.oscanf (args(1), who);
               else
                 ::error ("%s: format TEMPLATE must be a string", who.c_str ());
             }
@@ -1345,16 +1308,10 @@
   return retval;
 }
 
-/*
-%!test
-%! assert (sscanf ("1,2", "%f", "C"), 1)
-%! assert (sscanf ("1,2", "%f", "fr_FR"), 1.2)
-*/
-
 DEFUN (scanf, args, nargout,
   "-*- texinfo -*-\n\
 @deftypefn  {Built-in Function} {[@var{val}, @var{count}, @var{errmsg}] =} scanf (@var{template}, @var{size})\n\
-@deftypefnx {Built-in Function} {[@var{v1}, @var{v2}, @dots{}, @var{count}] =} scanf (@var{template}, @var{locale})\n\
+@deftypefnx {Built-in Function} {[@var{v1}, @var{v2}, @dots{}, @var{count}, @var{errmsg}]] =} scanf (@var{template}, \"C\")\n\
 This is equivalent to calling @code{fscanf} with @var{fid} = @code{stdin}.\n\
 \n\
 It is currently not useful to call @code{scanf} in interactive\n\
--- a/libinterp/interpfcn/input.cc	Mon Feb 11 15:45:26 2013 -0500
+++ b/libinterp/interpfcn/input.cc	Thu Feb 28 02:04:24 2013 -0500
@@ -100,10 +100,6 @@
 // TRUE means get input from current_eval_string.
 bool get_input_from_eval_string = false;
 
-// TRUE means we haven't been asked for the input from
-// current_eval_string yet.
-bool input_from_eval_string_pending = false;
-
 // TRUE means that input is coming from a file that was named on
 // the command line.
 bool input_from_command_line_file = false;
@@ -191,16 +187,16 @@
 }
 
 std::string
-gnu_readline (const std::string& s, bool force_readline)
+gnu_readline (const std::string& s, bool& eof, bool force_readline)
 {
   octave_quit ();
 
+  eof = false;
+
   std::string retval;
 
   if (line_editing || force_readline)
     {
-      bool eof;
-
       retval = command_editor::readline (s, eof);
 
       if (! eof && retval.empty ())
@@ -221,14 +217,22 @@
       if (reading_fcn_file || reading_script_file || reading_classdef_file)
         curr_stream = ff_instream;
 
-      retval = octave_fgets (curr_stream);
+      retval = octave_fgets (curr_stream, eof);
     }
 
   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 force_readline = false)
+interactive_input (const std::string& s, bool& eof, bool force_readline)
 {
   Vlast_prompt_time.stamp ();
 
@@ -247,14 +251,24 @@
         return "\n";
     }
 
-  return gnu_readline (s, force_readline);
+  return gnu_readline (s, eof, force_readline);
+}
+
+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 (void)
+octave_gets (bool& eof)
 {
   octave_quit ();
 
+  eof = false;
+
   std::string retval;
 
   bool history_skip_auto_repeated_debugging_command = false;
@@ -280,7 +294,7 @@
 
       octave_diary << prompt;
 
-      retval = interactive_input (prompt);
+      retval = interactive_input (prompt, eof, false);
 
       // There is no need to update the load_path cache if there is no
       // user input.
@@ -301,7 +315,7 @@
         }
     }
   else
-    retval = gnu_readline ("");
+    retval = gnu_readline ("", eof, false);
 
   current_input_line = retval;
 
@@ -329,99 +343,35 @@
 
 // Read a line from the input stream.
 
-static std::string
-get_user_input (void)
+std::string
+get_user_input (bool& eof)
 {
   octave_quit ();
 
+  eof = false;
+
   std::string retval;
 
   if (get_input_from_eval_string)
     {
-      if (input_from_eval_string_pending)
-        {
-          input_from_eval_string_pending = false;
+      retval = current_eval_string;
 
-          retval = current_eval_string;
+      size_t len = retval.length ();
 
-          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 = "";
 
-          if (len > 0 && retval[len-1] != '\n')
-            retval.append ("\n");
-        }
+      eof = true;
     }
   else
-    retval = octave_gets ();
+    retval = octave_gets (eof);
 
   current_input_line = retval;
 
   return retval;
 }
 
-int
-octave_read (char *buf, unsigned max_size)
-{
-  // FIXME -- is this a safe way to buffer the input?
-
-  static const char * const eol = "\n";
-  static std::string input_buf;
-  static const char *pos = 0;
-  static size_t chars_left = 0;
-
-  int status = 0;
-  if (chars_left == 0)
-    {
-      pos = 0;
-
-      input_buf = get_user_input ();
-
-      chars_left = input_buf.length ();
-
-      pos = input_buf.c_str ();
-    }
-
-  if (chars_left > 0)
-    {
-      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;
-
-    }
-  else if (chars_left == 0)
-    {
-      status = 0;
-    }
-  else
-    status = -1;
-
-  return status;
-}
-
 // Fix things up so that input can come from file 'name', printing a
 // warning if the file doesn't exist.
 
@@ -717,35 +667,33 @@
 
       frame.protect_var (get_input_from_eval_string);
       get_input_from_eval_string = false;
-
-      YY_BUFFER_STATE old_buf = current_buffer ();
-      YY_BUFFER_STATE new_buf = create_buffer (get_input_from_stdin ());
+    }
 
-      // FIXME: are these safe?
-      frame.add_fcn (switch_to_buffer, old_buf);
-      frame.add_fcn (delete_buffer, new_buf);
+  // octave_parser constructor sets this for us.
+  frame.protect_var (CURR_LEXER);
 
-      switch_to_buffer (new_buf);
-    }
+  octave_parser *curr_parser = new octave_parser ();
+  frame.add_fcn (octave_parser::cleanup, curr_parser);
 
   while (Vdebugging)
     {
+      unwind_protect middle_frame;
+
       reset_error_handler ();
 
-      reset_parser ();
+      curr_parser->reset ();
 
       // Save current value of global_command.
-      frame.protect_var (global_command);
+      middle_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);
+      middle_frame.add_fcn (symbol_table::unmark_forced_variables, scope);
 
-      // This is the same as yyparse in parse.y.
-      int retval = octave_parse ();
+      int retval = curr_parser->run ();
 
       if (retval == 0 && global_command)
         {
@@ -763,10 +711,6 @@
             octave_completion_matches_called = false;
         }
 
-      // Unmark forced variables.
-      // Restore previous value of global_command.
-      frame.run (2);
-
       octave_quit ();
     }
 }
@@ -843,8 +787,8 @@
 
 DEFUN (input, args, nargout,
   "-*- texinfo -*-\n\
-@deftypefn  {Built-in Function} {} input (@var{prompt})\n\
-@deftypefnx {Built-in Function} {} input (@var{prompt}, \"s\")\n\
+@deftypefn  {Built-in Function} {@var{ans} =} input (@var{prompt})\n\
+@deftypefnx {Built-in Function} {@var{ans} =} input (@var{prompt}, \"s\")\n\
 Print a prompt and wait for user input.  For example,\n\
 \n\
 @example\n\
@@ -874,7 +818,8 @@
 Because there may be output waiting to be displayed by the pager, it is\n\
 a good idea to always call @code{fflush (stdout)} before calling\n\
 @code{input}.  This will ensure that all pending output is written to\n\
-the screen before your prompt.  @xref{Input and Output}.\n\
+the screen before your prompt.\n\
+@seealso{yes_or_no, kbhit}\n\
 @end deftypefn")
 {
   octave_value_list retval;
@@ -909,12 +854,14 @@
 
 DEFUN (yes_or_no, args, ,
   "-*- texinfo -*-\n\
-@deftypefn {Built-in Function} {} yes_or_no (@var{prompt})\n\
-Ask the user a yes-or-no question.  Return 1 if the answer is yes.\n\
-Takes one argument, which is the string to display to ask the\n\
-question.  It should end in a space; @samp{yes-or-no-p} adds\n\
-@samp{(yes or no) } to it.  The user must confirm the answer with\n\
-RET and can edit it until it has been confirmed.\n\
+@deftypefn {Built-in Function} {@var{ans} =} yes_or_no (\"@var{prompt}\")\n\
+Ask the user a yes-or-no question.  Return logical true if the answer is yes\n\
+or false if the answer is no.  Takes one argument, @var{prompt}, which is\n\
+the string to display when asking the question.  @var{prompt} should end in\n\
+a space; @code{yes-or-no} adds the string @samp{(yes or no) } to it.  The\n\
+user must confirm the answer with @key{RET} and can edit it until it has\n\
+been confirmed.\n\
+@seealso{input}\n\
 @end deftypefn")
 {
   octave_value retval;
@@ -986,7 +933,7 @@
 DEFUN (keyboard, args, ,
   "-*- texinfo -*-\n\
 @deftypefn  {Built-in Function} {} keyboard ()\n\
-@deftypefnx {Built-in Function} {} keyboard (@var{prompt})\n\
+@deftypefnx {Built-in Function} {} keyboard (\"@var{prompt}\")\n\
 This function is normally used for simple debugging.  When the\n\
 @code{keyboard} function is executed, Octave prints a prompt and waits\n\
 for user input.  The input strings are then evaluated and the results\n\
@@ -1241,31 +1188,28 @@
 static int
 input_event_hook (void)
 {
-  if (! lexer_flags.defining_func)
-    {
-      hook_fcn_map_type::iterator p = hook_fcn_map.begin ();
+  hook_fcn_map_type::iterator p = hook_fcn_map.begin ();
 
-      while (p != hook_fcn_map.end ())
-        {
-          std::string hook_fcn = p->first;
-          octave_value user_data = p->second;
+  while (p != hook_fcn_map.end ())
+    {
+      std::string hook_fcn = p->first;
+      octave_value user_data = p->second;
 
-          hook_fcn_map_type::iterator q = p++;
+      hook_fcn_map_type::iterator q = p++;
 
-          if (is_valid_function (hook_fcn))
-            {
-              if (user_data.is_defined ())
-                feval (hook_fcn, user_data, 0);
-              else
-                feval (hook_fcn, octave_value_list (), 0);
-            }
+      if (is_valid_function (hook_fcn))
+        {
+          if (user_data.is_defined ())
+            feval (hook_fcn, user_data, 0);
           else
-            hook_fcn_map.erase (q);
+            feval (hook_fcn, octave_value_list (), 0);
         }
+      else
+        hook_fcn_map.erase (q);
+    }
 
-      if (hook_fcn_map.empty ())
-        command_editor::remove_event_hook (input_event_hook);
-    }
+  if (hook_fcn_map.empty ())
+    command_editor::remove_event_hook (input_event_hook);
 
   return 0;
 }
--- a/libinterp/interpfcn/input.h	Mon Feb 11 15:45:26 2013 -0500
+++ b/libinterp/interpfcn/input.h	Thu Feb 28 02:04:24 2013 -0500
@@ -35,8 +35,11 @@
 
 class octave_value;
 
-extern OCTINTERP_API int octave_read (char *buf, unsigned max_size);
-extern OCTINTERP_API FILE *get_input_from_file (const std::string& name, int warn = 1);
+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().
@@ -45,10 +48,6 @@
 // TRUE means get input from current_eval_string.
 extern bool get_input_from_eval_string;
 
-// TRUE means we haven't been asked for the input from
-// current_eval_string yet.
-extern bool input_from_eval_string_pending;
-
 // TRUE means that input is coming from a file that was named on
 // the command line.
 extern bool input_from_command_line_file;
--- a/libinterp/interpfcn/oct-hist.cc	Mon Feb 11 15:45:26 2013 -0500
+++ b/libinterp/interpfcn/oct-hist.cc	Thu Feb 28 02:04:24 2013 -0500
@@ -377,7 +377,9 @@
   int hist_count = hlist.length () - 1;  // switch to zero-based indexing
 
   // The current command line is already part of the history list by
-  // the time we get to this point.  Delete it from the list.
+  // the time we get to this point.  Delete the cmd from the list when
+  // executing 'edit_history' so that it doesn't show up in the history
+  // but the actual commands performed will.
 
   if (! insert_curr)
     command_history::remove (hist_count);
@@ -521,13 +523,15 @@
           continue;
         }
 
-      if (first)
-        {
-          first = 0;
-          edit_history_repl_hist (line);
-        }
-      else
-        edit_history_add_hist (line);
+      // Command 'edit history' has already been removed in
+      // mk_tmp_hist_file ()
+      //if (first)
+      //  {
+      //    first = 0;
+      //    edit_history_repl_hist (line);
+      //  }
+      //else
+      edit_history_add_hist (line);
 
       delete [] line;
     }
@@ -638,27 +642,30 @@
 
 DEFUN (history, args, nargout,
   "-*- texinfo -*-\n\
-@deftypefn {Command} history options\n\
-@deftypefnx {Built-in Function} {@var{h} = } history (@var{opt1}, @var{opt2}, @dots{})\n\
+@deftypefn  {Command} {} history\n\
+@deftypefnx {Command} {} history @var{opt1} @dots{}\n\
+@deftypefnx {Built-in Function} {@var{h} =} history ()\n\
+@deftypefnx {Built-in Function} {@var{h} =} history (@var{opt1}, @dots{})\n\
 If invoked with no arguments, @code{history} displays a list of commands\n\
 that you have executed.  Valid options are:\n\
 \n\
 @table @code\n\
-@item -w @var{file}\n\
-Write the current history to the file @var{file}.  If the name is\n\
-omitted, use the default history file (normally @file{~/.octave_hist}).\n\
+@item   @var{n}\n\
+@itemx -@var{n}\n\
+Display only the most recent @var{n} lines of history.\n\
+\n\
+@item -q\n\
+Don't number the displayed lines of history.  This is useful for cutting\n\
+and pasting commands using the X Window System.\n\
 \n\
 @item -r @var{file}\n\
 Read the file @var{file}, appending its contents to the current\n\
 history list.  If the name is omitted, use the default history file\n\
 (normally @file{~/.octave_hist}).\n\
 \n\
-@item @var{n}\n\
-Display only the most recent @var{n} lines of history.\n\
-\n\
-@item -q\n\
-Don't number the displayed lines of history.  This is useful for cutting\n\
-and pasting commands using the X Window System.\n\
+@item -w @var{file}\n\
+Write the current history to the file @var{file}.  If the name is\n\
+omitted, use the default history file (normally @file{~/.octave_hist}).\n\
 @end table\n\
 \n\
 For example, to display the five most recent commands that you have\n\
--- a/libinterp/interpfcn/symtab.cc	Mon Feb 11 15:45:26 2013 -0500
+++ b/libinterp/interpfcn/symtab.cc	Thu Feb 28 02:04:24 2013 -0500
@@ -1049,20 +1049,12 @@
 symbol_table::set_class_relationship (const std::string& sup_class,
                                       const std::string& inf_class)
 {
-  class_precedence_table_const_iterator p
-    = class_precedence_table.find (inf_class);
-
-  if (p != class_precedence_table.end ())
-    {
-      const std::set<std::string>& inferior_classes = p->second;
+  if (is_superiorto (inf_class, sup_class))
+    return false;
 
-      std::set<std::string>::const_iterator q
-        = inferior_classes.find (sup_class);
-
-      if (q != inferior_classes.end ())
-        return false;
-    }
-
+  // If sup_class doesn't have an entry in the precedence table,
+  // this will automatically create it, and associate to it a
+  // singleton set {inf_class} of inferior classes.
   class_precedence_table[sup_class].insert (inf_class);
 
   return true;
@@ -1070,7 +1062,7 @@
 
 // Has class A been marked as superior to class B?  Also returns
 // TRUE if B has been marked as inferior to A, since we only keep
-// one table, and convert inferiort information to a superiorto
+// one table, and convert inferiorto information to a superiorto
 // relationship.  Two calls are required to determine whether there
 // is no relationship between two classes:
 //
@@ -1084,20 +1076,14 @@
 bool
 symbol_table::is_superiorto (const std::string& a, const std::string& b)
 {
-  bool retval = false;
-
   class_precedence_table_const_iterator p = class_precedence_table.find (a);
+  // If a has no entry in the precedence table, return false
+  if (p == class_precedence_table.end ())
+    return false;
 
-  if (p != class_precedence_table.end ())
-    {
-      const std::set<std::string>& inferior_classes = p->second;
-      std::set<std::string>::const_iterator q = inferior_classes.find (b);
-
-      if (q != inferior_classes.end ())
-        retval = true;
-    }
-
-  return retval;
+  const std::set<std::string>& inferior_classes = p->second;
+  std::set<std::string>::const_iterator q = inferior_classes.find (b);
+  return (q != inferior_classes.end ());
 }
 
 static std::string
@@ -1516,7 +1502,7 @@
             {
               if (ours.is_global () || ours.is_persistent ())
                 ::error ("global and persistent may only be used in the topmost level in which a nested variable is used");
-                
+
               if (! ours.is_formal ())
                 {
                   ours.invalidate ();
--- a/libinterp/interpfcn/sysdep.cc	Mon Feb 11 15:45:26 2013 -0500
+++ b/libinterp/interpfcn/sysdep.cc	Thu Feb 28 02:04:24 2013 -0500
@@ -619,8 +619,9 @@
 
 DEFUN (kbhit, args, ,
   "-*- texinfo -*-\n\
-@deftypefn {Built-in Function} {} kbhit ()\n\
-Read a single keystroke from the keyboard.  If called with one\n\
+@deftypefn  {Built-in Function} {} kbhit ()\n\
+@deftypefnx {Built-in Function} {} kbhit (1)\n\
+Read a single keystroke from the keyboard.  If called with an\n\
 argument, don't wait for a keypress.  For example,\n\
 \n\
 @example\n\
@@ -636,8 +637,9 @@
 @end example\n\
 \n\
 @noindent\n\
-identical to the above example, but don't wait for a keypress,\n\
+is identical to the above example, but doesn't wait for a keypress,\n\
 returning the empty string if no key is available.\n\
+@seealso{input}\n\
 @end deftypefn")
 {
   octave_value retval;
@@ -653,7 +655,7 @@
       if (c == -1)
         c = 0;
 
-      char s[2] = {c, '\0'};
+      char s[2] = { static_cast<char> (c), '\0' };
 
       retval = s;
     }
--- a/libinterp/interpfcn/sysdep.h	Mon Feb 11 15:45:26 2013 -0500
+++ b/libinterp/interpfcn/sysdep.h	Thu Feb 28 02:04:24 2013 -0500
@@ -30,9 +30,9 @@
 #include "lo-ieee.h"
 #include "lo-sysdep.h"
 
-extern void sysdep_init (void);
+extern OCTINTERP_API void sysdep_init (void);
 
-extern void sysdep_cleanup (void);
+extern OCTINTERP_API void sysdep_cleanup (void);
 
 extern OCTINTERP_API void raw_mode (bool, bool wait = true);
 
--- a/libinterp/interpfcn/toplev.cc	Mon Feb 11 15:45:26 2013 -0500
+++ b/libinterp/interpfcn/toplev.cc	Thu Feb 28 02:04:24 2013 -0500
@@ -559,16 +559,24 @@
 
   // The big loop.
 
+  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);
+
   int retval = 0;
   do
     {
       try
         {
-          unwind_protect frame;
+          unwind_protect inner_frame;
 
           reset_error_handler ();
 
-          reset_parser ();
+          curr_parser->reset ();
 
           if (symbol_table::at_top_level ())
             tree_evaluator::reset_debug_state ();
@@ -577,14 +585,13 @@
           // 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);
+          inner_frame.add_fcn (symbol_table::unmark_forced_variables, scope);
 
-          frame.protect_var (global_command);
+          inner_frame.protect_var (global_command);
 
           global_command = 0;
 
-          // This is the same as yyparse in parse.y.
-          retval = octave_parse ();
+          retval = curr_parser->run ();
 
           if (retval == 0)
             {
@@ -632,7 +639,7 @@
                         command_editor::increment_current_command_number ();
                     }
                 }
-              else if (parser_end_of_input)
+              else if (curr_parser->end_of_input)
                 break;
             }
         }
--- a/libinterp/octave-value/ov-base-diag.cc	Mon Feb 11 15:45:26 2013 -0500
+++ b/libinterp/octave-value/ov-base-diag.cc	Thu Feb 28 02:04:24 2013 -0500
@@ -109,7 +109,7 @@
 
       if (idx0.is_scalar () && idx1.is_scalar ())
         {
-          retval = matrix.elem (idx0(0), idx1(0));
+          retval = matrix.checkelem (idx0(0), idx1(0));
         }
       else
         {
--- a/libinterp/octave-value/ov-cell.cc	Mon Feb 11 15:45:26 2013 -0500
+++ b/libinterp/octave-value/ov-cell.cc	Thu Feb 28 02:04:24 2013 -0500
@@ -136,7 +136,8 @@
 octave_value_list
 octave_cell::subsref (const std::string& type,
                       const std::list<octave_value_list>& idx,
-                      int nargout)
+                      int nargout,
+                      const std::list<octave_lvalue> *lvalue_list)
 {
   octave_value_list retval;
 
@@ -178,7 +179,9 @@
   // octave_user_function::subsref.
 
   if (idx.size () > 1)
-    retval = retval(0).next_subsref (nargout, type, idx);
+    retval = (lvalue_list
+              ? retval(0).next_subsref (nargout, type, idx, lvalue_list)
+              : retval(0).next_subsref (nargout, type, idx));
 
   return retval;
 }
--- a/libinterp/octave-value/ov-cell.h	Mon Feb 11 15:45:26 2013 -0500
+++ b/libinterp/octave-value/ov-cell.h	Thu Feb 28 02:04:24 2013 -0500
@@ -79,7 +79,16 @@
     }
 
   octave_value_list subsref (const std::string& type,
-                             const std::list<octave_value_list>& idx, int);
+                             const std::list<octave_value_list>& idx,
+                             int nargout)
+  {
+    return subsref (type, idx, nargout, 0);
+  }
+
+  octave_value_list subsref (const std::string& type,
+                             const std::list<octave_value_list>& idx,
+                             int nargout,
+                             const std::list<octave_lvalue> *lvalue_list);
 
   octave_value subsref (const std::string& type,
                         const std::list<octave_value_list>& idx,
--- a/libinterp/octave-value/ov-class.cc	Mon Feb 11 15:45:26 2013 -0500
+++ b/libinterp/octave-value/ov-class.cc	Thu Feb 28 02:04:24 2013 -0500
@@ -2191,42 +2191,34 @@
   octave_value retval;
 
   octave_function *fcn = octave_call_stack::caller ();
-
-  if (fcn && fcn->is_class_constructor ())
+  if ((! fcn) || (! fcn->is_class_constructor ()))
     {
-      for (int i = 0; i < args.length (); i++)
-        {
-          std::string class_name = args(i).string_value ();
-
-          if (! error_state)
-            {
-              if (! is_built_in_class (class_name))
-                {
-                  std::string this_class_name = fcn->name ();
+      error ("superiorto: invalid call from outside class constructor");
+      return retval;
+    }
 
-                  if (! symbol_table::set_class_relationship (this_class_name,
-                                                              class_name))
-                    {
-                      error ("superiorto: precedence already set for %s and %s",
-                             this_class_name.c_str (), class_name.c_str ());
-                      break;
-                    }
-                }
-              else
-                {
-                  // User defined classes always have higher precedence
-                  // than built-in classes.
-                }
-            }
-          else
-            {
+  for (int i = 0; i < args.length (); i++)
+    {
+      std::string inf_class = args(i).string_value ();
+      if (error_state)
+        {
               error ("superiorto: expecting argument to be class name");
               break;
-            }
+        }
+
+      // User defined classes always have higher precedence
+      // than built-in classes
+      if (is_built_in_class (inf_class))
+        break;
+
+      std::string sup_class = fcn->name ();
+      if (! symbol_table::set_class_relationship (sup_class, inf_class))
+        {
+          error ("superiorto: opposite precedence already set for %s and %s",
+                 sup_class.c_str (), inf_class.c_str ());
+          break;
         }
     }
-  else
-    error ("superiorto: invalid call from outside class constructor");
 
   return retval;
 }
@@ -2243,45 +2235,36 @@
   octave_value retval;
 
   octave_function *fcn = octave_call_stack::caller ();
-
-  if (fcn && fcn->is_class_constructor ())
+  if ((! fcn) || (! fcn->is_class_constructor ()))
     {
-      for (int i = 0; i < args.length (); i++)
-        {
-          std::string class_name = args(i).string_value ();
-
-          if (! error_state)
-            {
-              if (! is_built_in_class (class_name))
-                {
-                  std::string this_class_name = fcn->name ();
-
-                  symbol_table::set_class_relationship (class_name,
-                                                        this_class_name);
+      error ("inferiorto: invalid call from outside class constructor");
+      return retval;
+    }
 
-                  if (! symbol_table::set_class_relationship (this_class_name,
-                                                              class_name))
-                    {
-                      error ("inferiorto: precedence already set for %s and %s",
-                             this_class_name.c_str (), class_name.c_str ());
-                      break;
-                    }
-                }
-              else
-                {
-                  error ("inferiorto: cannot give user-defined class lower precedence than built-in class");
-                  break;
-                }
-            }
-          else
-            {
-              error ("inferiorto: expecting argument to be class name");
-              break;
-            }
+  for (int i = 0; i < args.length (); i++)
+    {
+      std::string sup_class = args(i).string_value ();
+      if (error_state)
+        {
+          error ("inferiorto: expecting argument to be class name");
+          break;
+        }
+
+      if (is_built_in_class (sup_class))
+        {
+          error ("inferiorto: cannot give user-defined class lower "
+                 "precedence than built-in class");
+          break;
+        }
+
+      std::string inf_class = fcn->name ();
+      if (! symbol_table::set_class_relationship (sup_class, inf_class))
+        {
+          error ("inferiorto: opposite precedence already set for %s and %s",
+                 inf_class.c_str (), sup_class.c_str ());
+          break;
         }
     }
-  else
-    error ("inferiorto: invalid call from outside class constructor");
 
   return retval;
 }
--- a/libinterp/octave-value/ov-java.cc	Mon Feb 11 15:45:26 2013 -0500
+++ b/libinterp/octave-value/ov-java.cc	Thu Feb 28 02:04:24 2013 -0500
@@ -26,6 +26,11 @@
 
 #include "defun.h"
 #include "error.h"
+#include "fpucw.h"
+
+#if HAVE_FPU_CONTROL_H
+#include <fpu_control.h>
+#endif
 
 #if defined HAVE_JAVA
 
@@ -392,6 +397,22 @@
   return retval;
 }
 
+#ifndef _FPU_DEFAULT
+#if defined __i386__ || defined __x86_64__
+#define _FPU_DEFAULT 0x037f
+#else
+#define _FPU_DEFAULT 0
+#endif
+#endif
+
+static void
+restore_fpu_state (void)
+{
+  fpucw_t cw = GET_FPUCW ();
+  if (cw != _FPU_DEFAULT)
+    SET_FPUCW (_FPU_DEFAULT);
+}
+
 static void
 initialize_jvm (void)
 {
@@ -583,6 +604,8 @@
 
       if (jvm_lib)
         jvm_lib.close ();
+
+      restore_fpu_state ();
     }
 }
 
@@ -742,6 +765,8 @@
       idx++;
     }
 
+  restore_fpu_state ();
+
   return dv;
 }
 
@@ -798,6 +823,8 @@
   else
     retval = check_exception (jni_env);
 
+  restore_fpu_state ();
+
   return retval;
 }
 
@@ -826,6 +853,8 @@
   else
     retval = check_exception (jni_env);
 
+  restore_fpu_state ();
+
   return retval;
 }
 
@@ -862,6 +891,8 @@
           jstring_ref fieldName (jni_env, reinterpret_cast<jstring> (jni_env->CallObjectMethod (field, f_getName_ID)));
           name_list.push_back (jstring_to_string (jni_env, fieldName));
         }
+
+      restore_fpu_state ();
     }
 
   string_vector v (name_list);
@@ -921,6 +952,8 @@
         }
       else
         error ("unable to convert Java object to string");
+
+      restore_fpu_state ();
     }
 
   return retval;
@@ -1155,6 +1188,8 @@
   if (retval.is_undefined ())
     retval = octave_value (new octave_java (jobj, jcls));
 
+  restore_fpu_state ();
+
   return retval;
 }
 
@@ -1381,6 +1416,8 @@
       jclass_ref cls (current_env, find_octave_class (current_env, "org/octave/Octave"));
       jmethodID mID = current_env->GetStaticMethodID (cls, "checkPendingAction", "()V");
       current_env->CallStaticVoidMethod (cls, mID);
+
+      restore_fpu_state ();
     }
 
   return 0;
@@ -1406,6 +1443,8 @@
         {
           error (msg.c_str ());
         }
+
+      restore_fpu_state ();
     }
 }
 
@@ -1738,6 +1777,8 @@
           else
             retval = check_exception (jni_env);
         }
+
+      restore_fpu_state ();
     }
 
   return retval;
@@ -1768,6 +1809,8 @@
           else
             retval = check_exception (jni_env);
         }
+
+      restore_fpu_state ();
     }
 
   return retval;
@@ -1797,6 +1840,8 @@
           else
             check_exception (jni_env);
         }
+
+      restore_fpu_state ();
     }
 
   return retval;
@@ -1820,6 +1865,8 @@
         retval = box (jni_env, resObj);
       else
         retval = check_exception (jni_env);
+
+      restore_fpu_state ();
     }
 
   return retval;
@@ -1844,6 +1891,8 @@
         retval = box (jni_env, resObj);
       else
         retval = check_exception (jni_env);
+
+      restore_fpu_state ();
     }
 
   return retval;
@@ -1869,6 +1918,8 @@
           jni_env->CallStaticObjectMethod (helperClass, mID, to_java (), jstring (fName), jobject (jobj));
           check_exception (jni_env);
         }
+
+      restore_fpu_state ();
     }
 
   return retval;
@@ -1895,6 +1946,8 @@
           jni_env->CallStaticObjectMethod (helperClass, mID, jstring (cName), jstring (fName), jobject (jobj));
           check_exception (jni_env);
         }
+
+      restore_fpu_state ();
     }
 
   return retval;
--- a/libinterp/octave-value/ov-usr-fcn.cc	Mon Feb 11 15:45:26 2013 -0500
+++ b/libinterp/octave-value/ov-usr-fcn.cc	Thu Feb 28 02:04:24 2013 -0500
@@ -517,7 +517,9 @@
       tree_expression *expr = special_expr ();
 
       if (expr)
-        retval = expr->rvalue (nargout);
+        retval = (lvalue_list
+                  ? expr->rvalue (nargout, lvalue_list)
+                  : expr->rvalue (nargout));
     }
   else
     cmd_list->accept (*current_evaluator);
@@ -1042,4 +1044,24 @@
 %!test
 %! [x, y] = try_isargout ();
 %! assert ([x, y], [1, 2]);
+%!
+%% It should work without ():
+%!test
+%! [~, y] = try_isargout;
+%! assert (y, -2);
+%!
+%% It should work in function handles, anonymous functions, and cell
+%% arrays of handles or anonymous functions.
+%!test
+%! fh = @try_isargout;
+%! af = @() try_isargout;
+%! c = {fh, af};
+%! [~, y] = fh ();
+%! assert (y, -2);
+%! [~, y] = af ();
+%! assert (y, -2);
+%! [~, y] = c{1}();
+%! assert (y, -2);
+%! [~, y] = c{2}();
+%! assert (y, -2);
 */
--- a/libinterp/octave-value/ov.cc	Mon Feb 11 15:45:26 2013 -0500
+++ b/libinterp/octave-value/ov.cc	Thu Feb 28 02:04:24 2013 -0500
@@ -1313,6 +1313,23 @@
     return *this;
 }
 
+octave_value_list
+octave_value::next_subsref (int nargout, const std::string& type,
+                            const std::list<octave_value_list>& idx,
+                            const std::list<octave_lvalue> *lvalue_list,
+                            size_t skip)
+{
+  if (! error_state && idx.size () > skip)
+    {
+      std::list<octave_value_list> new_idx (idx);
+      for (size_t i = 0; i < skip; i++)
+        new_idx.erase (new_idx.begin ());
+      return subsref (type.substr (skip), new_idx, nargout, lvalue_list);
+    }
+  else
+    return *this;
+}
+
 octave_value
 octave_value::next_subsref (bool auto_add, const std::string& type,
                             const std::list<octave_value_list>& idx,
--- a/libinterp/octave-value/ov.h	Mon Feb 11 15:45:26 2013 -0500
+++ b/libinterp/octave-value/ov.h	Thu Feb 28 02:04:24 2013 -0500
@@ -419,6 +419,12 @@
                                   std::list<octave_value_list>& idx,
                                   size_t skip = 1);
 
+  octave_value_list next_subsref (int nargout,
+                                  const std::string& type, const
+                                  std::list<octave_value_list>& idx,
+                                  const std::list<octave_lvalue> *lvalue_list,
+                                  size_t skip = 1);
+
   octave_value next_subsref (bool auto_add, const std::string& type, const
                              std::list<octave_value_list>& idx,
                              size_t skip = 1);
--- a/libinterp/octave.cc	Mon Feb 11 15:45:26 2013 -0500
+++ b/libinterp/octave.cc	Thu Feb 28 02:04:24 2013 -0500
@@ -1000,9 +1000,6 @@
   // Now argv should have the full set of args.
   intern_argv (octave_cmdline_argc, octave_cmdline_argv);
 
-  if (! octave_embedded)
-    switch_to_buffer (create_buffer (get_input_from_stdin ()));
-
   // Force input to be echoed if not really interactive, but the user
   // has forced interactive behavior.
 
--- a/libinterp/parse-tree/lex.h	Mon Feb 11 15:45:26 2013 -0500
+++ b/libinterp/parse-tree/lex.h	Thu Feb 28 02:04:24 2013 -0500
@@ -24,35 +24,34 @@
 #define octave_lex_h 1
 
 #include <list>
+#include <set>
 #include <stack>
 
-// FIXME -- these input buffer things should be members of a
-// parser input stream class.
-
-typedef struct yy_buffer_state *YY_BUFFER_STATE;
-
-// Associate a buffer with a new file to read.
-extern OCTINTERP_API YY_BUFFER_STATE create_buffer (FILE *f);
-
-// Report the current buffer.
-extern OCTINTERP_API YY_BUFFER_STATE current_buffer (void);
-
-// Connect to new buffer buffer.
-extern OCTINTERP_API void switch_to_buffer (YY_BUFFER_STATE buf);
-
-// Delete a buffer.
-extern OCTINTERP_API void delete_buffer (YY_BUFFER_STATE buf);
-
-extern OCTINTERP_API void clear_all_buffers (void);
-
 extern OCTINTERP_API void cleanup_parser (void);
 
 // Is the given string a keyword?
 extern bool is_keyword (const std::string& s);
 
-extern void prep_lexer_for_script_file (void);
-extern void prep_lexer_for_function_file (void);
-extern void prep_lexer_for_classdef_file (void);
+class
+stream_reader
+{
+public:
+  virtual int getc (void) = 0;
+  virtual int ungetc (int c) = 0;
+
+protected:
+  stream_reader (void) { }
+  ~stream_reader (void) { }
+
+private:
+
+  // No copying!
+  stream_reader (const stream_reader&);
+  stream_reader& operator = (const stream_reader&);
+};
+
+// Forward decl for lexical_feedback::token_stack.
+class token;
 
 // For communication between the lexer and parser.
 
@@ -61,53 +60,234 @@
 {
 public:
 
-  lexical_feedback (void)
+  // Did eat_whitespace or eat_continuation eat a space or tab, or a
+  // newline, or both?
+  //
+  // Functions that return this type will return a logical OR of the
+  // following values:
+  //
+  //  NO_WHITESPACE  no spaces to eat
+  //  SPACE_OR_TAB   space or tab in input
+  //  NEWLINE        bare new line in input
+
+  enum whitespace_type
+    {
+      NO_WHITESPACE = 1,
+      SPACE_OR_TAB = 2,
+      NEWLINE = 4
+    };
+
+  // Track nesting of square brackets, curly braces, and parentheses.
+
+  class bbp_nesting_level
+  {
+  private:
 
-    : bracketflag (0), braceflag (0), looping (0),
-      convert_spaces_to_comma (true), at_beginning_of_statement (true),
-      defining_func (0), looking_at_function_handle (0),
-      looking_at_anon_fcn_args (true),
-      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_at_object_index (),
-      looking_for_object_index (false), do_comma_insert (false),
-      looking_at_indirect_ref (false), parsed_function_name (),
-      parsing_class_method (false), maybe_classdef_get_set_method (false),
-      parsing_classdef (false), parsing_classdef_get_method (false),
-      parsing_classdef_set_method (false), quote_is_transpose (false),
-      pending_local_variables ()
+    enum bracket_type
+      {
+        BRACKET = 1,
+        BRACE = 2,
+        PAREN = 3
+      };
+
+  public:
+
+    bbp_nesting_level (void) : context () { }
+
+    bbp_nesting_level (const bbp_nesting_level& nl) : context (nl.context) { }
 
+    bbp_nesting_level& operator = (const bbp_nesting_level& nl)
     {
-      init ();
+      if (&nl != this)
+        context = nl.context;
+
+      return *this;
+    }
+
+    ~bbp_nesting_level (void) { }
+
+    void bracket (void) { context.push (BRACKET); }
+
+    bool is_bracket (void)
+    {
+      return ! context.empty () && context.top () == BRACKET;
     }
 
-  ~lexical_feedback (void) { }
+    void brace (void) { context.push (BRACE); }
+
+    bool is_brace (void)
+    {
+      return ! context.empty () && context.top () == BRACE;
+    }
+
+    void paren (void) { context.push (PAREN); }
+
+    bool is_paren (void)
+    {
+      return ! context.empty () && context.top () == PAREN;
+    }
+
+    bool is_bracket_or_brace (void)
+    {
+      return (! context.empty ()
+              && (context.top () == BRACKET || context.top () == BRACE));
+    }
+
+    bool none (void) { return context.empty (); }
+
+    void remove (void)
+    {
+      if (! context.empty ())
+        context.pop ();
+    }
+
+    void clear (void)
+    {
+      while (! context.empty ())
+        context.pop ();
+    }
+
+  private:
+
+    std::stack<int> context;
+  };
+
+  lexical_feedback (void)
+    : scanner (0), 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),
+      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),
+      looking_at_object_index (), parsed_function_name (),
+      pending_local_variables (), nesting_level ()
+  {
+    init ();
+  }
+
+  ~lexical_feedback (void);
 
   void init (void);
 
-  // Square bracket level count.
-  int bracketflag;
+  void reset (void);
+
+  void prep_for_script_file (void);
+
+  void prep_for_function_file (void);
+
+  void prep_for_classdef_file (void);
+
+  int octave_read (char *buf, unsigned int max_size);
+
+  char *flex_yytext (void);
+
+  int flex_yyleng (void);
+
+  void do_comma_insert_check (void);
+
+  int text_yyinput (void);
+
+  void xunput (char c, char *buf);
+
+  void xunput (char c);
+
+  void fixup_column_count (char *s);
+
+  bool inside_any_object_index (void);
+
+  int is_keyword_token (const std::string& s);
+
+  bool is_variable (const std::string& name);
+
+  std::string grab_block_comment (stream_reader& reader, bool& eof);
+
+  std::string grab_comment_block (stream_reader& reader, bool at_bol,
+                                  bool& eof);
+
+  int process_comment (bool start_in_block, bool& eof);
+
+  bool next_token_is_sep_op (void);
+
+  bool next_token_is_postfix_unary_op (bool spc_prev);
+
+  bool next_token_is_bin_op (bool spc_prev);
+
+  void scan_for_comments (const char *text);
+
+  int eat_whitespace (void);
+
+  void handle_number (void);
 
-  // Curly brace level count.
-  int braceflag;
+  bool have_continuation (bool trailing_comments_ok = true);
+
+  bool have_ellipsis_continuation (bool trailing_comments_ok = true);
+
+  int eat_continuation (void);
+
+  int handle_string (char delim);
+
+  bool next_token_is_assign_op (void);
+
+  bool next_token_is_index_op (void);
+
+  int handle_close_bracket (bool spc_gobbled, int bracket_type);
+
+  void maybe_unput_comma (int spc_gobbled);
+
+  bool next_token_can_follow_bin_op (void);
+
+  bool looks_like_command_arg (void);
+
+  int handle_superclass_identifier (void);
+
+  int handle_meta_identifier (void);
 
-  // TRUE means we're in the middle of defining a loop.
-  int looping;
+  int handle_identifier (void);
+
+  void maybe_warn_separator_insert (char sep);
+
+  void gripe_single_quote_string (void);
+
+  void gripe_matlab_incompatible (const std::string& msg);
+
+  void maybe_gripe_matlab_incompatible_comment (char c);
+
+  void gripe_matlab_incompatible_continuation (void);
+
+  void gripe_matlab_incompatible_operator (const std::string& op);
+
+  void push_token (token *);
+
+  token *current_token (void);
+
+  void display_token (int tok);
+
+  void fatal_error (const char *msg);
+
+  void lexer_debug (const char *pattern, const char *text);
+
+  // 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;
 
+  // GAG.  Stupid kludge so that [[1,2][3,4]] will work.
+  bool do_comma_insert;
+
   // TRUE means we are at the beginning of a statement, where a
   // command name is possible.
   bool at_beginning_of_statement;
 
-  // 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;
-
   // TRUE means we are parsing an anonymous function argument list.
   bool looking_at_anon_fcn_args;
 
@@ -129,25 +309,13 @@
   // multi-value assignment statement.
   bool looking_at_matrix_or_assign_lhs;
 
-  // 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;
-
   // Object index not possible until we've seen something.
   bool looking_for_object_index;
 
-  // GAG.  Stupid kludge so that [[1,2][3,4]] will work.
-  bool do_comma_insert;
-
   // TRUE means we're looking at an indirect reference to a
   // structure element.
   bool looking_at_indirect_ref;
 
-  // 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;
-
   // TRUE means we are parsing a class method in function or classdef file.
   bool parsing_class_method;
 
@@ -168,41 +336,61 @@
   // Return transpose or start a string?
   bool quote_is_transpose;
 
+  // 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;
+
+  // 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;
+
+  // For unwind protect.
+  static void cleanup (lexical_feedback *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&);
 
   lexical_feedback& operator = (const lexical_feedback&);
 };
 
-class
-stream_reader
-{
-public:
-  virtual int getc (void) = 0;
-  virtual int ungetc (int c) = 0;
-
-protected:
-  stream_reader (void) { }
-  ~stream_reader (void) { }
-
-private:
-
-  // No copying!
-  stream_reader (const stream_reader&);
-  stream_reader& operator = (const stream_reader&);
-};
-
-extern std::string
-grab_comment_block (stream_reader& reader, bool at_bol, bool& eof);
-
-// TRUE means that we have encountered EOF on the input stream.
-extern bool parser_end_of_input;
-
-// Flags that need to be shared between the lexer and parser.
-extern lexical_feedback lexer_flags;
-
 #endif
--- a/libinterp/parse-tree/lex.ll	Mon Feb 11 15:45:26 2013 -0500
+++ b/libinterp/parse-tree/lex.ll	Thu Feb 28 02:04:24 2013 -0500
@@ -20,7 +20,21 @@
 
 */
 
+/*
+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.
+*/
+
 %option prefix = "octave_"
+%option noyywrap
+%option reentrant
+%option bison-bridge
 
 %top {
 #ifdef HAVE_CONFIG_H
@@ -54,9 +68,9 @@
 #include "quit.h"
 #include "lo-mappers.h"
 
-// These would be alphabetical, but y.tab.h must be included before
-// oct-gperf.h and y.tab.h must be included after token.h and the tree
-// class declarations.  We can't include y.tab.h in oct-gperf.h
+// These would be alphabetical, but oct-parse.h must be included before
+// oct-gperf.h and oct-parse.h must be included after token.h and the tree
+// class declarations.  We can't include oct-parse.h in oct-gperf.h
 // because it may not be protected to allow it to be included multiple
 // times.
 
@@ -96,7 +110,8 @@
 #error lex.l requires flex version 2.5.4 or later
 #endif
 
-#define yylval octave_lval
+#define YY_EXTRA_TYPE lexical_feedback *
+#define curr_lexer yyextra
 
 // Arrange to get input via readline.
 
@@ -104,35 +119,26 @@
 #undef YY_INPUT
 #endif
 #define YY_INPUT(buf, result, max_size) \
-  if ((result = octave_read (buf, max_size)) < 0) \
-    YY_FATAL_ERROR ("octave_read () in flex scanner failed");
+  result = curr_lexer->octave_read (buf, max_size)
 
 // Try to avoid crashing out completely on fatal scanner errors.
-// The call to yy_fatal_error should never happen, but it avoids a
-// 'static function defined but not used' warning from gcc.
 
 #ifdef YY_FATAL_ERROR
 #undef YY_FATAL_ERROR
 #endif
 #define YY_FATAL_ERROR(msg) \
-  do \
-    { \
-      error (msg); \
-      OCTAVE_QUIT; \
-      yy_fatal_error (msg); \
-    } \
-  while (0)
+  (yyget_extra (yyscanner))->fatal_error (msg)
 
 #define DISPLAY_TOK_AND_RETURN(tok) \
   do \
     { \
       int tok_val = tok; \
       if (Vdisplay_tokens) \
-        display_token (tok_val); \
+        curr_lexer->display_token (tok_val); \
       if (lexer_debug_flag) \
         { \
           std::cerr << "R: "; \
-          display_token (tok_val); \
+          curr_lexer->display_token (tok_val); \
           std::cerr << std::endl;  \
         } \
       return tok_val; \
@@ -150,9 +156,9 @@
 #define TOK_RETURN(tok) \
   do \
     { \
-      current_input_column += yyleng; \
-      lexer_flags.quote_is_transpose = false; \
-      lexer_flags.convert_spaces_to_comma = true; \
+      curr_lexer->current_input_column += yyleng; \
+      curr_lexer->quote_is_transpose = false; \
+      curr_lexer->convert_spaces_to_comma = true; \
       COUNT_TOK_AND_RETURN (tok); \
     } \
   while (0)
@@ -160,9 +166,9 @@
 #define TOK_PUSH_AND_RETURN(name, tok) \
   do \
     { \
-      yylval.tok_val = new token (name, input_line_number, \
-                                  current_input_column); \
-      token_stack.push (yylval.tok_val); \
+      curr_lexer->push_token \
+        (new token (name, curr_lexer->input_line_number, \
+         curr_lexer->current_input_column)); \
       TOK_RETURN (tok); \
     } \
   while (0)
@@ -170,13 +176,14 @@
 #define BIN_OP_RETURN_INTERNAL(tok, convert, bos, qit) \
   do \
     { \
-      yylval.tok_val = new token (input_line_number, current_input_column); \
-      token_stack.push (yylval.tok_val); \
-      current_input_column += yyleng; \
-      lexer_flags.quote_is_transpose = qit; \
-      lexer_flags.convert_spaces_to_comma = convert; \
-      lexer_flags.looking_for_object_index = false; \
-      lexer_flags.at_beginning_of_statement = bos; \
+      curr_lexer->push_token \
+        (new token (curr_lexer->input_line_number, \
+         curr_lexer->current_input_column)); \
+      curr_lexer->current_input_column += yyleng; \
+      curr_lexer->quote_is_transpose = qit; \
+      curr_lexer->convert_spaces_to_comma = convert; \
+      curr_lexer->looking_for_object_index = false; \
+      curr_lexer->at_beginning_of_statement = bos; \
       COUNT_TOK_AND_RETURN (tok); \
     } \
   while (0)
@@ -184,7 +191,7 @@
 #define XBIN_OP_RETURN_INTERNAL(tok, convert, bos, qit) \
   do \
     { \
-      gripe_matlab_incompatible_operator (yytext); \
+      curr_lexer->gripe_matlab_incompatible_operator (yytext); \
       BIN_OP_RETURN_INTERNAL (tok, convert, bos, qit); \
     } \
   while (0)
@@ -199,7 +206,7 @@
 #define XBIN_OP_RETURN(tok, convert, bos) \
   do \
     { \
-      gripe_matlab_incompatible_operator (yytext); \
+      curr_lexer->gripe_matlab_incompatible_operator (yytext); \
       BIN_OP_RETURN (tok, convert, bos); \
     } \
   while (0)
@@ -208,129 +215,21 @@
   do \
     { \
       if (lexer_debug_flag) \
-        lexer_debug (pattern, yytext); \
+        curr_lexer->lexer_debug (pattern, yytext); \
     } \
   while (0)
 
-// TRUE means that we have encountered EOF on the input stream.
-bool parser_end_of_input = false;
-
-// Flags that need to be shared between the lexer and parser.
-lexical_feedback lexer_flags;
-
-// 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.  This has to appear before lex.h is included, because
-// one of the macros defined there uses token_stack.
-//
-// FIXME -- this should really be static, but that causes
-// problems on some systems.
-std::stack <token*> token_stack;
-
-// Did eat_whitespace() eat a space or tab, or a newline, or both?
-
-typedef int yum_yum;
-
-const yum_yum ATE_NOTHING = 0;
-const yum_yum ATE_SPACE_OR_TAB = 1;
-const yum_yum ATE_NEWLINE = 2;
-
-// Is the closest nesting level a square bracket, squiggly brace or a paren?
-
-class bracket_brace_paren_nesting_level
-{
-public:
-
-  bracket_brace_paren_nesting_level (void) : context () { }
-
-  ~bracket_brace_paren_nesting_level (void) { }
-
-  void bracket (void) { context.push (BRACKET); }
-  bool is_bracket (void)
-    { return ! context.empty () && context.top () == BRACKET; }
-
-  void brace (void) {  context.push (BRACE); }
-  bool is_brace (void)
-    { return ! context.empty () && context.top () == BRACE; }
-
-  void paren (void) {  context.push (PAREN); }
-  bool is_paren (void)
-    { return ! context.empty () && context.top () == PAREN; }
-
-  bool is_bracket_or_brace (void)
-    { return (! context.empty ()
-              && (context.top () == BRACKET || context.top () == BRACE)); }
-
-  bool none (void) { return context.empty (); }
-
-  void remove (void) { if (! context.empty ()) context.pop (); }
-
-  void clear (void) { while (! context.empty ()) context.pop (); }
-
-private:
-
-  std::stack<int> context;
-
-  static const int BRACKET;
-  static const int BRACE;
-  static const int PAREN;
-
-  bracket_brace_paren_nesting_level (const bracket_brace_paren_nesting_level&);
-
-  bracket_brace_paren_nesting_level&
-  operator = (const bracket_brace_paren_nesting_level&);
-};
-
-const int bracket_brace_paren_nesting_level::BRACKET = 1;
-const int bracket_brace_paren_nesting_level::BRACE = 2;
-const int bracket_brace_paren_nesting_level::PAREN = 3;
-
-static bracket_brace_paren_nesting_level nesting_level;
-
 static bool Vdisplay_tokens = false;
 
 static unsigned int Vtoken_count = 0;
 
-// The start state that was in effect when the beginning of a block
-// comment was noticed.
-static int block_comment_nesting_level = 0;
-
 // Internal variable for lexer debugging state.
 static bool lexer_debug_flag = false;
 
 // Forward declarations for functions defined at the bottom of this
-// file.
-
-static int text_yyinput (void);
-static void xunput (char c, char *buf);
-static void fixup_column_count (char *s);
-static void do_comma_insert_check (void);
-static int is_keyword_token (const std::string& s);
-static int process_comment (bool start_in_block, bool& eof);
-static bool match_any (char c, const char *s);
-static bool next_token_is_sep_op (void);
-static bool next_token_is_bin_op (bool spc_prev);
-static bool next_token_is_postfix_unary_op (bool spc_prev);
+// file that are needed inside the lexer actions.
+
 static std::string strip_trailing_whitespace (char *s);
-static void handle_number (void);
-static int handle_string (char delim);
-static int handle_close_bracket (bool spc_gobbled, int bracket_type);
-static int handle_superclass_identifier (void);
-static int handle_meta_identifier (void);
-static int handle_identifier (void);
-static bool have_continuation (bool trailing_comments_ok = true);
-static bool have_ellipsis_continuation (bool trailing_comments_ok = true);
-static void scan_for_comments (const char *);
-static yum_yum eat_whitespace (void);
-static yum_yum eat_continuation (void);
-static void maybe_warn_separator_insert (char sep);
-static void gripe_single_quote_string (void);
-static void gripe_matlab_incompatible (const std::string& msg);
-static void maybe_gripe_matlab_incompatible_comment (char c);
-static void gripe_matlab_incompatible_continuation (void);
-static void gripe_matlab_incompatible_operator (const std::string& op);
-static void display_token (int tok);
-static void lexer_debug (const char *pattern, const char *text);
 
 %}
 
@@ -362,7 +261,7 @@
     LEXER_DEBUG ("<SCRIPT_FILE_BEGIN>.");
 
     BEGIN (INITIAL);
-    xunput (yytext[0], yytext);
+    curr_lexer->xunput (yytext[0]);
     COUNT_TOK_AND_RETURN (SCRIPT_FILE);
   }
 
@@ -370,7 +269,7 @@
     LEXER_DEBUG ("<FUNCTION_FILE_BEGIN>.");
 
     BEGIN (INITIAL);
-    xunput (yytext[0], yytext);
+    curr_lexer->xunput (yytext[0]);
     COUNT_TOK_AND_RETURN (FUNCTION_FILE);
   }
 
@@ -378,7 +277,7 @@
     LEXER_DEBUG ("<CLASSDEF_FILE_BEGIN>.");
 
     BEGIN (INITIAL);
-    xunput (yytext[0], yytext);
+    curr_lexer->xunput (yytext[0], yytext);
     COUNT_TOK_AND_RETURN (CLASSDEF_FILE);
   }
 
@@ -390,13 +289,13 @@
     LEXER_DEBUG ("<COMMAND_START>{NL}");
 
     BEGIN (INITIAL);
-    input_line_number++;
-    current_input_column = 1;
-
-    lexer_flags.quote_is_transpose = false;
-    lexer_flags.convert_spaces_to_comma = true;
-    lexer_flags.looking_for_object_index = false;
-    lexer_flags.at_beginning_of_statement = true;
+    curr_lexer->input_line_number++;
+    curr_lexer->current_input_column = 1;
+
+    curr_lexer->quote_is_transpose = false;
+    curr_lexer->convert_spaces_to_comma = true;
+    curr_lexer->looking_for_object_index = false;
+    curr_lexer->at_beginning_of_statement = true;
 
     COUNT_TOK_AND_RETURN ('\n');
   }
@@ -404,8 +303,8 @@
 <COMMAND_START>[\;\,] {
     LEXER_DEBUG ("<COMMAND_START>[\\;\\,]");
 
-    lexer_flags.looking_for_object_index = false;
-    lexer_flags.at_beginning_of_statement = true;
+    curr_lexer->looking_for_object_index = false;
+    curr_lexer->at_beginning_of_statement = true;
 
     BEGIN (INITIAL);
 
@@ -418,10 +317,10 @@
 <COMMAND_START>[\"\'] {
     LEXER_DEBUG ("<COMMAND_START>[\\\"\\']");
 
-    lexer_flags.at_beginning_of_statement = false;
-
-    current_input_column++;
-    int tok = handle_string (yytext[0]);
+    curr_lexer->at_beginning_of_statement = false;
+
+    curr_lexer->current_input_column++;
+    int tok = curr_lexer->handle_string (yytext[0]);
 
     COUNT_TOK_AND_RETURN (tok);
   }
@@ -431,8 +330,8 @@
 
     std::string tok = strip_trailing_whitespace (yytext);
 
-    lexer_flags.looking_for_object_index = false;
-    lexer_flags.at_beginning_of_statement = false;
+    curr_lexer->looking_for_object_index = false;
+    curr_lexer->at_beginning_of_statement = false;
 
     TOK_PUSH_AND_RETURN (tok, SQ_STRING);
   }
@@ -454,21 +353,21 @@
 <MATRIX_START>{SNLCMT}*\]{S}* {
     LEXER_DEBUG ("<MATRIX_START>{SNLCMT}*\\]{S}*");
 
-    scan_for_comments (yytext);
-    fixup_column_count (yytext);
-
-    lexer_flags.looking_at_object_index.pop_front ();
-
-    lexer_flags.looking_for_object_index = true;
-    lexer_flags.at_beginning_of_statement = false;
+    curr_lexer->scan_for_comments (yytext);
+    curr_lexer->fixup_column_count (yytext);
+
+    curr_lexer->looking_at_object_index.pop_front ();
+
+    curr_lexer->looking_for_object_index = true;
+    curr_lexer->at_beginning_of_statement = false;
 
     int c = yytext[yyleng-1];
-    int cont_is_spc = eat_continuation ();
+    bool cont_is_spc = (curr_lexer->eat_continuation () != lexical_feedback::NO_WHITESPACE);
     bool spc_gobbled = (cont_is_spc || c == ' ' || c == '\t');
-    int tok_to_return = handle_close_bracket (spc_gobbled, ']');
+    int tok_to_return = curr_lexer->handle_close_bracket (spc_gobbled, ']');
 
     if (spc_gobbled)
-      xunput (' ', yytext);
+      curr_lexer->xunput (' ');
 
     COUNT_TOK_AND_RETURN (tok_to_return);
   }
@@ -480,21 +379,21 @@
 <MATRIX_START>{SNLCMT}*\}{S}* {
     LEXER_DEBUG ("<MATRIX_START>{SNLCMT}*\\}{S}*");
 
-    scan_for_comments (yytext);
-    fixup_column_count (yytext);
-
-    lexer_flags.looking_at_object_index.pop_front ();
-
-    lexer_flags.looking_for_object_index = true;
-    lexer_flags.at_beginning_of_statement = false;
+    curr_lexer->scan_for_comments (yytext);
+    curr_lexer->fixup_column_count (yytext);
+
+    curr_lexer->looking_at_object_index.pop_front ();
+
+    curr_lexer->looking_for_object_index = true;
+    curr_lexer->at_beginning_of_statement = false;
 
     int c = yytext[yyleng-1];
-    int cont_is_spc = eat_continuation ();
+    bool cont_is_spc = (curr_lexer->eat_continuation () != lexical_feedback::NO_WHITESPACE);
     bool spc_gobbled = (cont_is_spc || c == ' ' || c == '\t');
-    int tok_to_return = handle_close_bracket (spc_gobbled, '}');
+    int tok_to_return = curr_lexer->handle_close_bracket (spc_gobbled, '}');
 
     if (spc_gobbled)
-      xunput (' ', yytext);
+      curr_lexer->xunput (' ');
 
     COUNT_TOK_AND_RETURN (tok_to_return);
   }
@@ -508,22 +407,22 @@
 <MATRIX_START>{S}*\,{S}* {
     LEXER_DEBUG ("<MATRIX_START>{S}*\\,{S}*");
 
-    current_input_column += yyleng;
-
-    int tmp = eat_continuation ();
-
-    lexer_flags.quote_is_transpose = false;
-    lexer_flags.convert_spaces_to_comma = true;
-    lexer_flags.looking_for_object_index = false;
-    lexer_flags.at_beginning_of_statement = false;
-
-    if (! lexer_flags.looking_at_object_index.front ())
+    curr_lexer->current_input_column += yyleng;
+
+    int tmp = curr_lexer->eat_continuation ();
+
+    curr_lexer->quote_is_transpose = false;
+    curr_lexer->convert_spaces_to_comma = true;
+    curr_lexer->looking_for_object_index = false;
+    curr_lexer->at_beginning_of_statement = false;
+
+    if (! curr_lexer->looking_at_object_index.front ())
       {
-        if ((tmp & ATE_NEWLINE) == ATE_NEWLINE)
+        if ((tmp & lexical_feedback::NEWLINE) == lexical_feedback::NEWLINE)
           {
-            maybe_warn_separator_insert (';');
-
-            xunput (';', yytext);
+            curr_lexer->maybe_warn_separator_insert (';');
+
+            curr_lexer->xunput (';');
           }
       }
 
@@ -540,34 +439,34 @@
 <MATRIX_START>{S}+ {
     LEXER_DEBUG ("<MATRIX_START>{S}+");
 
-    current_input_column += yyleng;
-
-    lexer_flags.at_beginning_of_statement = false;
-
-    int tmp = eat_continuation ();
-
-    if (! lexer_flags.looking_at_object_index.front ())
+    curr_lexer->current_input_column += yyleng;
+
+    curr_lexer->at_beginning_of_statement = false;
+
+    int tmp = curr_lexer->eat_continuation ();
+
+    if (! curr_lexer->looking_at_object_index.front ())
       {
-        bool bin_op = next_token_is_bin_op (true);
-        bool postfix_un_op = next_token_is_postfix_unary_op (true);
-        bool sep_op = next_token_is_sep_op ();
+        bool bin_op = curr_lexer->next_token_is_bin_op (true);
+        bool postfix_un_op = curr_lexer->next_token_is_postfix_unary_op (true);
+        bool sep_op = curr_lexer->next_token_is_sep_op ();
 
         if (! (postfix_un_op || bin_op || sep_op)
-            && nesting_level.is_bracket_or_brace ()
-            && lexer_flags.convert_spaces_to_comma)
+            && curr_lexer->nesting_level.is_bracket_or_brace ()
+            && curr_lexer->convert_spaces_to_comma)
           {
-            if ((tmp & ATE_NEWLINE) == ATE_NEWLINE)
+            if ((tmp & lexical_feedback::NEWLINE) == lexical_feedback::NEWLINE)
               {
-                maybe_warn_separator_insert (';');
-
-                xunput (';', yytext);
+                curr_lexer->maybe_warn_separator_insert (';');
+
+                curr_lexer->xunput (';');
               }
 
-            lexer_flags.quote_is_transpose = false;
-            lexer_flags.convert_spaces_to_comma = true;
-            lexer_flags.looking_for_object_index = false;
-
-            maybe_warn_separator_insert (',');
+            curr_lexer->quote_is_transpose = false;
+            curr_lexer->convert_spaces_to_comma = true;
+            curr_lexer->looking_for_object_index = false;
+
+            curr_lexer->maybe_warn_separator_insert (',');
 
             COUNT_TOK_AND_RETURN (',');
           }
@@ -585,14 +484,14 @@
 <MATRIX_START>{SNLCMT}*;{SNLCMT}* {
     LEXER_DEBUG ("<MATRIX_START>{SNLCMT}*;{SNLCMT}*");
 
-    scan_for_comments (yytext);
-    fixup_column_count (yytext);
-    eat_whitespace ();
-
-    lexer_flags.quote_is_transpose = false;
-    lexer_flags.convert_spaces_to_comma = true;
-    lexer_flags.looking_for_object_index = false;
-    lexer_flags.at_beginning_of_statement = false;
+    curr_lexer->scan_for_comments (yytext);
+    curr_lexer->fixup_column_count (yytext);
+    curr_lexer->eat_whitespace ();
+
+    curr_lexer->quote_is_transpose = false;
+    curr_lexer->convert_spaces_to_comma = true;
+    curr_lexer->looking_for_object_index = false;
+    curr_lexer->at_beginning_of_statement = false;
 
     COUNT_TOK_AND_RETURN (';');
   }
@@ -609,21 +508,21 @@
 <MATRIX_START>{S}*{NL}{SNLCMT}* {
     LEXER_DEBUG ("<MATRIX_START>{S}*{COMMENT}{SNLCMT}*|<MATRIX_START>{S}*{NL}{SNLCMT}*");
 
-    scan_for_comments (yytext);
-    fixup_column_count (yytext);
-    eat_whitespace ();
-
-    lexer_flags.quote_is_transpose = false;
-    lexer_flags.convert_spaces_to_comma = true;
-    lexer_flags.at_beginning_of_statement = false;
-
-    if (nesting_level.none ())
+    curr_lexer->scan_for_comments (yytext);
+    curr_lexer->fixup_column_count (yytext);
+    curr_lexer->eat_whitespace ();
+
+    curr_lexer->quote_is_transpose = false;
+    curr_lexer->convert_spaces_to_comma = true;
+    curr_lexer->at_beginning_of_statement = false;
+
+    if (curr_lexer->nesting_level.none ())
       return LEXICAL_ERROR;
 
-    if (! lexer_flags.looking_at_object_index.front ()
-        && nesting_level.is_bracket_or_brace ())
+    if (! curr_lexer->looking_at_object_index.front ()
+        && curr_lexer->nesting_level.is_bracket_or_brace ())
       {
-        maybe_warn_separator_insert (';');
+        curr_lexer->maybe_warn_separator_insert (';');
 
         COUNT_TOK_AND_RETURN (';');
       }
@@ -632,26 +531,26 @@
 \[{S}* {
     LEXER_DEBUG ("\\[{S}*");
 
-    nesting_level.bracket ();
-
-    lexer_flags.looking_at_object_index.push_front (false);
-
-    current_input_column += yyleng;
-    lexer_flags.quote_is_transpose = false;
-    lexer_flags.convert_spaces_to_comma = true;
-    lexer_flags.looking_for_object_index = false;
-    lexer_flags.at_beginning_of_statement = false;
-
-    if (lexer_flags.defining_func
-        && ! lexer_flags.parsed_function_name.top ())
-      lexer_flags.looking_at_return_list = true;
+    curr_lexer->nesting_level.bracket ();
+
+    curr_lexer->looking_at_object_index.push_front (false);
+
+    curr_lexer->current_input_column += yyleng;
+    curr_lexer->quote_is_transpose = false;
+    curr_lexer->convert_spaces_to_comma = true;
+    curr_lexer->looking_for_object_index = false;
+    curr_lexer->at_beginning_of_statement = false;
+
+    if (curr_lexer->defining_func
+        && ! curr_lexer->parsed_function_name.top ())
+      curr_lexer->looking_at_return_list = true;
     else
-      lexer_flags.looking_at_matrix_or_assign_lhs = true;
+      curr_lexer->looking_at_matrix_or_assign_lhs = true;
 
     promptflag--;
-    eat_whitespace ();
-
-    lexer_flags.bracketflag++;
+    curr_lexer->eat_whitespace ();
+
+    curr_lexer->bracketflag++;
     BEGIN (MATRIX_START);
     COUNT_TOK_AND_RETURN ('[');
   }
@@ -659,12 +558,12 @@
 \] {
     LEXER_DEBUG ("\\]");
 
-    nesting_level.remove ();
-
-    lexer_flags.looking_at_object_index.pop_front ();
-
-    lexer_flags.looking_for_object_index = true;
-    lexer_flags.at_beginning_of_statement = false;
+    curr_lexer->nesting_level.remove ();
+
+    curr_lexer->looking_at_object_index.pop_front ();
+
+    curr_lexer->looking_for_object_index = true;
+    curr_lexer->at_beginning_of_statement = false;
 
     TOK_RETURN (']');
   }
@@ -676,7 +575,7 @@
 {NUMBER}{Im} {
     LEXER_DEBUG ("{NUMBER}{Im}");
 
-    handle_number ();
+    curr_lexer->handle_number ();
     COUNT_TOK_AND_RETURN (IMAG_NUM);
   }
 
@@ -688,7 +587,7 @@
 {D}+/\.[\*/\\^\'] |
 {NUMBER} {
     LEXER_DEBUG ("{D}+/\\.[\\*/\\^\\']|{NUMBER}");
-    handle_number ();
+    curr_lexer->handle_number ();
     COUNT_TOK_AND_RETURN (NUM);
   }
 
@@ -698,7 +597,7 @@
 %}
 
 {S}* {
-    current_input_column += yyleng;
+    curr_lexer->current_input_column += yyleng;
   }
 
 %{
@@ -710,11 +609,11 @@
     LEXER_DEBUG ("{CONT}{S}*{NL}|{CONT}{S}*{COMMENT}");
 
     if (yytext[0] == '\\')
-      gripe_matlab_incompatible_continuation ();
-    scan_for_comments (yytext);
+      curr_lexer->gripe_matlab_incompatible_continuation ();
+    curr_lexer->scan_for_comments (yytext);
     promptflag--;
-    input_line_number++;
-    current_input_column = 1;
+    curr_lexer->input_line_number++;
+    curr_lexer->current_input_column = 1;
   }
 
 %{
@@ -724,14 +623,14 @@
 <<EOF>> {
     LEXER_DEBUG ("<<EOF>>");
 
-    if (block_comment_nesting_level != 0)
+    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'",
-                   input_line_number, curr_fcn_file_name.c_str ());
+                   curr_lexer->input_line_number, curr_fcn_file_name.c_str ());
       }
 
     TOK_RETURN (END_OF_INPUT);
@@ -745,7 +644,7 @@
 {IDENT}{S}* {
     LEXER_DEBUG ("{IDENT}{S}*");
 
-    int id_tok = handle_identifier ();
+    int id_tok = curr_lexer->handle_identifier ();
 
     if (id_tok >= 0)
       COUNT_TOK_AND_RETURN (id_tok);
@@ -759,11 +658,11 @@
 {IDENT}@{IDENT}.{IDENT}{S}* {
     LEXER_DEBUG ("{IDENT}@{IDENT}{S}*|{IDENT}@{IDENT}.{IDENT}{S}*");
 
-    int id_tok = handle_superclass_identifier ();
+    int id_tok = curr_lexer->handle_superclass_identifier ();
 
     if (id_tok >= 0)
       {
-        lexer_flags.looking_for_object_index = true;
+        curr_lexer->looking_for_object_index = true;
 
         COUNT_TOK_AND_RETURN (id_tok);
       }
@@ -777,11 +676,11 @@
 \?{IDENT}\.{IDENT}{S}* {
     LEXER_DEBUG ("\\?{IDENT}{S}*|\\?{IDENT}\\.{IDENT}{S}*");
 
-    int id_tok = handle_meta_identifier ();
+    int id_tok = curr_lexer->handle_meta_identifier ();
 
     if (id_tok >= 0)
       {
-        lexer_flags.looking_for_object_index = true;
+        curr_lexer->looking_for_object_index = true;
 
         COUNT_TOK_AND_RETURN (id_tok);
       }
@@ -794,13 +693,13 @@
 "@" {
     LEXER_DEBUG ("@");
 
-    current_input_column++;
-
-    lexer_flags.quote_is_transpose = false;
-    lexer_flags.convert_spaces_to_comma = false;
-    lexer_flags.looking_at_function_handle++;
-    lexer_flags.looking_for_object_index = false;
-    lexer_flags.at_beginning_of_statement = false;
+    curr_lexer->current_input_column++;
+
+    curr_lexer->quote_is_transpose = false;
+    curr_lexer->convert_spaces_to_comma = false;
+    curr_lexer->looking_at_function_handle++;
+    curr_lexer->looking_for_object_index = false;
+    curr_lexer->at_beginning_of_statement = false;
 
     COUNT_TOK_AND_RETURN ('@');
 
@@ -815,23 +714,23 @@
 {NL} {
     LEXER_DEBUG ("{NL}");
 
-    input_line_number++;
-    current_input_column = 1;
-
-    lexer_flags.quote_is_transpose = false;
-    lexer_flags.convert_spaces_to_comma = true;
-
-    if (nesting_level.none ())
+    curr_lexer->input_line_number++;
+    curr_lexer->current_input_column = 1;
+
+    curr_lexer->quote_is_transpose = false;
+    curr_lexer->convert_spaces_to_comma = true;
+
+    if (curr_lexer->nesting_level.none ())
       {
-        lexer_flags.at_beginning_of_statement = true;
+        curr_lexer->at_beginning_of_statement = true;
         COUNT_TOK_AND_RETURN ('\n');
       }
-    else if (nesting_level.is_paren ())
+    else if (curr_lexer->nesting_level.is_paren ())
       {
-        lexer_flags.at_beginning_of_statement = false;
-        gripe_matlab_incompatible ("bare newline inside parentheses");
+        curr_lexer->at_beginning_of_statement = false;
+        curr_lexer->gripe_matlab_incompatible ("bare newline inside parentheses");
       }
-    else if (nesting_level.is_bracket_or_brace ())
+    else if (curr_lexer->nesting_level.is_bracket_or_brace ())
       return LEXICAL_ERROR;
   }
 
@@ -843,17 +742,17 @@
 "'" {
     LEXER_DEBUG ("'");
 
-    current_input_column++;
-    lexer_flags.convert_spaces_to_comma = true;
-
-    if (lexer_flags.quote_is_transpose)
+    curr_lexer->current_input_column++;
+    curr_lexer->convert_spaces_to_comma = true;
+
+    if (curr_lexer->quote_is_transpose)
       {
-        do_comma_insert_check ();
+        curr_lexer->do_comma_insert_check ();
         COUNT_TOK_AND_RETURN (QUOTE);
       }
     else
       {
-        int tok = handle_string ('\'');
+        int tok = curr_lexer->handle_string ('\'');
         COUNT_TOK_AND_RETURN (tok);
       }
   }
@@ -865,8 +764,8 @@
 \" {
     LEXER_DEBUG ("\"");
 
-    current_input_column++;
-    int tok = handle_string ('"');
+    curr_lexer->current_input_column++;
+    int tok = curr_lexer->handle_string ('"');
 
     COUNT_TOK_AND_RETURN (tok);
 }
@@ -878,12 +777,12 @@
 {CCHAR} {
     LEXER_DEBUG ("{CCHAR}");
 
-    lexer_flags.looking_for_object_index = false;
-
-    xunput (yytext[0], yytext);
+    curr_lexer->looking_for_object_index = false;
+
+    curr_lexer->xunput (yytext[0]);
 
     bool eof = false;
-    int tok = process_comment (false, eof);
+    int tok = curr_lexer->process_comment (false, eof);
 
     if (eof)
       TOK_RETURN (END_OF_INPUT);
@@ -898,15 +797,15 @@
 ^{S}*{CCHAR}\{{S}*{NL} {
     LEXER_DEBUG ("^{S}*{CCHAR}\\{{S}*{NL}");
 
-    lexer_flags.looking_for_object_index = false;
-
-    input_line_number++;
-    current_input_column = 1;
-    block_comment_nesting_level++;
+    curr_lexer->looking_for_object_index = false;
+
+    curr_lexer->input_line_number++;
+    curr_lexer->current_input_column = 1;
+    curr_lexer->block_comment_nesting_level++;
     promptflag--;
 
     bool eof = false;
-    process_comment (true, eof);
+    curr_lexer->process_comment (true, eof);
   }
 
 %{
@@ -922,9 +821,9 @@
 ".\\"   { LEXER_DEBUG (".\\"); BIN_OP_RETURN (ELEFTDIV, false, false); }
 ".^"    { LEXER_DEBUG (".^"); BIN_OP_RETURN (EPOW, false, false); }
 ".**"   { LEXER_DEBUG (".**"); XBIN_OP_RETURN (EPOW, false, false); }
-".'"    { LEXER_DEBUG (".'"); do_comma_insert_check (); BIN_OP_RETURN (TRANSPOSE, true, false); }
-"++"    { LEXER_DEBUG ("++"); do_comma_insert_check (); XBIN_OP_RETURN_INTERNAL (PLUS_PLUS, true, false, true); }
-"--"    { LEXER_DEBUG ("--"); do_comma_insert_check (); XBIN_OP_RETURN_INTERNAL (MINUS_MINUS, true, false, true); }
+".'"    { LEXER_DEBUG (".'"); curr_lexer->do_comma_insert_check (); BIN_OP_RETURN (TRANSPOSE, true, false); }
+"++"    { LEXER_DEBUG ("++"); curr_lexer->do_comma_insert_check (); XBIN_OP_RETURN_INTERNAL (PLUS_PLUS, true, false, true); }
+"--"    { LEXER_DEBUG ("--"); curr_lexer->do_comma_insert_check (); XBIN_OP_RETURN_INTERNAL (MINUS_MINUS, true, false, true); }
 "<="    { LEXER_DEBUG ("<="); BIN_OP_RETURN (EXPR_LE, false, false); }
 "=="    { LEXER_DEBUG ("=="); BIN_OP_RETURN (EXPR_EQ, false, false); }
 "~="    { LEXER_DEBUG ("~="); BIN_OP_RETURN (EXPR_NE, false, false); }
@@ -940,7 +839,7 @@
 "/"     { LEXER_DEBUG ("/"); BIN_OP_RETURN ('/', false, false); }
 "\\"    { LEXER_DEBUG ("\\"); BIN_OP_RETURN (LEFTDIV, false, false); }
 ";"     { LEXER_DEBUG (";"); BIN_OP_RETURN (';', true, true); }
-","     { LEXER_DEBUG (","); BIN_OP_RETURN (',', true, ! lexer_flags.looking_at_object_index.front ()); }
+","     { LEXER_DEBUG (","); BIN_OP_RETURN (',', true, ! curr_lexer->looking_at_object_index.front ()); }
 "^"     { LEXER_DEBUG ("^"); BIN_OP_RETURN (POW, false, false); }
 "**"    { LEXER_DEBUG ("**"); XBIN_OP_RETURN (POW, false, false); }
 "="     { LEXER_DEBUG ("="); BIN_OP_RETURN ('=', true, false); }
@@ -966,14 +865,14 @@
     // is current (so that we can pop it off the stack when we find
     // the matching close paren).
 
-    lexer_flags.looking_at_object_index.push_front
-      (lexer_flags.looking_for_object_index);
-
-    lexer_flags.looking_at_indirect_ref = false;
-    lexer_flags.looking_for_object_index = false;
-    lexer_flags.at_beginning_of_statement = false;
-
-    nesting_level.paren ();
+    curr_lexer->looking_at_object_index.push_front
+      (curr_lexer->looking_for_object_index);
+
+    curr_lexer->looking_at_indirect_ref = false;
+    curr_lexer->looking_for_object_index = false;
+    curr_lexer->at_beginning_of_statement = false;
+
+    curr_lexer->nesting_level.paren ();
     promptflag--;
 
     TOK_RETURN ('(');
@@ -982,22 +881,22 @@
 ")" {
     LEXER_DEBUG (")");
 
-    nesting_level.remove ();
-    current_input_column++;
-
-    lexer_flags.looking_at_object_index.pop_front ();
-
-    lexer_flags.quote_is_transpose = true;
-    lexer_flags.convert_spaces_to_comma
-      = (nesting_level.is_bracket_or_brace ()
-         && ! lexer_flags.looking_at_anon_fcn_args);
-    lexer_flags.looking_for_object_index = true;
-    lexer_flags.at_beginning_of_statement = false;
-
-    if (lexer_flags.looking_at_anon_fcn_args)
-      lexer_flags.looking_at_anon_fcn_args = false;
-
-    do_comma_insert_check ();
+    curr_lexer->nesting_level.remove ();
+    curr_lexer->current_input_column++;
+
+    curr_lexer->looking_at_object_index.pop_front ();
+
+    curr_lexer->quote_is_transpose = true;
+    curr_lexer->convert_spaces_to_comma
+      = (curr_lexer->nesting_level.is_bracket_or_brace ()
+         && ! curr_lexer->looking_at_anon_fcn_args);
+    curr_lexer->looking_for_object_index = true;
+    curr_lexer->at_beginning_of_statement = false;
+
+    if (curr_lexer->looking_at_anon_fcn_args)
+      curr_lexer->looking_at_anon_fcn_args = false;
+
+    curr_lexer->do_comma_insert_check ();
 
     COUNT_TOK_AND_RETURN (')');
   }
@@ -1005,8 +904,8 @@
 "." {
     LEXER_DEBUG (".");
 
-    lexer_flags.looking_for_object_index = false;
-    lexer_flags.at_beginning_of_statement = false;
+    curr_lexer->looking_for_object_index = false;
+    curr_lexer->at_beginning_of_statement = false;
 
     TOK_RETURN ('.');
   }
@@ -1031,21 +930,21 @@
 \{{S}* {
     LEXER_DEBUG ("\\{{S}*");
 
-    nesting_level.brace ();
-
-    lexer_flags.looking_at_object_index.push_front
-      (lexer_flags.looking_for_object_index);
-
-    current_input_column += yyleng;
-    lexer_flags.quote_is_transpose = false;
-    lexer_flags.convert_spaces_to_comma = true;
-    lexer_flags.looking_for_object_index = false;
-    lexer_flags.at_beginning_of_statement = false;
+    curr_lexer->nesting_level.brace ();
+
+    curr_lexer->looking_at_object_index.push_front
+      (curr_lexer->looking_for_object_index);
+
+    curr_lexer->current_input_column += yyleng;
+    curr_lexer->quote_is_transpose = false;
+    curr_lexer->convert_spaces_to_comma = true;
+    curr_lexer->looking_for_object_index = false;
+    curr_lexer->at_beginning_of_statement = false;
 
     promptflag--;
-    eat_whitespace ();
-
-    lexer_flags.braceflag++;
+    curr_lexer->eat_whitespace ();
+
+    curr_lexer->braceflag++;
     BEGIN (MATRIX_START);
     COUNT_TOK_AND_RETURN ('{');
   }
@@ -1053,12 +952,12 @@
 "}" {
     LEXER_DEBUG ("}");
 
-    lexer_flags.looking_at_object_index.pop_front ();
-
-    lexer_flags.looking_for_object_index = true;
-    lexer_flags.at_beginning_of_statement = false;
-
-    nesting_level.remove ();
+    curr_lexer->looking_at_object_index.pop_front ();
+
+    curr_lexer->looking_for_object_index = true;
+    curr_lexer->at_beginning_of_statement = false;
+
+    curr_lexer->nesting_level.remove ();
 
     TOK_RETURN ('}');
   }
@@ -1070,17 +969,17 @@
 . {
     LEXER_DEBUG (".");
 
-    xunput (yytext[0], yytext);
-
-    int c = text_yyinput ();
+    curr_lexer->xunput (yytext[0]);
+
+    int c = curr_lexer->text_yyinput ();
 
     if (c != EOF)
       {
-        current_input_column++;
+        curr_lexer->current_input_column++;
 
         error ("invalid character '%s' (ASCII %d) near line %d, column %d",
                undo_string_escape (static_cast<char> (c)), c,
-               input_line_number, current_input_column);
+               curr_lexer->input_line_number, curr_lexer->current_input_column);
 
         return LEXICAL_ERROR;
       }
@@ -1090,85 +989,6 @@
 
 %%
 
-// GAG.
-//
-// If we're reading a matrix and the next character is '[', make sure
-// that we insert a comma ahead of it.
-
-void
-do_comma_insert_check (void)
-{
-  int spc_gobbled = eat_continuation ();
-
-  int c = text_yyinput ();
-
-  xunput (c, yytext);
-
-  if (spc_gobbled)
-    xunput (' ', yytext);
-
-  lexer_flags.do_comma_insert = (! lexer_flags.looking_at_object_index.front ()
-                                 && lexer_flags.bracketflag && c == '[');
-}
-
-// Fix things up for errors or interrupts.  The parser is never called
-// recursively, so it is always safe to reinitialize its state before
-// doing any parsing.
-
-void
-reset_parser (void)
-{
-  // Start off on the right foot.
-  BEGIN (INITIAL);
-
-  parser_end_of_input = false;
-
-  parser_symtab_context.clear ();
-
-  // We do want a prompt by default.
-  promptflag = 1;
-
-  // We are not in a block comment.
-  block_comment_nesting_level = 0;
-
-  // Error may have occurred inside some brackets, braces, or parentheses.
-  nesting_level.clear ();
-
-  // Clear out the stack of token info used to track line and column
-  // numbers.
-  while (! token_stack.empty ())
-    {
-      delete token_stack.top ();
-      token_stack.pop ();
-    }
-
-  // Can be reset by defining a function.
-  if (! (reading_script_file || reading_fcn_file || reading_classdef_file))
-    {
-      current_input_column = 1;
-      input_line_number = command_editor::current_command_number ();
-    }
-
-  // Only ask for input from stdin if we are expecting interactive
-  // input.
-
-  if (! quitting_gracefully
-      && (interactive || forced_interactive)
-      && ! (reading_fcn_file
-            || reading_classdef_file
-            || reading_script_file
-            || get_input_from_eval_string
-            || input_from_startup_file))
-    yyrestart (stdin);
-
-  // Clear the buffer for help text.
-  while (! help_buf.empty ())
-    help_buf.pop ();
-
-  // Reset other flags.
-  lexer_flags.init ();
-}
-
 static void
 display_character (char c)
 {
@@ -1315,10 +1135,376 @@
       }
 }
 
-static int
-text_yyinput (void)
+void
+cleanup_parser (void)
+{
+}
+
+// Return 1 if the given character matches any character in the given
+// string.
+
+static bool
+match_any (char c, const char *s)
+{
+  char tmp;
+  while ((tmp = *s++) != '\0')
+    {
+      if (c == tmp)
+        return true;
+    }
+  return false;
+}
+
+// Given information about the spacing surrounding an operator,
+// return 1 if it looks like it should be treated as a binary
+// operator.  For example,
+//
+//   [ 1 + 2 ]  or  [ 1+ 2]  or  [ 1+2 ]  ==>  binary
+//
+//   [ 1 +2 ]  ==>  unary
+
+static bool
+looks_like_bin_op (bool spc_prev, int next_char)
+{
+  bool spc_next = (next_char == ' ' || next_char == '\t');
+
+  return ((spc_prev && spc_next) || ! spc_prev);
+}
+
+bool
+is_keyword (const std::string& s)
+{
+  // Parsing function names like "set.property_name" inside
+  // classdef-style class definitions is simplified by handling the
+  // "set" and "get" portions of the names using the same mechanism as
+  // is used for keywords.  However, they are not really keywords in
+  // the language, so omit them from the list of possible keywords.
+
+  return (octave_kw_hash::in_word_set (s.c_str (), s.length ()) != 0
+          && ! (s == "set" || s == "get"));
+}
+
+DEFUN (iskeyword, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn  {Built-in Function} {} iskeyword ()\n\
+@deftypefnx {Built-in Function} {} iskeyword (@var{name})\n\
+Return true if @var{name} is an Octave keyword.  If @var{name}\n\
+is omitted, return a list of keywords.\n\
+@seealso{isvarname, exist}\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+  int argc = args.length () + 1;
+
+  string_vector argv = args.make_argv ("iskeyword");
+
+  if (error_state)
+    return retval;
+
+  if (argc == 1)
+    {
+      // Neither set and get are keywords.  See the note in the
+      // is_keyword function for additional details.
+
+      string_vector lst (TOTAL_KEYWORDS);
+
+      int j = 0;
+
+      for (int i = 0; i < TOTAL_KEYWORDS; i++)
+        {
+          std::string tmp = wordlist[i].name;
+
+          if (! (tmp == "set" || tmp == "get"))
+            lst[j++] = tmp;
+        }
+
+      lst.resize (j);
+
+      retval = Cell (lst.sort ());
+    }
+  else if (argc == 2)
+    {
+      retval = is_keyword (argv[1]);
+    }
+  else
+    print_usage ();
+
+  return retval;
+}
+
+/*
+
+%!assert (iskeyword ("for"))
+%!assert (iskeyword ("fort"), false)
+%!assert (iskeyword ("fft"), false)
+
+*/
+
+// Used to delete trailing white space from tokens.
+
+static std::string
+strip_trailing_whitespace (char *s)
+{
+  std::string retval = s;
+
+  size_t pos = retval.find_first_of (" \t");
+
+  if (pos != std::string::npos)
+    retval.resize (pos);
+
+  return retval;
+}
+
+DEFUN (__display_tokens__, args, nargout,
+  "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} {} __display_tokens__ ()\n\
+Query or set the internal variable that determines whether Octave's\n\
+lexer displays tokens as they are read.\n\
+@end deftypefn")
+{
+  return SET_INTERNAL_VARIABLE (display_tokens);
+}
+
+DEFUN (__token_count__, , ,
+  "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} {} __token_count__ ()\n\
+Number of language tokens processed since Octave startup.\n\
+@end deftypefn")
+{
+  return octave_value (Vtoken_count);
+}
+
+DEFUN (__lexer_debug_flag__, args, nargout,
+  "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} {@var{old_val} =} __lexer_debug_flag__ (@var{new_val}))\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+  retval = set_internal_variable (lexer_debug_flag, args, nargout,
+                                  "__lexer_debug_flag__");
+
+  return retval;
+}
+
+class
+flex_stream_reader : public stream_reader
+{
+public:
+  flex_stream_reader (lexical_feedback *l, char *buf_arg)
+    : stream_reader (), lexer (l), buf (buf_arg)
+  { }
+
+  int getc (void) { return lexer->text_yyinput (); }
+  int ungetc (int c) { lexer->xunput (c, buf); return 0; }
+
+private:
+
+  // No copying!
+
+  flex_stream_reader (const flex_stream_reader&);
+
+  flex_stream_reader& operator = (const flex_stream_reader&);
+
+  lexical_feedback *lexer;
+
+  char *buf;
+};
+
+lexical_feedback::~lexical_feedback (void)
 {
-  int c = yyinput ();
+  // Clear out the stack of token info used to track line and
+  // column numbers.
+
+  while (! token_stack.empty ())
+    {
+      delete token_stack.top ();
+      token_stack.pop ();
+    }
+
+  yylex_destroy (scanner);
+}
+
+void
+lexical_feedback::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
+  // 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
+// by calling a function instead of using the BEGIN macro, we could
+// eliminate the OCTAVE_YYG macro.
+
+#define OCTAVE_YYG \
+  struct yyguts_t *yyg = static_cast<struct yyguts_t*> (scanner)
+
+void
+lexical_feedback::reset (void)
+{
+  OCTAVE_YYG;
+
+  // Start off on the right foot.
+  BEGIN (INITIAL);
+
+  parser_symtab_context.clear ();
+
+  // We do want a prompt by default.
+  promptflag = 1;
+
+  // Only ask for input from stdin if we are expecting interactive
+  // input.
+
+  if (! quitting_gracefully
+      && (interactive || forced_interactive)
+      && ! (reading_fcn_file
+            || reading_classdef_file
+            || reading_script_file
+            || get_input_from_eval_string
+            || input_from_startup_file))
+    yyrestart (stdin, scanner);
+
+  // Clear the buffer for help text.
+  while (! help_buf.empty ())
+    help_buf.pop ();
+}
+
+void
+lexical_feedback::prep_for_script_file (void)
+{
+  OCTAVE_YYG;
+
+  BEGIN (SCRIPT_FILE_BEGIN);
+}
+
+void
+lexical_feedback::prep_for_function_file (void)
+{
+  OCTAVE_YYG;
+
+  BEGIN (FUNCTION_FILE_BEGIN);
+}
+
+void
+lexical_feedback::prep_for_classdef_file (void)
+{
+  OCTAVE_YYG;
+
+  BEGIN (CLASSDEF_FILE_BEGIN);
+}
+
+int
+lexical_feedback::octave_read (char *buf, unsigned max_size)
+{
+  static const char * const eol = "\n";
+  static std::string input_buf;
+  static const char *pos = 0;
+  static size_t chars_left = 0;
+  static bool eof = false;
+
+  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)
+    {
+      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;
+    }
+  else
+    {
+      status = YY_NULL;
+
+      if (! eof)
+        fatal_error ("octave_read () in flex scanner failed");
+    }
+
+  return status;
+}
+
+char *
+lexical_feedback::flex_yytext (void)
+{
+  return yyget_text (scanner);
+}
+
+int
+lexical_feedback::flex_yyleng (void)
+{
+  return yyget_leng (scanner);
+}
+
+// GAG.
+//
+// If we're reading a matrix and the next character is '[', make sure
+// that we insert a comma ahead of it.
+
+void
+lexical_feedback::do_comma_insert_check (void)
+{
+  bool spc_gobbled = (eat_continuation () != lexical_feedback::NO_WHITESPACE);
+
+  int c = text_yyinput ();
+
+  xunput (c);
+
+  if (spc_gobbled)
+    xunput (' ');
+
+  do_comma_insert = (! looking_at_object_index.front ()
+                     && bracketflag && c == '[');
+}
+
+int
+lexical_feedback::text_yyinput (void)
+{
+  int c = yyinput (scanner);
 
   if (lexer_debug_flag)
     {
@@ -1331,7 +1517,7 @@
 
   if (c == '\r')
     {
-      c = yyinput ();
+      c = yyinput (scanner);
 
       if (lexer_debug_flag)
         {
@@ -1342,7 +1528,7 @@
 
       if (c != '\n')
         {
-          xunput (c, yytext);
+          xunput (c);
           c = '\n';
         }
     }
@@ -1353,8 +1539,8 @@
   return c;
 }
 
-static void
-xunput (char c, char *buf)
+void
+lexical_feedback::xunput (char c, char *buf)
 {
   if (lexer_debug_flag)
     {
@@ -1366,14 +1552,22 @@
   if (c == '\n')
     input_line_number--;
 
-  yyunput (c, buf);
+  yyunput (c, buf, scanner);
+}
+
+void
+lexical_feedback::xunput (char c)
+{
+  char *yytxt = flex_yytext ();
+
+  xunput (c, yytxt);
 }
 
 // If we read some newlines, we need figure out what column we're
 // really looking at.
 
-static void
-fixup_column_count (char *s)
+void
+lexical_feedback::fixup_column_count (char *s)
 {
   char c;
   while ((c = *s++) != '\0')
@@ -1388,89 +1582,13 @@
     }
 }
 
-// Include these so that we don't have to link to libfl.a.
-
-int
-yywrap (void)
-{
-  return 1;
-}
-
-// Tell us all what the current buffer is.
-
-YY_BUFFER_STATE
-current_buffer (void)
-{
-  return YY_CURRENT_BUFFER;
-}
-
-// Create a new buffer.
-
-YY_BUFFER_STATE
-create_buffer (FILE *f)
-{
-  return yy_create_buffer (f, YY_BUF_SIZE);
-}
-
-// Start reading a new buffer.
-
-void
-switch_to_buffer (YY_BUFFER_STATE buf)
-{
-  yy_switch_to_buffer (buf);
-}
-
-// Delete a buffer.
-
-void
-delete_buffer (YY_BUFFER_STATE buf)
-{
-  yy_delete_buffer (buf);
-
-  // Prevent invalid yyin from being used by yyrestart.
-  if (! current_buffer ())
-    yyin = 0; 
-}
-
-// Delete all buffers from the stack.
-void
-clear_all_buffers (void)
-{                 
-  while (current_buffer ())
-    octave_pop_buffer_state ();
-}
-
-void
-cleanup_parser (void)
-{
-  reset_parser ();
-
-  clear_all_buffers ();
-}
-
-// Restore a buffer (for unwind-prot).
-
-void
-restore_input_buffer (void *buf)
-{
-  switch_to_buffer (static_cast<YY_BUFFER_STATE> (buf));
-}
-
-// Delete a buffer (for unwind-prot).
-
-void
-delete_input_buffer (void *buf)
-{
-  delete_buffer (static_cast<YY_BUFFER_STATE> (buf));
-}
-
-static bool
-inside_any_object_index (void)
+bool
+lexical_feedback::inside_any_object_index (void)
 {
   bool retval = false;
 
-  for (std::list<bool>::const_iterator i = lexer_flags.looking_at_object_index.begin ();
-       i != lexer_flags.looking_at_object_index.end (); i++)
+  for (std::list<bool>::const_iterator i = looking_at_object_index.begin ();
+       i != looking_at_object_index.end (); i++)
     {
       if (*i)
         {
@@ -1484,8 +1602,8 @@
 
 // Handle keywords.  Return -1 if the keyword should be ignored.
 
-static int
-is_keyword_token (const std::string& s)
+int
+lexical_feedback::is_keyword_token (const std::string& s)
 {
   int l = input_line_number;
   int c = current_input_column;
@@ -1496,7 +1614,7 @@
 
   if (kw)
     {
-      yylval.tok_val = 0;
+      token *tok_val = 0;
 
       switch (kw->kw_id)
         {
@@ -1507,7 +1625,7 @@
         case otherwise_kw:
         case return_kw:
         case unwind_protect_cleanup_kw:
-          lexer_flags.at_beginning_of_statement = true;
+          at_beginning_of_statement = true;
           break;
 
         case static_kw:
@@ -1536,78 +1654,78 @@
         case end_kw:
           if (inside_any_object_index ()
               || (! reading_classdef_file
-                  && (lexer_flags.defining_func
-                      && ! (lexer_flags.looking_at_return_list
-                            || lexer_flags.parsed_function_name.top ()))))
+                  && (defining_func
+                      && ! (looking_at_return_list
+                            || parsed_function_name.top ()))))
             return 0;
 
-          yylval.tok_val = new token (token::simple_end, l, c);
-          lexer_flags.at_beginning_of_statement = true;
+          tok_val = new token (token::simple_end, l, c);
+          at_beginning_of_statement = true;
           break;
 
         case end_try_catch_kw:
-          yylval.tok_val = new token (token::try_catch_end, l, c);
-          lexer_flags.at_beginning_of_statement = true;
+          tok_val = new token (token::try_catch_end, l, c);
+          at_beginning_of_statement = true;
           break;
 
         case end_unwind_protect_kw:
-          yylval.tok_val = new token (token::unwind_protect_end, l, c);
-          lexer_flags.at_beginning_of_statement = true;
+          tok_val = new token (token::unwind_protect_end, l, c);
+          at_beginning_of_statement = true;
           break;
 
         case endfor_kw:
-          yylval.tok_val = new token (token::for_end, l, c);
-          lexer_flags.at_beginning_of_statement = true;
+          tok_val = new token (token::for_end, l, c);
+          at_beginning_of_statement = true;
           break;
 
         case endfunction_kw:
-          yylval.tok_val = new token (token::function_end, l, c);
-          lexer_flags.at_beginning_of_statement = true;
+          tok_val = new token (token::function_end, l, c);
+          at_beginning_of_statement = true;
           break;
 
         case endif_kw:
-          yylval.tok_val = new token (token::if_end, l, c);
-          lexer_flags.at_beginning_of_statement = true;
+          tok_val = new token (token::if_end, l, c);
+          at_beginning_of_statement = true;
           break;
 
         case endparfor_kw:
-          yylval.tok_val = new token (token::parfor_end, l, c);
-          lexer_flags.at_beginning_of_statement = true;
+          tok_val = new token (token::parfor_end, l, c);
+          at_beginning_of_statement = true;
           break;
 
         case endswitch_kw:
-          yylval.tok_val = new token (token::switch_end, l, c);
-          lexer_flags.at_beginning_of_statement = true;
+          tok_val = new token (token::switch_end, l, c);
+          at_beginning_of_statement = true;
           break;
 
         case endwhile_kw:
-          yylval.tok_val = new token (token::while_end, l, c);
-          lexer_flags.at_beginning_of_statement = true;
+          tok_val = new token (token::while_end, l, c);
+          at_beginning_of_statement = true;
           break;
 
         case endclassdef_kw:
-          yylval.tok_val = new token (token::classdef_end, l, c);
-          lexer_flags.at_beginning_of_statement = true;
+          tok_val = new token (token::classdef_end, l, c);
+          at_beginning_of_statement = true;
           break;
 
         case endenumeration_kw:
-          yylval.tok_val = new token (token::enumeration_end, l, c);
-          lexer_flags.at_beginning_of_statement = true;
+          tok_val = new token (token::enumeration_end, l, c);
+          at_beginning_of_statement = true;
           break;
 
         case endevents_kw:
-          yylval.tok_val = new token (token::events_end, l, c);
-          lexer_flags.at_beginning_of_statement = true;
+          tok_val = new token (token::events_end, l, c);
+          at_beginning_of_statement = true;
           break;
 
         case endmethods_kw:
-          yylval.tok_val = new token (token::methods_end, l, c);
-          lexer_flags.at_beginning_of_statement = true;
+          tok_val = new token (token::methods_end, l, c);
+          at_beginning_of_statement = true;
           break;
 
         case endproperties_kw:
-          yylval.tok_val = new token (token::properties_end, l, c);
-          lexer_flags.at_beginning_of_statement = true;
+          tok_val = new token (token::properties_end, l, c);
+          at_beginning_of_statement = true;
           break;
 
 
@@ -1615,18 +1733,18 @@
         case parfor_kw:
         case while_kw:
           promptflag--;
-          lexer_flags.looping++;
+          looping++;
           break;
 
         case do_kw:
-          lexer_flags.at_beginning_of_statement = true;
+          at_beginning_of_statement = true;
           promptflag--;
-          lexer_flags.looping++;
+          looping++;
           break;
 
         case try_kw:
         case unwind_protect_kw:
-          lexer_flags.at_beginning_of_statement = true;
+          at_beginning_of_statement = true;
           promptflag--;
           break;
 
@@ -1639,7 +1757,7 @@
         case set_kw:
           // 'get' and 'set' are keywords in classdef method
           // declarations.
-          if (! lexer_flags.maybe_classdef_get_set_method)
+          if (! maybe_classdef_get_set_method)
             return 0;
           break;
 
@@ -1649,7 +1767,7 @@
         case properties_kw:
           // 'properties', 'methods' and 'events' are keywords for
           // classdef blocks.
-          if (! lexer_flags.parsing_classdef)
+          if (! parsing_classdef)
             return 0;
           // fall through ...
 
@@ -1661,8 +1779,8 @@
         case function_kw:
           promptflag--;
 
-          lexer_flags.defining_func++;
-          lexer_flags.parsed_function_name.push (false);
+          defining_func++;
+          parsed_function_name.push (false);
 
           if (! (reading_fcn_file || reading_script_file
                  || reading_classdef_file))
@@ -1674,24 +1792,24 @@
             if ((reading_fcn_file || reading_script_file
                  || reading_classdef_file)
                 && ! curr_fcn_file_full_name.empty ())
-              yylval.tok_val = new token (curr_fcn_file_full_name, l, c);
+              tok_val = new token (curr_fcn_file_full_name, l, c);
             else
-              yylval.tok_val = new token ("stdin", l, c);
+              tok_val = new token ("stdin", l, c);
           }
           break;
 
         case magic_line_kw:
-          yylval.tok_val = new token (static_cast<double> (l), "", l, c);
+          tok_val = new token (static_cast<double> (l), "", l, c);
           break;
 
         default:
           panic_impossible ();
         }
 
-      if (! yylval.tok_val)
-        yylval.tok_val = new token (l, c);
-
-      token_stack.push (yylval.tok_val);
+      if (! tok_val)
+        tok_val = new token (l, c);
+
+      push_token (tok_val);
 
       return kw->tok;
     }
@@ -1699,16 +1817,16 @@
   return 0;
 }
 
-static bool
-is_variable (const std::string& name)
+bool
+lexical_feedback::is_variable (const std::string& name)
 {
   return (symbol_table::is_variable (name)
-          || (lexer_flags.pending_local_variables.find (name)
-              != lexer_flags.pending_local_variables.end ()));
+          || (pending_local_variables.find (name)
+              != pending_local_variables.end ()));
 }
 
-static std::string
-grab_block_comment (stream_reader& reader, bool& eof)
+std::string
+lexical_feedback::grab_block_comment (stream_reader& reader, bool& eof)
 {
   std::string buf;
 
@@ -1814,8 +1932,8 @@
 }
 
 std::string
-grab_comment_block (stream_reader& reader, bool at_bol,
-                    bool& eof)
+lexical_feedback::grab_comment_block (stream_reader& reader, bool at_bol,
+                                      bool& eof)
 {
   std::string buf;
 
@@ -1953,29 +2071,11 @@
   return buf;
 }
 
-class
-flex_stream_reader : public stream_reader
+int
+lexical_feedback::process_comment (bool start_in_block, bool& eof)
 {
-public:
-  flex_stream_reader (char *buf_arg) : stream_reader (), buf (buf_arg) { }
-
-  int getc (void) { return ::text_yyinput (); }
-  int ungetc (int c) { ::xunput (c, buf); return 0; }
-
-private:
-
-  // No copying!
-
-  flex_stream_reader (const flex_stream_reader&);
-
-  flex_stream_reader& operator = (const flex_stream_reader&);
-
-  char *buf;
-};
-
-static int
-process_comment (bool start_in_block, bool& eof)
-{
+  OCTAVE_YYG;
+
   eof = false;
 
   std::string help_txt;
@@ -1983,7 +2083,8 @@
   if (! help_buf.empty ())
     help_txt = help_buf.top ();
 
-  flex_stream_reader flex_reader (yytext);
+  char *yytxt = flex_yytext ();
+  flex_stream_reader flex_reader (this, yytxt);
 
   // process_comment is only supposed to be called when we are not
   // initially looking at a block comment.
@@ -2006,9 +2107,9 @@
   octave_comment_buffer::append (txt);
 
   current_input_column = 1;
-  lexer_flags.quote_is_transpose = false;
-  lexer_flags.convert_spaces_to_comma = true;
-  lexer_flags.at_beginning_of_statement = true;
+  quote_is_transpose = false;
+  convert_spaces_to_comma = true;
+  at_beginning_of_statement = true;
 
   if (YY_START == COMMAND_START)
     BEGIN (INITIAL);
@@ -2021,42 +2122,11 @@
     return 0;
 }
 
-// Return 1 if the given character matches any character in the given
-// string.
-
-static bool
-match_any (char c, const char *s)
-{
-  char tmp;
-  while ((tmp = *s++) != '\0')
-    {
-      if (c == tmp)
-        return true;
-    }
-  return false;
-}
-
-// Given information about the spacing surrounding an operator,
-// return 1 if it looks like it should be treated as a binary
-// operator.  For example,
-//
-//   [ 1 + 2 ]  or  [ 1+ 2]  or  [ 1+2 ]  ==>  binary
-//
-//   [ 1 +2 ]  ==>  unary
-
-static bool
-looks_like_bin_op (bool spc_prev, int next_char)
-{
-  bool spc_next = (next_char == ' ' || next_char == '\t');
-
-  return ((spc_prev && spc_next) || ! spc_prev);
-}
-
 // Recognize separators.  If the separator is a CRLF pair, it is
 // replaced by a single LF.
 
-static bool
-next_token_is_sep_op (void)
+bool
+lexical_feedback::next_token_is_sep_op (void)
 {
   bool retval = false;
 
@@ -2064,7 +2134,7 @@
 
   retval = match_any (c, ",;\n]");
 
-  xunput (c, yytext);
+  xunput (c);
 
   return retval;
 }
@@ -2072,8 +2142,8 @@
 // Try to determine if the next token should be treated as a postfix
 // unary operator.  This is ugly, but it seems to do the right thing.
 
-static bool
-next_token_is_postfix_unary_op (bool spc_prev)
+bool
+lexical_feedback::next_token_is_postfix_unary_op (bool spc_prev)
 {
   bool un_op = false;
 
@@ -2087,22 +2157,22 @@
     {
       int c1 = text_yyinput ();
       un_op = (c1 == '\'');
-      xunput (c1, yytext);
+      xunput (c1);
     }
   else if (c0 == '+')
     {
       int c1 = text_yyinput ();
       un_op = (c1 == '+');
-      xunput (c1, yytext);
+      xunput (c1);
     }
   else if (c0 == '-')
     {
       int c1 = text_yyinput ();
       un_op = (c1 == '-');
-      xunput (c1, yytext);
+      xunput (c1);
     }
 
-  xunput (c0, yytext);
+  xunput (c0);
 
   return un_op;
 }
@@ -2119,8 +2189,8 @@
 // (e.g., the characters '[' 'a' ' ' '+' '\' LFD 'b' ']') will be
 // parsed as a binary operator.
 
-static bool
-next_token_is_bin_op (bool spc_prev)
+bool
+lexical_feedback::next_token_is_bin_op (bool spc_prev)
 {
   bool bin_op = false;
 
@@ -2151,7 +2221,7 @@
             break;
           }
 
-        xunput (c1, yytext);
+        xunput (c1);
       }
       break;
 
@@ -2175,7 +2245,7 @@
           // A structure element reference is a binary op.
           bin_op = true;
 
-        xunput (c1, yytext);
+        xunput (c1);
       }
       break;
 
@@ -2205,7 +2275,7 @@
         if (c1 == '=')
           bin_op = true;
 
-        xunput (c1, yytext);
+        xunput (c1);
       }
       break;
 
@@ -2213,30 +2283,15 @@
       break;
     }
 
-  xunput (c0, yytext);
+  xunput (c0);
 
   return bin_op;
 }
 
-// Used to delete trailing white space from tokens.
-
-static std::string
-strip_trailing_whitespace (char *s)
-{
-  std::string retval = s;
-
-  size_t pos = retval.find_first_of (" \t");
-
-  if (pos != std::string::npos)
-    retval.resize (pos);
-
-  return retval;
-}
-
 // FIXME -- we need to handle block comments here.
 
-static void
-scan_for_comments (const char *text)
+void
+lexical_feedback::scan_for_comments (const char *text)
 {
   std::string comment_buf;
 
@@ -2293,19 +2348,13 @@
 }
 
 // Discard whitespace, including comments and continuations.
-//
-// Return value is logical OR of the following values:
-//
-//  ATE_NOTHING      : no spaces to eat
-//  ATE_SPACE_OR_TAB : space or tab in input
-//  ATE_NEWLINE      : bare new line in input
 
 // FIXME -- we need to handle block comments here.
 
-static yum_yum
-eat_whitespace (void)
+int
+lexical_feedback::eat_whitespace (void)
 {
-  yum_yum retval = ATE_NOTHING;
+  int retval = lexical_feedback::NO_WHITESPACE;
 
   std::string comment_buf;
 
@@ -2327,11 +2376,11 @@
               comment_buf += static_cast<char> (c);
               beginning_of_comment = false;
             }
-          retval |= ATE_SPACE_OR_TAB;
+          retval |= lexical_feedback::SPACE_OR_TAB;
           break;
 
         case '\n':
-          retval |= ATE_NEWLINE;
+          retval |= lexical_feedback::NEWLINE;
           if (in_comment)
             {
               comment_buf += static_cast<char> (c);
@@ -2404,7 +2453,7 @@
     octave_comment_buffer::append (comment_buf);
 
  done:
-  xunput (c, yytext);
+  xunput (c);
   current_input_column--;
   return retval;
 }
@@ -2415,23 +2464,25 @@
   return (len > 2 && s[0] == '0' && (s[1] == 'x' || s[1] == 'X'));
 }
 
-static void
-handle_number (void)
+void
+lexical_feedback::handle_number (void)
 {
   double value = 0.0;
   int nread = 0;
 
-  if (looks_like_hex (yytext, strlen (yytext)))
+  char *yytxt = flex_yytext ();
+
+  if (looks_like_hex (yytxt, strlen (yytxt)))
     {
       unsigned long ival;
 
-      nread = sscanf (yytext, "%lx", &ival);
+      nread = sscanf (yytxt, "%lx", &ival);
 
       value = static_cast<double> (ival);
     }
   else
     {
-      char *tmp = strsave (yytext);
+      char *tmp = strsave (yytxt);
 
       char *idx = strpbrk (tmp, "Dd");
 
@@ -2447,17 +2498,15 @@
 
   assert (nread == 1);
 
-  lexer_flags.quote_is_transpose = true;
-  lexer_flags.convert_spaces_to_comma = true;
-  lexer_flags.looking_for_object_index = false;
-  lexer_flags.at_beginning_of_statement = false;
-
-  yylval.tok_val = new token (value, yytext, input_line_number,
-                              current_input_column);
-
-  token_stack.push (yylval.tok_val);
-
-  current_input_column += yyleng;
+  quote_is_transpose = true;
+  convert_spaces_to_comma = true;
+  looking_for_object_index = false;
+  at_beginning_of_statement = false;
+
+  push_token (new token (value, yytxt, input_line_number,
+                         current_input_column));
+
+  current_input_column += flex_yyleng ();
 
   do_comma_insert_check ();
 }
@@ -2473,8 +2522,8 @@
 
 // FIXME -- we need to handle block comments here.
 
-static bool
-have_continuation (bool trailing_comments_ok)
+bool
+lexical_feedback::have_continuation (bool trailing_comments_ok)
 {
   std::ostringstream buf;
 
@@ -2543,7 +2592,7 @@
         }
     }
 
-  xunput (c, yytext);
+  xunput (c);
   return false;
 
 cleanup:
@@ -2552,7 +2601,7 @@
 
   int len = s.length ();
   while (len--)
-    xunput (s[len], yytext);
+    xunput (s[len]);
 
   return false;
 }
@@ -2561,8 +2610,8 @@
 // continuation.  If so, this eats it, up to and including the new
 // line character.
 
-static bool
-have_ellipsis_continuation (bool trailing_comments_ok)
+bool
+lexical_feedback::have_ellipsis_continuation (bool trailing_comments_ok)
 {
   char c1 = text_yyinput ();
   if (c1 == '.')
@@ -2572,25 +2621,23 @@
         return true;
       else
         {
-          xunput (c2, yytext);
-          xunput (c1, yytext);
+          xunput (c2);
+          xunput (c1);
         }
     }
   else
-    xunput (c1, yytext);
+    xunput (c1);
 
   return false;
 }
 
 // See if we have a continuation line.  If so, eat it and the leading
 // whitespace on the next line.
-//
-// Return value is the same as described for eat_whitespace().
-
-static yum_yum
-eat_continuation (void)
+
+int
+lexical_feedback::eat_continuation (void)
 {
-  int retval = ATE_NOTHING;
+  int retval = lexical_feedback::NO_WHITESPACE;
 
   int c = text_yyinput ();
 
@@ -2598,13 +2645,13 @@
       || (c == '\\' && have_continuation ()))
     retval = eat_whitespace ();
   else
-    xunput (c, yytext);
+    xunput (c);
 
   return retval;
 }
 
-static int
-handle_string (char delim)
+int
+lexical_feedback::handle_string (char delim)
 {
   std::ostringstream buf;
 
@@ -2661,26 +2708,25 @@
               else
                 {
                   std::string s;
-                  xunput (c, yytext);
+                  xunput (c);
 
                   if (delim == '\'')
                     s = buf.str ();
                   else
                     s = do_string_escapes (buf.str ());
 
-                  lexer_flags.quote_is_transpose = true;
-                  lexer_flags.convert_spaces_to_comma = true;
-
-                  yylval.tok_val = new token (s, bos_line, bos_col);
-                  token_stack.push (yylval.tok_val);
+                  quote_is_transpose = true;
+                  convert_spaces_to_comma = true;
+
+                  push_token (new token (s, bos_line, bos_col));
 
                   if (delim == '"')
                     gripe_matlab_incompatible ("\" used as string delimiter");
                   else if (delim == '\'')
                     gripe_single_quote_string ();
 
-                  lexer_flags.looking_for_object_index = true;
-                  lexer_flags.at_beginning_of_statement = false;
+                  looking_for_object_index = true;
+                  at_beginning_of_statement = false;
 
                   return delim == '"' ? DQ_STRING : SQ_STRING;
                 }
@@ -2697,8 +2743,8 @@
   return LEXICAL_ERROR;
 }
 
-static bool
-next_token_is_assign_op (void)
+bool
+lexical_feedback::next_token_is_assign_op (void)
 {
   bool retval = false;
 
@@ -2709,7 +2755,7 @@
     case '=':
       {
         int c1 = text_yyinput ();
-        xunput (c1, yytext);
+        xunput (c1);
         if (c1 != '=')
           retval = true;
       }
@@ -2724,7 +2770,7 @@
     case '|':
       {
         int c1 = text_yyinput ();
-        xunput (c1, yytext);
+        xunput (c1);
         if (c1 == '=')
           retval = true;
       }
@@ -2736,11 +2782,11 @@
         if (match_any (c1, "+-*/\\"))
           {
             int c2 = text_yyinput ();
-            xunput (c2, yytext);
+            xunput (c2);
             if (c2 == '=')
               retval = true;
           }
-        xunput (c1, yytext);
+        xunput (c1);
       }
       break;
 
@@ -2750,11 +2796,11 @@
         if (c1 == '>')
           {
             int c2 = text_yyinput ();
-            xunput (c2, yytext);
+            xunput (c2);
             if (c2 == '=')
               retval = true;
           }
-        xunput (c1, yytext);
+        xunput (c1);
       }
       break;
 
@@ -2764,11 +2810,11 @@
         if (c1 == '<')
           {
             int c2 = text_yyinput ();
-            xunput (c2, yytext);
+            xunput (c2);
             if (c2 == '=')
               retval = true;
           }
-        xunput (c1, yytext);
+        xunput (c1);
       }
       break;
 
@@ -2776,22 +2822,24 @@
       break;
     }
 
-  xunput (c0, yytext);
+  xunput (c0);
 
   return retval;
 }
 
-static bool
-next_token_is_index_op (void)
+bool
+lexical_feedback::next_token_is_index_op (void)
 {
   int c = text_yyinput ();
-  xunput (c, yytext);
+  xunput (c);
   return c == '(' || c == '{';
 }
 
-static int
-handle_close_bracket (bool spc_gobbled, int bracket_type)
+int
+lexical_feedback::handle_close_bracket (bool spc_gobbled, int bracket_type)
 {
+  OCTAVE_YYG;
+
   int retval = bracket_type;
 
   if (! nesting_level.none ())
@@ -2799,27 +2847,27 @@
       nesting_level.remove ();
 
       if (bracket_type == ']')
-        lexer_flags.bracketflag--;
+        bracketflag--;
       else if (bracket_type == '}')
-        lexer_flags.braceflag--;
+        braceflag--;
       else
         panic_impossible ();
     }
 
-  if (lexer_flags.bracketflag == 0 && lexer_flags.braceflag == 0)
+  if (bracketflag == 0 && braceflag == 0)
     BEGIN (INITIAL);
 
   if (bracket_type == ']'
       && next_token_is_assign_op ()
-      && ! lexer_flags.looking_at_return_list)
+      && ! looking_at_return_list)
     {
       retval = CLOSE_BRACE;
     }
-  else if ((lexer_flags.bracketflag || lexer_flags.braceflag)
-           && lexer_flags.convert_spaces_to_comma
+  else if ((bracketflag || braceflag)
+           && convert_spaces_to_comma
            && (nesting_level.is_bracket ()
                || (nesting_level.is_brace ()
-                   && ! lexer_flags.looking_at_object_index.front ())))
+                   && ! looking_at_object_index.front ())))
     {
       bool index_op = next_token_is_index_op ();
 
@@ -2843,24 +2891,24 @@
             {
               maybe_warn_separator_insert (',');
 
-              xunput (',', yytext);
+              xunput (',');
               return retval;
             }
         }
     }
 
-  lexer_flags.quote_is_transpose = true;
-  lexer_flags.convert_spaces_to_comma = true;
+  quote_is_transpose = true;
+  convert_spaces_to_comma = true;
 
   return retval;
 }
 
-static void
-maybe_unput_comma (int spc_gobbled)
+void
+lexical_feedback::maybe_unput_comma (int spc_gobbled)
 {
   if (nesting_level.is_bracket ()
       || (nesting_level.is_brace ()
-          && ! lexer_flags.looking_at_object_index.front ()))
+          && ! looking_at_object_index.front ()))
     {
       int bin_op = next_token_is_bin_op (spc_gobbled);
 
@@ -2869,8 +2917,8 @@
       int c1 = text_yyinput ();
       int c2 = text_yyinput ();
 
-      xunput (c2, yytext);
-      xunput (c1, yytext);
+      xunput (c2);
+      xunput (c1);
 
       int sep_op = next_token_is_sep_op ();
 
@@ -2890,12 +2938,12 @@
 
       maybe_warn_separator_insert (',');
 
-      xunput (',', yytext);
+      xunput (',');
     }
 }
 
-static bool
-next_token_can_follow_bin_op (void)
+bool
+lexical_feedback::next_token_can_follow_bin_op (void)
 {
   std::stack<char> buf;
 
@@ -2915,7 +2963,7 @@
   // Restore input.
   while (! buf.empty ())
     {
-      xunput (buf.top (), yytext);
+      xunput (buf.top ());
 
       buf.pop ();
     }
@@ -2936,8 +2984,8 @@
             || tok == "NaN" || tok == "nan");
 }
 
-static bool
-looks_like_command_arg (void)
+bool
+lexical_feedback::looks_like_command_arg (void)
 {
   bool retval = true;
 
@@ -2958,12 +3006,12 @@
                 && next_token_can_follow_bin_op ())
               retval = false;
 
-            xunput (c2, yytext);
+            xunput (c2);
           }
         else
           retval = false;
 
-        xunput (c1, yytext);
+        xunput (c1);
       }
       break;
 
@@ -3013,12 +3061,12 @@
                   && next_token_can_follow_bin_op ())
                 retval = false;
 
-              xunput (c2, yytext);
+              xunput (c2);
             }
             break;
           }
 
-        xunput (c1, yytext);
+        xunput (c1);
       }
       break;
 
@@ -3033,7 +3081,7 @@
             && next_token_can_follow_bin_op ())
           retval = false;
 
-        xunput (c1, yytext);
+        xunput (c1);
       }
       break;
 
@@ -3054,13 +3102,13 @@
                     && next_token_can_follow_bin_op ())
                   retval = false;
 
-                xunput (c3, yytext);
+                xunput (c3);
               }
             else if (! match_any (c2, ",;\n") && (c2 == ' ' || c2 == '\t')
                      && next_token_can_follow_bin_op ())
               retval = false;
 
-            xunput (c2, yytext);
+            xunput (c2);
           }
         else if (! match_any (c1, ",;\n")
                  && (! isdigit (c1) && c1 != ' ' && c1 != '\t'
@@ -3071,7 +3119,7 @@
             retval = false;
           }
 
-        xunput (c1, yytext);
+        xunput (c1);
       }
       break;
 
@@ -3090,13 +3138,13 @@
                 && next_token_can_follow_bin_op ())
               retval = false;
 
-            xunput (c2, yytext);
+            xunput (c2);
           }
         else if (! match_any (c1, ",;\n") && (c1 == ' ' || c1 == '\t')
                  && next_token_can_follow_bin_op ())
           retval = false;
 
-        xunput (c1, yytext);
+        xunput (c1);
       }
       break;
 
@@ -3114,13 +3162,13 @@
                 && next_token_can_follow_bin_op ())
               retval = false;
 
-            xunput (c2, yytext);
+            xunput (c2);
           }
         else if (! match_any (c1, ",;\n") && (c1 == ' ' || c1 == '\t')
                  && next_token_can_follow_bin_op ())
           retval = false;
 
-        xunput (c1, yytext);
+        xunput (c1);
       }
       break;
 
@@ -3139,13 +3187,13 @@
                 && next_token_can_follow_bin_op ())
               retval = false;
 
-            xunput (c2, yytext);
+            xunput (c2);
           }
         else if (! match_any (c1, ",;\n") && (c1 == ' ' || c1 == '\t')
                  && next_token_can_follow_bin_op ())
           retval = false;
 
-        xunput (c1, yytext);
+        xunput (c1);
       }
       break;
 
@@ -3153,17 +3201,18 @@
       break;
     }
 
-  xunput (c0, yytext);
+  xunput (c0);
 
   return retval;
 }
 
-static int
-handle_superclass_identifier (void)
+int
+lexical_feedback::handle_superclass_identifier (void)
 {
-  int c = yytext[yyleng-1];
-
-  std::string meth = strip_trailing_whitespace (yytext);
+  char *yytxt = flex_yytext ();
+  int c = yytxt[flex_yyleng()-1];
+
+  std::string meth = strip_trailing_whitespace (yytxt);
 
   int cont_is_spc = eat_continuation ();
 
@@ -3189,23 +3238,23 @@
       return LEXICAL_ERROR;
     }
 
-  yylval.tok_val = new token (meth, pkg, cls, input_line_number,
-                              current_input_column);
-  token_stack.push (yylval.tok_val);
+  push_token (new token (meth, pkg, cls, input_line_number,
+                         current_input_column));
 
   do_comma_insert_check ();
   maybe_unput_comma (spc_gobbled);
-  current_input_column += yyleng;
+  current_input_column += flex_yyleng ();
 
   return SUPERCLASSREF;
 }
 
-static int
-handle_meta_identifier (void)
+int
+lexical_feedback::handle_meta_identifier (void)
 {
-  int c = yytext[yyleng-1];
-
-  std::string cls = strip_trailing_whitespace (yytext).substr (1);
+  char *yytxt = flex_yytext ();
+  int c = yytxt[flex_yyleng()-1];
+
+  std::string cls = strip_trailing_whitespace (yytxt).substr (1);
 
   int cont_is_spc = eat_continuation ();
 
@@ -3226,13 +3275,12 @@
       return LEXICAL_ERROR;
     }
 
-  yylval.tok_val = new token (pkg, cls, input_line_number,
-                              current_input_column);
-  token_stack.push (yylval.tok_val);
+  push_token (new token (pkg, cls, input_line_number,
+                         current_input_column));
 
   do_comma_insert_check ();
   maybe_unput_comma (spc_gobbled);
-  current_input_column += yyleng;
+  current_input_column += flex_yyleng ();
 
   return METAQUERY;
 }
@@ -3241,16 +3289,20 @@
 // an identifier.  Handles keywords.  Return -1 if the identifier
 // should be ignored.
 
-static int
-handle_identifier (void)
+int
+lexical_feedback::handle_identifier (void)
 {
-  bool at_bos = lexer_flags.at_beginning_of_statement;
-
-  std::string tok = strip_trailing_whitespace (yytext);
-
-  int c = yytext[yyleng-1];
-
-  int cont_is_spc = eat_continuation ();
+  OCTAVE_YYG;
+
+  bool at_bos = at_beginning_of_statement;
+
+  char *yytxt = flex_yytext ();
+
+  std::string tok = strip_trailing_whitespace (yytxt);
+
+  int c = yytxt[flex_yyleng()-1];
+
+  bool cont_is_spc = (eat_continuation () != lexical_feedback::NO_WHITESPACE);
 
   int spc_gobbled = (cont_is_spc || c == ' ' || c == '\t');
 
@@ -3259,30 +3311,28 @@
   // a string that is also a valid identifier.  But first, we have to
   // decide whether to insert a comma.
 
-  if (lexer_flags.looking_at_indirect_ref)
+  if (looking_at_indirect_ref)
     {
       do_comma_insert_check ();
 
       maybe_unput_comma (spc_gobbled);
 
-      yylval.tok_val = new token (tok, input_line_number,
-                                  current_input_column);
-
-      token_stack.push (yylval.tok_val);
-
-      lexer_flags.quote_is_transpose = true;
-      lexer_flags.convert_spaces_to_comma = true;
-      lexer_flags.looking_for_object_index = true;
-
-      current_input_column += yyleng;
+      push_token (new token (tok, input_line_number,
+                             current_input_column));
+
+      quote_is_transpose = true;
+      convert_spaces_to_comma = true;
+      looking_for_object_index = true;
+
+      current_input_column += flex_yyleng ();
 
       return STRUCT_ELT;
     }
 
-  lexer_flags.at_beginning_of_statement = false;
+  at_beginning_of_statement = false;
 
   // The is_keyword_token may reset
-  // lexer_flags.at_beginning_of_statement.  For example, if it sees
+  // at_beginning_of_statement.  For example, if it sees
   // an else token, then the next token is at the beginning of a
   // statement.
 
@@ -3292,7 +3342,7 @@
   // is already set.  Otherwise, we won't be at the beginning of a
   // statement.
 
-  if (lexer_flags.looking_at_function_handle)
+  if (looking_at_function_handle)
     {
       if (kw_token)
         {
@@ -3302,15 +3352,13 @@
         }
       else
         {
-          yylval.tok_val = new token (tok, input_line_number,
-                                      current_input_column);
-
-          token_stack.push (yylval.tok_val);
-
-          current_input_column += yyleng;
-          lexer_flags.quote_is_transpose = false;
-          lexer_flags.convert_spaces_to_comma = true;
-          lexer_flags.looking_for_object_index = true;
+          push_token (new token (tok, input_line_number,
+                                 current_input_column));
+
+          current_input_column += flex_yyleng ();
+          quote_is_transpose = false;
+          convert_spaces_to_comma = true;
+          looking_for_object_index = true;
 
           return FCN_HANDLE;
         }
@@ -3323,10 +3371,10 @@
     {
       if (kw_token >= 0)
         {
-          current_input_column += yyleng;
-          lexer_flags.quote_is_transpose = false;
-          lexer_flags.convert_spaces_to_comma = true;
-          lexer_flags.looking_for_object_index = false;
+          current_input_column += flex_yyleng ();
+          quote_is_transpose = false;
+          convert_spaces_to_comma = true;
+          looking_for_object_index = false;
         }
 
       return kw_token;
@@ -3340,13 +3388,13 @@
   if (c1 == '=')
     {
       int c2 = text_yyinput ();
-      xunput (c2, yytext);
+      xunput (c2);
 
       if (c2 != '=')
         next_tok_is_eq = true;
     }
 
-  xunput (c1, yytext);
+  xunput (c1);
 
   // Kluge alert.
   //
@@ -3366,16 +3414,16 @@
           BEGIN (COMMAND_START);
         }
       else if (next_tok_is_eq
-               || lexer_flags.looking_at_decl_list
-               || lexer_flags.looking_at_return_list
-               || (lexer_flags.looking_at_parameter_list
-                   && ! lexer_flags.looking_at_initializer_expression))
+               || looking_at_decl_list
+               || looking_at_return_list
+               || (looking_at_parameter_list
+                   && ! looking_at_initializer_expression))
         {
           symbol_table::force_variable (tok);
         }
-      else if (lexer_flags.looking_at_matrix_or_assign_lhs)
+      else if (looking_at_matrix_or_assign_lhs)
         {
-          lexer_flags.pending_local_variables.insert (tok);
+          pending_local_variables.insert (tok);
         }
     }
 
@@ -3385,195 +3433,33 @@
   if (tok == "end")
     tok = "__end__";
 
-  yylval.tok_val = new token (&(symbol_table::insert (tok)),
-                              input_line_number, current_input_column);
-
-  token_stack.push (yylval.tok_val);
+  push_token (new token (&(symbol_table::insert (tok)),
+                         input_line_number, current_input_column));
 
   // After seeing an identifer, it is ok to convert spaces to a comma
   // (if needed).
 
-  lexer_flags.convert_spaces_to_comma = true;
+  convert_spaces_to_comma = true;
 
   if (! (next_tok_is_eq || YY_START == COMMAND_START))
     {
-      lexer_flags.quote_is_transpose = true;
+      quote_is_transpose = true;
 
       do_comma_insert_check ();
 
       maybe_unput_comma (spc_gobbled);
     }
 
-  current_input_column += yyleng;
+  current_input_column += flex_yyleng ();
 
   if (tok != "__end__")
-    lexer_flags.looking_for_object_index = true;
+    looking_for_object_index = true;
 
   return NAME;
 }
 
 void
-lexical_feedback::init (void)
-{
-  // Not initially defining a matrix list.
-  bracketflag = 0;
-
-  // Not initially defining a cell array list.
-  braceflag = 0;
-
-  // Not initially inside a loop or if statement.
-  looping = 0;
-
-  // Not initially defining a function.
-  defining_func = 0;
-
-  // Not parsing an object index.
-  while (! parsed_function_name.empty ())
-    parsed_function_name.pop ();
-
-  parsing_class_method = false;
-
-  // Not initially defining a class with classdef.
-  maybe_classdef_get_set_method = false;
-  parsing_classdef = false;
-  parsing_classdef_get_method = false;
-  parsing_classdef_set_method = false;
-
-  // Not initiallly looking at a function handle.
-  looking_at_function_handle = 0;
-
-  // Not initiallly looking at an anonymous function argument list.
-  looking_at_anon_fcn_args = 0;
-
-  // Not parsing a function return, parameter, or declaration list.
-  looking_at_return_list = false;
-  looking_at_parameter_list = false;
-  looking_at_decl_list = false;
-
-  // Not looking at an argument list initializer expression.
-  looking_at_initializer_expression = false;
-
-  // Not parsing a matrix or the left hand side of multi-value
-  // assignment statement.
-  looking_at_matrix_or_assign_lhs = false;
-
-  // Not parsing an object index.
-  while (! looking_at_object_index.empty ())
-    looking_at_object_index.pop_front ();
-
-  looking_at_object_index.push_front (false);
-
-  // Object index not possible until we've seen something.
-  looking_for_object_index = false;
-
-  // Yes, we are at the beginning of a statement.
-  at_beginning_of_statement = true;
-
-  // No need to do comma insert or convert spaces to comma at
-  // beginning of input.
-  convert_spaces_to_comma = true;
-  do_comma_insert = false;
-
-  // Not initially looking at indirect references.
-  looking_at_indirect_ref = false;
-
-  // Quote marks strings intially.
-  quote_is_transpose = false;
-
-  // Set of identifiers that might be local variable names is empty.
-  pending_local_variables.clear ();
-}
-
-bool
-is_keyword (const std::string& s)
-{
-  // Parsing function names like "set.property_name" inside
-  // classdef-style class definitions is simplified by handling the
-  // "set" and "get" portions of the names using the same mechanism as
-  // is used for keywords.  However, they are not really keywords in
-  // the language, so omit them from the list of possible keywords.
-
-  return (octave_kw_hash::in_word_set (s.c_str (), s.length ()) != 0
-          && ! (s == "set" || s == "get"));
-}
-
-DEFUN (iskeyword, args, ,
-  "-*- texinfo -*-\n\
-@deftypefn  {Built-in Function} {} iskeyword ()\n\
-@deftypefnx {Built-in Function} {} iskeyword (@var{name})\n\
-Return true if @var{name} is an Octave keyword.  If @var{name}\n\
-is omitted, return a list of keywords.\n\
-@seealso{isvarname, exist}\n\
-@end deftypefn")
-{
-  octave_value retval;
-
-  int argc = args.length () + 1;
-
-  string_vector argv = args.make_argv ("iskeyword");
-
-  if (error_state)
-    return retval;
-
-  if (argc == 1)
-    {
-      // Neither set and get are keywords.  See the note in the
-      // is_keyword function for additional details.
-
-      string_vector lst (TOTAL_KEYWORDS);
-
-      int j = 0;
-
-      for (int i = 0; i < TOTAL_KEYWORDS; i++)
-        {
-          std::string tmp = wordlist[i].name;
-
-          if (! (tmp == "set" || tmp == "get"))
-            lst[j++] = tmp;
-        }
-
-      lst.resize (j);
-
-      retval = Cell (lst.sort ());
-    }
-  else if (argc == 2)
-    {
-      retval = is_keyword (argv[1]);
-    }
-  else
-    print_usage ();
-
-  return retval;
-}
-
-/*
-
-%!assert (iskeyword ("for"))
-%!assert (iskeyword ("fort"), false)
-%!assert (iskeyword ("fft"), false)
-
-*/
-
-void
-prep_lexer_for_script_file (void)
-{
-  BEGIN (SCRIPT_FILE_BEGIN);
-}
-
-void
-prep_lexer_for_function_file (void)
-{
-  BEGIN (FUNCTION_FILE_BEGIN);
-}
-
-void
-prep_lexer_for_classdef_file (void)
-{
-  BEGIN (CLASSDEF_FILE_BEGIN);
-}
-
-static void
-maybe_warn_separator_insert (char sep)
+lexical_feedback::maybe_warn_separator_insert (char sep)
 {
   std::string nm = curr_fcn_file_full_name;
 
@@ -3587,8 +3473,8 @@
                      sep, input_line_number, nm.c_str ());
 }
 
-static void
-gripe_single_quote_string (void)
+void
+lexical_feedback::gripe_single_quote_string (void)
 {
   std::string nm = curr_fcn_file_full_name;
 
@@ -3602,8 +3488,8 @@
                      input_line_number, nm.c_str ());
 }
 
-static void
-gripe_matlab_incompatible (const std::string& msg)
+void
+lexical_feedback::gripe_matlab_incompatible (const std::string& msg)
 {
   std::string nm = curr_fcn_file_full_name;
 
@@ -3617,21 +3503,21 @@
                      msg.c_str (), input_line_number, nm.c_str ());
 }
 
-static void
-maybe_gripe_matlab_incompatible_comment (char c)
+void
+lexical_feedback::maybe_gripe_matlab_incompatible_comment (char c)
 {
   if (c == '#')
     gripe_matlab_incompatible ("# used as comment character");
 }
 
-static void
-gripe_matlab_incompatible_continuation (void)
+void
+lexical_feedback::gripe_matlab_incompatible_continuation (void)
 {
   gripe_matlab_incompatible ("\\ used as line continuation marker");
 }
 
-static void
-gripe_matlab_incompatible_operator (const std::string& op)
+void
+lexical_feedback::gripe_matlab_incompatible_operator (const std::string& op)
 {
   std::string t = op;
   int n = t.length ();
@@ -3640,8 +3526,23 @@
   gripe_matlab_incompatible (t + " used as operator");
 }
 
-static void
-display_token (int tok)
+void
+lexical_feedback::push_token (token *tok)
+{
+  YYSTYPE *lval = yyget_lval (scanner);
+  lval->tok_val = tok;
+  token_stack.push (tok);
+}
+
+token *
+lexical_feedback::current_token (void)
+{
+  YYSTYPE *lval = yyget_lval (scanner);
+  return lval->tok_val;
+}
+
+void
+lexical_feedback::display_token (int tok)
 {
   switch (tok)
     {
@@ -3693,16 +3594,24 @@
 
     case NUM:
     case IMAG_NUM:
-      std::cerr << (tok == NUM ? "NUM" : "IMAG_NUM")
-                << " [" << yylval.tok_val->number () << "]\n";
+      {
+        token *tok_val = current_token ();
+        std::cerr << (tok == NUM ? "NUM" : "IMAG_NUM")
+                  << " [" << tok_val->number () << "]\n";
+      }
       break;
 
     case STRUCT_ELT:
-      std::cerr << "STRUCT_ELT [" << yylval.tok_val->text () << "]\n"; break;
+      {
+        token *tok_val = current_token ();
+        std::cerr << "STRUCT_ELT [" << tok_val->text () << "]\n";
+      }
+      break;
 
     case NAME:
       {
-        symbol_table::symbol_record *sr = yylval.tok_val->sym_rec ();
+        token *tok_val = current_token ();
+        symbol_table::symbol_record *sr = tok_val->sym_rec ();
         std::cerr << "NAME";
         if (sr)
           std::cerr << " [" << sr->name () << "]";
@@ -3714,8 +3623,12 @@
 
     case DQ_STRING:
     case SQ_STRING:
-      std::cerr << (tok == DQ_STRING ? "DQ_STRING" : "SQ_STRING")
-                << " [" << yylval.tok_val->text () << "]\n";
+      {
+        token *tok_val = current_token ();
+
+        std::cerr << (tok == DQ_STRING ? "DQ_STRING" : "SQ_STRING")
+                  << " [" << tok_val->text () << "]\n";
+      }
       break;
 
     case FOR: std::cerr << "FOR\n"; break;
@@ -3768,11 +3681,11 @@
 }
 
 static void
-display_state (void)
+display_state (int state)
 {
   std::cerr << "S: ";
 
-  switch (YY_START)
+  switch (state)
     {
     case INITIAL:
       std::cerr << "INITIAL" << std::endl;
@@ -3804,46 +3717,25 @@
     }
 }
 
-static void
-lexer_debug (const char *pattern, const char *text)
+void
+lexical_feedback::fatal_error (const char *msg)
 {
+  error (msg);
+
+  OCTAVE_QUIT;
+
+  yy_fatal_error (msg, scanner);
+}
+
+void
+lexical_feedback::lexer_debug (const char *pattern, const char *text)
+{
+  OCTAVE_YYG;
+
   std::cerr << std::endl;
 
-  display_state ();
+  display_state (YY_START);
 
   std::cerr << "P: " << pattern << std::endl;
   std::cerr << "T: " << text << std::endl;
 }
-
-DEFUN (__display_tokens__, args, nargout,
-  "-*- texinfo -*-\n\
-@deftypefn {Built-in Function} {} __display_tokens__ ()\n\
-Query or set the internal variable that determines whether Octave's\n\
-lexer displays tokens as they are read.\n\
-@end deftypefn")
-{
-  return SET_INTERNAL_VARIABLE (display_tokens);
-}
-
-DEFUN (__token_count__, , ,
-  "-*- texinfo -*-\n\
-@deftypefn {Built-in Function} {} __token_count__ ()\n\
-Number of language tokens processed since Octave startup.\n\
-@end deftypefn")
-{
-  return octave_value (Vtoken_count);
-}
-
-DEFUN (__lexer_debug_flag__, args, nargout,
-  "-*- texinfo -*-\n\
-@deftypefn {Built-in Function} {@var{old_val} =} __lexer_debug_flag__ (@var{new_val}))\n\
-Undocumented internal function.\n\
-@end deftypefn")
-{
-  octave_value retval;
-
-  retval = set_internal_variable (lexer_debug_flag, args, nargout,
-                                  "__lexer_debug_flag__");
-
-  return retval;
-}
--- a/libinterp/parse-tree/oct-parse.yy	Mon Feb 11 15:45:26 2013 -0500
+++ b/libinterp/parse-tree/oct-parse.yy	Thu Feb 28 02:04:24 2013 -0500
@@ -79,6 +79,15 @@
 #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
@@ -88,18 +97,9 @@
 #define malloc GNULIB_NAMESPACE::malloc
 #endif
 
-// The current input line number.
-int input_line_number = 1;
-
-// The column of the current token.
-int current_input_column = 1;
-
 // Buffer for help text snagged from function files.
 std::stack<std::string> help_buf;
 
-// Buffer for comments appearing before a function statement.
-static std::string fcn_comment_header;
-
 // TRUE means we are using readline.
 // (--no-line-editing)
 bool line_editing = true;
@@ -110,297 +110,16 @@
 // TRUE means input is coming from startup file.
 bool input_from_startup_file = false;
 
-// = 0 currently outside any function.
-// = 1 inside the primary function or a subfunction.
-// > 1 means we are looking at a function definition that seems to be
-//     inside a function. Note that the function still might not be a
-//     nested function.
-static int current_function_depth = 0;
-
-// A stack holding the nested function scopes being parsed.
-// We don't use std::stack, because we want the clear method. Also, we
-// must access one from the top
-static std::vector<symbol_table::scope_id> function_scopes;
-
-// Maximum function depth detected. Just here to determine whether
-// we have nested functions or just implicitly ended subfunctions.
-static int max_function_depth = 0;
-
-// FALSE if we are still at the primary function. Subfunctions can
-// only be declared inside function files.
-static int parsing_subfunctions = false;
-
-// Have we found an explicit end to a function?
-static bool endfunction_found = false;
-
 // Keep track of symbol table information when parsing functions.
 symtab_context parser_symtab_context;
 
-// Name of the current class when we are parsing class methods or
-// constructors.
-std::string current_class_name;
-
-// TRUE means we are in the process of autoloading a function.
-static bool autoloading = false;
-
-// TRUE means the current function file was found in a relative path
-// element.
-static bool fcn_file_from_relative_lookup = false;
-
-// Pointer to the primary user function or user script function.
-static octave_function *primary_fcn_ptr = 0;
-
-// Scope where we install all subfunctions and nested functions. Only
-// used while reading function files.
-static symbol_table::scope_id primary_fcn_scope;
-
-// Pointer to the classdef object we just parsed, if any.
-static tree_classdef *classdef_object = 0;
-
 // 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.
 
-// Generic error messages.
-static void
-yyerror (const char *s);
-
-// Error mesages for mismatched end tokens.
-static void
-end_error (const char *type, token::end_tok_type ettype, int l, int c);
-
-// Check to see that end tokens are properly matched.
-static bool
-end_token_ok (token *tok, token::end_tok_type expected);
-
-// Maybe print a warning if an assignment expression is used as the
-// test in a logical expression.
-static void
-maybe_warn_assign_as_truth_value (tree_expression *expr);
-
-// Maybe print a warning about switch labels that aren't constants.
-static void
-maybe_warn_variable_switch_label (tree_expression *expr);
-
-// Finish building a range.
-static tree_expression *
-finish_colon_expression (tree_colon_expression *e);
-
-// Build a constant.
-static tree_constant *
-make_constant (int op, token *tok_val);
-
-// Build a function handle.
-static tree_fcn_handle *
-make_fcn_handle (token *tok_val);
-
-// Build an anonymous function handle.
-static tree_anon_fcn_handle *
-make_anon_fcn_handle (tree_parameter_list *param_list, tree_statement *stmt);
-
-// Build a binary expression.
-static tree_expression *
-make_binary_op (int op, tree_expression *op1, token *tok_val,
-                tree_expression *op2);
-
-// Build a boolean expression.
-static tree_expression *
-make_boolean_op (int op, tree_expression *op1, token *tok_val,
-                 tree_expression *op2);
-
-// Build a prefix expression.
-static tree_expression *
-make_prefix_op (int op, tree_expression *op1, token *tok_val);
-
-// Build a postfix expression.
-static tree_expression *
-make_postfix_op (int op, tree_expression *op1, token *tok_val);
-
-// Build an unwind-protect command.
-static tree_command *
-make_unwind_command (token *unwind_tok, tree_statement_list *body,
-                     tree_statement_list *cleanup, token *end_tok,
-                     octave_comment_list *lc, octave_comment_list *mc);
-
-// Build a try-catch command.
-static tree_command *
-make_try_command (token *try_tok, tree_statement_list *body,
-                  tree_statement_list *cleanup, token *end_tok,
-                  octave_comment_list *lc, octave_comment_list *mc);
-
-// Build a while command.
-static tree_command *
-make_while_command (token *while_tok, tree_expression *expr,
-                    tree_statement_list *body, token *end_tok,
-                    octave_comment_list *lc);
-
-// Build a do-until command.
-static tree_command *
-make_do_until_command (token *until_tok, tree_statement_list *body,
-                       tree_expression *expr, octave_comment_list *lc);
-
-// Build a for command.
-static tree_command *
-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);
-
-// Build a break command.
-static tree_command *
-make_break_command (token *break_tok);
-
-// Build a continue command.
-static tree_command *
-make_continue_command (token *continue_tok);
-
-// Build a return command.
-static tree_command *
-make_return_command (token *return_tok);
-
-// Start an if command.
-static tree_if_command_list *
-start_if_command (tree_expression *expr, tree_statement_list *list);
-
-// Finish an if command.
-static tree_if_command *
-finish_if_command (token *if_tok, tree_if_command_list *list,
-                   token *end_tok, octave_comment_list *lc);
-
-// Build an elseif clause.
-static tree_if_clause *
-make_elseif_clause (token *elseif_tok, tree_expression *expr,
-                    tree_statement_list *list, octave_comment_list *lc);
-
-// Finish a switch command.
-static tree_switch_command *
-finish_switch_command (token *switch_tok, tree_expression *expr,
-                       tree_switch_case_list *list, token *end_tok,
-                       octave_comment_list *lc);
-
-// Build a switch case.
-static tree_switch_case *
-make_switch_case (token *case_tok, tree_expression *expr,
-                  tree_statement_list *list, octave_comment_list *lc);
-
-// Build an assignment to a variable.
-static tree_expression *
-make_assign_op (int op, tree_argument_list *lhs, token *eq_tok,
-                tree_expression *rhs);
-
-// Define a script.
-static void
-make_script (tree_statement_list *cmds, tree_statement *end_script);
-
-// Begin defining a function.
-static octave_user_function *
-start_function (tree_parameter_list *param_list, tree_statement_list *body,
-                tree_statement *end_function);
-
-// Create a no-op statement for end_function.
-static tree_statement *
-make_end (const std::string& type, int l, int c);
-
-// Do most of the work for defining a function.
-static octave_user_function *
-frob_function (const std::string& fname, octave_user_function *fcn);
-
-// Finish defining a function.
-static tree_function_def *
-finish_function (tree_parameter_list *ret_list,
-                 octave_user_function *fcn, octave_comment_list *lc);
-
-// Reset state after parsing function.
-static void
-recover_from_parsing_function (void);
-
-// Make an index expression.
-static tree_index_expression *
-make_index_expression (tree_expression *expr,
-                       tree_argument_list *args, char type);
-
-// Make an indirect reference expression.
-static tree_index_expression *
-make_indirect_ref (tree_expression *expr, const std::string&);
-
-// Make an indirect reference expression with dynamic field name.
-static tree_index_expression *
-make_indirect_ref (tree_expression *expr, tree_expression *field);
-
-// Make a declaration command.
-static tree_decl_command *
-make_decl_command (int tok, token *tok_val, tree_decl_init_list *lst);
-
-// Validate argument list forming a matrix or cell row.
-static tree_argument_list *
-validate_matrix_row (tree_argument_list *row);
-
-// Finish building a matrix list.
-static tree_expression *
-finish_matrix (tree_matrix *m);
-
-// Finish building a cell list.
-static tree_expression *
-finish_cell (tree_cell *c);
-
-// Maybe print a warning.  Duh.
-static void
-maybe_warn_missing_semi (tree_statement_list *);
-
-// Set the print flag for a statement based on the separator type.
-static tree_statement_list *
-set_stmt_print_flag (tree_statement_list *, char, bool);
-
-// Create a statement list.
-static tree_statement_list *make_statement_list (tree_statement *stmt);
-
-// Append a statement to an existing statement list.
-static tree_statement_list *
-append_statement_list (tree_statement_list *list, char sep,
-                       tree_statement *stmt, bool warn_missing_semi);
-
-static tree_funcall *
-make_superclass_ref (const std::string& method_nm,
-                     const std::string& package_nm,
-                     const std::string& class_nm,
-                     int l, int c);
-
-static tree_funcall *
-make_meta_class_query (const std::string& package_nm,
-                       const std::string& class_nm,
-                       int l, int c);
-
-static tree_classdef *
-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);
-
-static tree_classdef_properties_block *
-make_classdef_properties_block (token *tok_val,
-                                tree_classdef_attribute_list *a,
-                                tree_classdef_property_list *plist,
-                                token *end_tok, octave_comment_list *lc);
-
-static tree_classdef_methods_block *
-make_classdef_methods_block (token *tok_val,
-                             tree_classdef_attribute_list *a,
-                             tree_classdef_methods_list *mlist,
-                             token *end_tok, octave_comment_list *lc);
-
-static tree_classdef_events_block *
-make_classdef_events_block (token *tok_val,
-                            tree_classdef_attribute_list *a,
-                            tree_classdef_events_list *elist,
-                            token *end_tok, octave_comment_list *lc);
-
-static tree_classdef_enum_block *
-make_classdef_enum_block (token *tok_val,
-                          tree_classdef_attribute_list *a,
-                          tree_classdef_enum_list *elist,
-                          token *end_tok, octave_comment_list *lc);
+static void yyerror (octave_parser *curr_parser, const char *s);
 
 // Finish building a statement.
 template <class T>
@@ -427,6 +146,9 @@
     } \
   while (0)
 
+#define curr_lexer curr_parser->curr_lexer
+#define scanner curr_lexer->scanner
+
 %}
 
 // Bison declarations.
@@ -436,6 +158,19 @@
 
 %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.
@@ -633,7 +368,7 @@
                   { $$ = 0; }
                 | END_OF_INPUT
                   {
-                    parser_end_of_input = 1;
+                    curr_parser->end_of_input = true;
                     $$ = 0;
                   }
                 | simple_list
@@ -645,13 +380,13 @@
                 ;
 
 simple_list     : simple_list1 opt_sep_no_nl
-                  { $$ = set_stmt_print_flag ($1, $2, false); }
+                  { $$ = curr_parser->set_stmt_print_flag ($1, $2, false); }
                 ;
 
 simple_list1    : statement
-                  { $$ = make_statement_list ($1); }
+                  { $$ = curr_parser->make_statement_list ($1); }
                 | simple_list1 sep_no_nl statement
-                  { $$ = append_statement_list ($1, $2, $3, false); }
+                  { $$ = curr_parser->append_statement_list ($1, $2, $3, false); }
                 ;
 
 opt_list        : // empty
@@ -661,13 +396,13 @@
                 ;
 
 list            : list1 opt_sep
-                  { $$ = set_stmt_print_flag ($1, $2, true); }
+                  { $$ = curr_parser->set_stmt_print_flag ($1, $2, true); }
                 ;
 
 list1           : statement
-                  { $$ = make_statement_list ($1); }
+                  { $$ = curr_parser->make_statement_list ($1); }
                 | list1 sep statement
-                  { $$ = append_statement_list ($1, $2, $3, true); }
+                  { $$ = curr_parser->append_statement_list ($1, $2, $3, true); }
                 ;
 
 statement       : expression
@@ -687,7 +422,7 @@
 // WHILE, etc.
 
 word_list_cmd   : identifier word_list
-                  { $$ = make_index_expression ($1, $2, '('); }
+                  { $$ = curr_parser->make_index_expression ($1, $2, '('); }
                 ;
 
 word_list       : string
@@ -717,8 +452,9 @@
                     std::string package_nm = $1->superclass_package_name ();
                     std::string class_nm = $1->superclass_class_name ();
 
-                    $$ = make_superclass_ref (method_nm, package_nm, class_nm,
-                                              $1->line (), $1->column ());
+                    $$ = curr_parser->make_superclass_ref
+                                        (method_nm, package_nm, class_nm,
+                                         $1->line (), $1->column ());
                   }
                 ;
 
@@ -727,21 +463,22 @@
                     std::string package_nm = $1->meta_package_name ();
                     std::string class_nm = $1->meta_class_name ();
 
-                    $$ = make_meta_class_query (package_nm, class_nm,
-                                                $1->line (), $1->column ());
+                    $$ = curr_parser->make_meta_class_query
+                                        (package_nm, class_nm,
+                                         $1->line (), $1->column ());
                   }
                 ;
 
 string          : DQ_STRING
-                  { $$ = make_constant (DQ_STRING, $1); }
+                  { $$ = curr_parser->make_constant (DQ_STRING, $1); }
                 | SQ_STRING
-                  { $$ = make_constant (SQ_STRING, $1); }
+                  { $$ = curr_parser->make_constant (SQ_STRING, $1); }
                 ;
 
 constant        : NUM
-                  { $$ = make_constant (NUM, $1); }
+                  { $$ = curr_parser->make_constant (NUM, $1); }
                 | IMAG_NUM
-                  { $$ = make_constant (IMAG_NUM, $1); }
+                  { $$ = curr_parser->make_constant (IMAG_NUM, $1); }
                 | string
                   { $$ = $1; }
                 ;
@@ -749,26 +486,26 @@
 matrix          : '[' ']'
                   {
                     $$ = new tree_constant (octave_null_matrix::instance);
-                    lexer_flags.looking_at_matrix_or_assign_lhs = false;
-                    lexer_flags.pending_local_variables.clear ();
+                    curr_lexer->looking_at_matrix_or_assign_lhs = false;
+                    curr_lexer->pending_local_variables.clear ();
                   }
                 | '[' ';' ']'
                   {
                     $$ = new tree_constant (octave_null_matrix::instance);
-                    lexer_flags.looking_at_matrix_or_assign_lhs = false;
-                    lexer_flags.pending_local_variables.clear ();
+                    curr_lexer->looking_at_matrix_or_assign_lhs = false;
+                    curr_lexer->pending_local_variables.clear ();
                   }
                 | '[' ',' ']'
                   {
                     $$ = new tree_constant (octave_null_matrix::instance);
-                    lexer_flags.looking_at_matrix_or_assign_lhs = false;
-                    lexer_flags.pending_local_variables.clear ();
+                    curr_lexer->looking_at_matrix_or_assign_lhs = false;
+                    curr_lexer->pending_local_variables.clear ();
                   }
                 | '[' matrix_rows ']'
                   {
-                    $$ = finish_matrix ($2);
-                    lexer_flags.looking_at_matrix_or_assign_lhs = false;
-                    lexer_flags.pending_local_variables.clear ();
+                    $$ = curr_parser->finish_matrix ($2);
+                    curr_lexer->looking_at_matrix_or_assign_lhs = false;
+                    curr_lexer->pending_local_variables.clear ();
                   }
                 ;
 
@@ -792,7 +529,7 @@
                 | '{' ';' '}'
                   { $$ = new tree_constant (octave_value (Cell ())); }
                 | '{' cell_rows '}'
-                  { $$ = finish_cell ($2); }
+                  { $$ = curr_parser->finish_cell ($2); }
                 ;
 
 cell_rows       : cell_rows1
@@ -812,22 +549,22 @@
 
 cell_or_matrix_row
                 : arg_list
-                  { $$ = validate_matrix_row ($1); }
+                  { $$ = curr_parser->validate_matrix_row ($1); }
                 | arg_list ','  // Ignore trailing comma.
-                  { $$ = validate_matrix_row ($1); }
+                  { $$ = curr_parser->validate_matrix_row ($1); }
                 ;
 
 fcn_handle      : '@' FCN_HANDLE
                   {
-                    $$ = make_fcn_handle ($2);
-                    lexer_flags.looking_at_function_handle--;
+                    $$ = curr_parser->make_fcn_handle ($2);
+                    curr_lexer->looking_at_function_handle--;
                   }
                 ;
 
 anon_fcn_handle : '@' param_list statement
                   {
-                    lexer_flags.quote_is_transpose = false;
-                    $$ = make_anon_fcn_handle ($2, $3);
+                    curr_lexer->quote_is_transpose = false;
+                    $$ = curr_parser->make_anon_fcn_handle ($2, $3);
                   }
                 ;
 
@@ -886,69 +623,69 @@
                 ;
 
 indirect_ref_op : '.'
-                  { lexer_flags.looking_at_indirect_ref = true; }
+                  { curr_lexer->looking_at_indirect_ref = true; }
                 ;
 
 oper_expr       : primary_expr
                   { $$ = $1; }
                 | oper_expr PLUS_PLUS
-                  { $$ = make_postfix_op (PLUS_PLUS, $1, $2); }
+                  { $$ = curr_parser->make_postfix_op (PLUS_PLUS, $1, $2); }
                 | oper_expr MINUS_MINUS
-                  { $$ = make_postfix_op (MINUS_MINUS, $1, $2); }
+                  { $$ = curr_parser->make_postfix_op (MINUS_MINUS, $1, $2); }
                 | oper_expr '(' ')'
-                  { $$ = make_index_expression ($1, 0, '('); }
+                  { $$ = curr_parser->make_index_expression ($1, 0, '('); }
                 | oper_expr '(' arg_list ')'
-                  { $$ = make_index_expression ($1, $3, '('); }
+                  { $$ = curr_parser->make_index_expression ($1, $3, '('); }
                 | oper_expr '{' '}'
-                  { $$ = make_index_expression ($1, 0, '{'); }
+                  { $$ = curr_parser->make_index_expression ($1, 0, '{'); }
                 | oper_expr '{' arg_list '}'
-                  { $$ = make_index_expression ($1, $3, '{'); }
+                  { $$ = curr_parser->make_index_expression ($1, $3, '{'); }
                 | oper_expr QUOTE
-                  { $$ = make_postfix_op (QUOTE, $1, $2); }
+                  { $$ = curr_parser->make_postfix_op (QUOTE, $1, $2); }
                 | oper_expr TRANSPOSE
-                  { $$ = make_postfix_op (TRANSPOSE, $1, $2); }
+                  { $$ = curr_parser->make_postfix_op (TRANSPOSE, $1, $2); }
                 | oper_expr indirect_ref_op STRUCT_ELT
-                  { $$ = make_indirect_ref ($1, $3->text ()); }
+                  { $$ = curr_parser->make_indirect_ref ($1, $3->text ()); }
                 | oper_expr indirect_ref_op '(' expression ')'
-                  { $$ = make_indirect_ref ($1, $4); }
+                  { $$ = curr_parser->make_indirect_ref ($1, $4); }
                 | PLUS_PLUS oper_expr %prec UNARY
-                  { $$ = make_prefix_op (PLUS_PLUS, $2, $1); }
+                  { $$ = curr_parser->make_prefix_op (PLUS_PLUS, $2, $1); }
                 | MINUS_MINUS oper_expr %prec UNARY
-                  { $$ = make_prefix_op (MINUS_MINUS, $2, $1); }
+                  { $$ = curr_parser->make_prefix_op (MINUS_MINUS, $2, $1); }
                 | EXPR_NOT oper_expr %prec UNARY
-                  { $$ = make_prefix_op (EXPR_NOT, $2, $1); }
+                  { $$ = curr_parser->make_prefix_op (EXPR_NOT, $2, $1); }
                 | '+' oper_expr %prec UNARY
-                  { $$ = make_prefix_op ('+', $2, $1); }
+                  { $$ = curr_parser->make_prefix_op ('+', $2, $1); }
                 | '-' oper_expr %prec UNARY
-                  { $$ = make_prefix_op ('-', $2, $1); }
+                  { $$ = curr_parser->make_prefix_op ('-', $2, $1); }
                 | oper_expr POW oper_expr
-                  { $$ = make_binary_op (POW, $1, $2, $3); }
+                  { $$ = curr_parser->make_binary_op (POW, $1, $2, $3); }
                 | oper_expr EPOW oper_expr
-                  { $$ = make_binary_op (EPOW, $1, $2, $3); }
+                  { $$ = curr_parser->make_binary_op (EPOW, $1, $2, $3); }
                 | oper_expr '+' oper_expr
-                  { $$ = make_binary_op ('+', $1, $2, $3); }
+                  { $$ = curr_parser->make_binary_op ('+', $1, $2, $3); }
                 | oper_expr '-' oper_expr
-                  { $$ = make_binary_op ('-', $1, $2, $3); }
+                  { $$ = curr_parser->make_binary_op ('-', $1, $2, $3); }
                 | oper_expr '*' oper_expr
-                  { $$ = make_binary_op ('*', $1, $2, $3); }
+                  { $$ = curr_parser->make_binary_op ('*', $1, $2, $3); }
                 | oper_expr '/' oper_expr
-                  { $$ = make_binary_op ('/', $1, $2, $3); }
+                  { $$ = curr_parser->make_binary_op ('/', $1, $2, $3); }
                 | oper_expr EPLUS oper_expr
-                  { $$ = make_binary_op ('+', $1, $2, $3); }
+                  { $$ = curr_parser->make_binary_op ('+', $1, $2, $3); }
                 | oper_expr EMINUS oper_expr
-                  { $$ = make_binary_op ('-', $1, $2, $3); }
+                  { $$ = curr_parser->make_binary_op ('-', $1, $2, $3); }
                 | oper_expr EMUL oper_expr
-                  { $$ = make_binary_op (EMUL, $1, $2, $3); }
+                  { $$ = curr_parser->make_binary_op (EMUL, $1, $2, $3); }
                 | oper_expr EDIV oper_expr
-                  { $$ = make_binary_op (EDIV, $1, $2, $3); }
+                  { $$ = curr_parser->make_binary_op (EDIV, $1, $2, $3); }
                 | oper_expr LEFTDIV oper_expr
-                  { $$ = make_binary_op (LEFTDIV, $1, $2, $3); }
+                  { $$ = curr_parser->make_binary_op (LEFTDIV, $1, $2, $3); }
                 | oper_expr ELEFTDIV oper_expr
-                  { $$ = make_binary_op (ELEFTDIV, $1, $2, $3); }
+                  { $$ = curr_parser->make_binary_op (ELEFTDIV, $1, $2, $3); }
                 ;
 
 colon_expr      : colon_expr1
-                  { $$ = finish_colon_expression ($1); }
+                  { $$ = curr_parser->finish_colon_expression ($1); }
                 ;
 
 colon_expr1     : oper_expr
@@ -963,29 +700,29 @@
 simple_expr     : colon_expr
                   { $$ = $1; }
                 | simple_expr LSHIFT simple_expr
-                  { $$ = make_binary_op (LSHIFT, $1, $2, $3); }
+                  { $$ = curr_parser->make_binary_op (LSHIFT, $1, $2, $3); }
                 | simple_expr RSHIFT simple_expr
-                  { $$ = make_binary_op (RSHIFT, $1, $2, $3); }
+                  { $$ = curr_parser->make_binary_op (RSHIFT, $1, $2, $3); }
                 | simple_expr EXPR_LT simple_expr
-                  { $$ = make_binary_op (EXPR_LT, $1, $2, $3); }
+                  { $$ = curr_parser->make_binary_op (EXPR_LT, $1, $2, $3); }
                 | simple_expr EXPR_LE simple_expr
-                  { $$ = make_binary_op (EXPR_LE, $1, $2, $3); }
+                  { $$ = curr_parser->make_binary_op (EXPR_LE, $1, $2, $3); }
                 | simple_expr EXPR_EQ simple_expr
-                  { $$ = make_binary_op (EXPR_EQ, $1, $2, $3); }
+                  { $$ = curr_parser->make_binary_op (EXPR_EQ, $1, $2, $3); }
                 | simple_expr EXPR_GE simple_expr
-                  { $$ = make_binary_op (EXPR_GE, $1, $2, $3); }
+                  { $$ = curr_parser->make_binary_op (EXPR_GE, $1, $2, $3); }
                 | simple_expr EXPR_GT simple_expr
-                  { $$ = make_binary_op (EXPR_GT, $1, $2, $3); }
+                  { $$ = curr_parser->make_binary_op (EXPR_GT, $1, $2, $3); }
                 | simple_expr EXPR_NE simple_expr
-                  { $$ = make_binary_op (EXPR_NE, $1, $2, $3); }
+                  { $$ = curr_parser->make_binary_op (EXPR_NE, $1, $2, $3); }
                 | simple_expr EXPR_AND simple_expr
-                  { $$ = make_binary_op (EXPR_AND, $1, $2, $3); }
+                  { $$ = curr_parser->make_binary_op (EXPR_AND, $1, $2, $3); }
                 | simple_expr EXPR_OR simple_expr
-                  { $$ = make_binary_op (EXPR_OR, $1, $2, $3); }
+                  { $$ = curr_parser->make_binary_op (EXPR_OR, $1, $2, $3); }
                 | simple_expr EXPR_AND_AND simple_expr
-                  { $$ = make_boolean_op (EXPR_AND_AND, $1, $2, $3); }
+                  { $$ = curr_parser->make_boolean_op (EXPR_AND_AND, $1, $2, $3); }
                 | simple_expr EXPR_OR_OR simple_expr
-                  { $$ = make_boolean_op (EXPR_OR_OR, $1, $2, $3); }
+                  { $$ = curr_parser->make_boolean_op (EXPR_OR_OR, $1, $2, $3); }
                 ;
 
 // Arrange for the lexer to return CLOSE_BRACE for ']' by looking ahead
@@ -999,47 +736,47 @@
                 | '[' arg_list opt_comma CLOSE_BRACE
                   {
                     $$ = $2;
-                    lexer_flags.looking_at_matrix_or_assign_lhs = false;
-                    for (std::set<std::string>::const_iterator p = lexer_flags.pending_local_variables.begin ();
-                         p != lexer_flags.pending_local_variables.end ();
+                    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);
                       }
-                    lexer_flags.pending_local_variables.clear ();
+                    curr_lexer->pending_local_variables.clear ();
                   }
                 ;
 
 assign_expr     : assign_lhs '=' expression
-                  { $$ = make_assign_op ('=', $1, $2, $3); }
+                  { $$ = curr_parser->make_assign_op ('=', $1, $2, $3); }
                 | assign_lhs ADD_EQ expression
-                  { $$ = make_assign_op (ADD_EQ, $1, $2, $3); }
+                  { $$ = curr_parser->make_assign_op (ADD_EQ, $1, $2, $3); }
                 | assign_lhs SUB_EQ expression
-                  { $$ = make_assign_op (SUB_EQ, $1, $2, $3); }
+                  { $$ = curr_parser->make_assign_op (SUB_EQ, $1, $2, $3); }
                 | assign_lhs MUL_EQ expression
-                  { $$ = make_assign_op (MUL_EQ, $1, $2, $3); }
+                  { $$ = curr_parser->make_assign_op (MUL_EQ, $1, $2, $3); }
                 | assign_lhs DIV_EQ expression
-                  { $$ = make_assign_op (DIV_EQ, $1, $2, $3); }
+                  { $$ = curr_parser->make_assign_op (DIV_EQ, $1, $2, $3); }
                 | assign_lhs LEFTDIV_EQ expression
-                  { $$ = make_assign_op (LEFTDIV_EQ, $1, $2, $3); }
+                  { $$ = curr_parser->make_assign_op (LEFTDIV_EQ, $1, $2, $3); }
                 | assign_lhs POW_EQ expression
-                  { $$ = make_assign_op (POW_EQ, $1, $2, $3); }
+                  { $$ = curr_parser->make_assign_op (POW_EQ, $1, $2, $3); }
                 | assign_lhs LSHIFT_EQ expression
-                  { $$ = make_assign_op (LSHIFT_EQ, $1, $2, $3); }
+                  { $$ = curr_parser->make_assign_op (LSHIFT_EQ, $1, $2, $3); }
                 | assign_lhs RSHIFT_EQ expression
-                  { $$ = make_assign_op (RSHIFT_EQ, $1, $2, $3); }
+                  { $$ = curr_parser->make_assign_op (RSHIFT_EQ, $1, $2, $3); }
                 | assign_lhs EMUL_EQ expression
-                  { $$ = make_assign_op (EMUL_EQ, $1, $2, $3); }
+                  { $$ = curr_parser->make_assign_op (EMUL_EQ, $1, $2, $3); }
                 | assign_lhs EDIV_EQ expression
-                  { $$ = make_assign_op (EDIV_EQ, $1, $2, $3); }
+                  { $$ = curr_parser->make_assign_op (EDIV_EQ, $1, $2, $3); }
                 | assign_lhs ELEFTDIV_EQ expression
-                  { $$ = make_assign_op (ELEFTDIV_EQ, $1, $2, $3); }
+                  { $$ = curr_parser->make_assign_op (ELEFTDIV_EQ, $1, $2, $3); }
                 | assign_lhs EPOW_EQ expression
-                  { $$ = make_assign_op (EPOW_EQ, $1, $2, $3); }
+                  { $$ = curr_parser->make_assign_op (EPOW_EQ, $1, $2, $3); }
                 | assign_lhs AND_EQ expression
-                  { $$ = make_assign_op (AND_EQ, $1, $2, $3); }
+                  { $$ = curr_parser->make_assign_op (AND_EQ, $1, $2, $3); }
                 | assign_lhs OR_EQ expression
-                  { $$ = make_assign_op (OR_EQ, $1, $2, $3); }
+                  { $$ = curr_parser->make_assign_op (OR_EQ, $1, $2, $3); }
                 ;
 
 expression      : simple_expr
@@ -1076,17 +813,17 @@
 
 parsing_decl_list
                 : // empty
-                  { lexer_flags.looking_at_decl_list = true; }
+                  { curr_lexer->looking_at_decl_list = true; }
 
 declaration     : GLOBAL parsing_decl_list decl1
                   {
-                    $$ = make_decl_command (GLOBAL, $1, $3);
-                    lexer_flags.looking_at_decl_list = false;
+                    $$ = curr_parser->make_decl_command (GLOBAL, $1, $3);
+                    curr_lexer->looking_at_decl_list = false;
                   }
                 | PERSISTENT parsing_decl_list decl1
                   {
-                    $$ = make_decl_command (PERSISTENT, $1, $3);
-                    lexer_flags.looking_at_decl_list = false;
+                    $$ = curr_parser->make_decl_command (PERSISTENT, $1, $3);
+                    curr_lexer->looking_at_decl_list = false;
                   }
                 ;
 
@@ -1100,13 +837,13 @@
                 ;
 
 decl_param_init : // empty
-                { lexer_flags.looking_at_initializer_expression = true; }
+                { curr_lexer->looking_at_initializer_expression = true; }
 
 decl2           : identifier
                   { $$ = new tree_decl_elt ($1); }
                 | identifier '=' decl_param_init expression
                   {
-                    lexer_flags.looking_at_initializer_expression = false;
+                    curr_lexer->looking_at_initializer_expression = false;
                     $$ = new tree_decl_elt ($1, $4);
                   }
                 | magic_tilde
@@ -1131,7 +868,7 @@
 
 if_command      : IF stash_comment if_cmd_list END
                   {
-                    if (! ($$ = finish_if_command ($1, $3, $4, $2)))
+                    if (! ($$ = curr_parser->finish_if_command ($1, $3, $4, $2)))
                       ABORT_PARSE;
                   }
                 ;
@@ -1149,7 +886,7 @@
                   {
                     $1->mark_braindead_shortcircuit (curr_fcn_file_full_name);
 
-                    $$ = start_if_command ($1, $3);
+                    $$ = curr_parser->start_if_command ($1, $3);
                   }
                 | if_cmd_list1 elseif_clause
                   {
@@ -1162,7 +899,7 @@
                   {
                     $4->mark_braindead_shortcircuit (curr_fcn_file_full_name);
 
-                    $$ = make_elseif_clause ($1, $4, $6, $2);
+                    $$ = curr_parser->make_elseif_clause ($1, $4, $6, $2);
                   }
                 ;
 
@@ -1176,7 +913,7 @@
 
 switch_command  : SWITCH stash_comment expression opt_sep case_list END
                   {
-                    if (! ($$ = finish_switch_command ($1, $3, $5, $6, $2)))
+                    if (! ($$ = curr_parser->finish_switch_command ($1, $3, $5, $6, $2)))
                       ABORT_PARSE;
                   }
                 ;
@@ -1204,7 +941,7 @@
                 ;
 
 switch_case     : CASE stash_comment opt_sep expression opt_sep opt_list
-                  { $$ = make_switch_case ($1, $4, $6, $2); }
+                  { $$ = curr_parser->make_switch_case ($1, $4, $6, $2); }
                 ;
 
 default_case    : OTHERWISE stash_comment opt_sep opt_list
@@ -1221,35 +958,35 @@
                   {
                     $3->mark_braindead_shortcircuit (curr_fcn_file_full_name);
 
-                    if (! ($$ = make_while_command ($1, $3, $5, $6, $2)))
+                    if (! ($$ = curr_parser->make_while_command ($1, $3, $5, $6, $2)))
                       ABORT_PARSE;
                   }
                 | DO stash_comment opt_sep opt_list UNTIL expression
                   {
-                    if (! ($$ = make_do_until_command ($5, $4, $6, $2)))
+                    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 (! ($$ = make_for_command (FOR, $1, $3, $5, 0,
+                    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 (! ($$ = make_for_command (FOR, $1, $4, $6, 0,
+                    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 (! ($$ = make_for_command (PARFOR, $1, $3, $5,
+                    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 (! ($$ = make_for_command (PARFOR, $1, $4, $6,
+                    if (! ($$ = curr_parser->make_for_command (PARFOR, $1, $4, $6,
                                                   $8, $11, $12, $2)))
                       ABORT_PARSE;
                   }
@@ -1261,17 +998,17 @@
 
 jump_command    : BREAK
                   {
-                    if (! ($$ = make_break_command ($1)))
+                    if (! ($$ = curr_parser->make_break_command ($1)))
                       ABORT_PARSE;
                   }
                 | CONTINUE
                   {
-                    if (! ($$ = make_continue_command ($1)))
+                    if (! ($$ = curr_parser->make_continue_command ($1)))
                       ABORT_PARSE;
                   }
                 | FUNC_RET
                   {
-                    if (! ($$ = make_return_command ($1)))
+                    if (! ($$ = curr_parser->make_return_command ($1)))
                       ABORT_PARSE;
                   }
                 ;
@@ -1283,18 +1020,18 @@
 except_command  : UNWIND stash_comment opt_sep opt_list CLEANUP
                   stash_comment opt_sep opt_list END
                   {
-                    if (! ($$ = make_unwind_command ($1, $4, $8, $9, $2, $6)))
+                    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 (! ($$ = make_try_command ($1, $4, $8, $9, $2, $6)))
+                    if (! ($$ = curr_parser->make_try_command ($1, $4, $8, $9, $2, $6)))
                       ABORT_PARSE;
                   }
                 | TRY stash_comment opt_sep opt_list END
                   {
-                    if (! ($$ = make_try_command ($1, $4, 0, $5, $2, 0)))
+                    if (! ($$ = curr_parser->make_try_command ($1, $4, 0, $5, $2, 0)))
                       ABORT_PARSE;
                   }
                 ;
@@ -1305,23 +1042,23 @@
 
 push_fcn_symtab : // empty
                   {
-                    current_function_depth++;
-
-                    if (max_function_depth < current_function_depth)
-                      max_function_depth = current_function_depth;
+                    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 ());
 
-                    function_scopes.push_back (symbol_table::current_scope ());
-
-                    if (! reading_script_file && current_function_depth == 1
-                        && ! parsing_subfunctions)
-                      primary_fcn_scope = symbol_table::current_scope ();
-
-                    if (reading_script_file && current_function_depth > 1)
-                      yyerror ("nested functions not implemented in this context");
+                    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");
                   }
                 ;
 
@@ -1331,33 +1068,33 @@
 
 param_list_beg  : '('
                   {
-                    lexer_flags.looking_at_parameter_list = true;
-
-                    if (lexer_flags.looking_at_function_handle)
+                    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 ());
-                        lexer_flags.looking_at_function_handle--;
-                        lexer_flags.looking_at_anon_fcn_args = true;
+                        curr_lexer->looking_at_function_handle--;
+                        curr_lexer->looking_at_anon_fcn_args = true;
                       }
                   }
                 ;
 
 param_list_end  : ')'
                   {
-                    lexer_flags.looking_at_parameter_list = false;
-                    lexer_flags.looking_for_object_index = false;
+                    curr_lexer->looking_at_parameter_list = false;
+                    curr_lexer->looking_for_object_index = false;
                   }
                 ;
 
 param_list      : param_list_beg param_list1 param_list_end
                   {
-                    lexer_flags.quote_is_transpose = false;
+                    curr_lexer->quote_is_transpose = false;
                     $$ = $2;
                   }
                 | param_list_beg error
                   {
-                    yyerror ("invalid parameter list");
+                    curr_parser->bison_error ("invalid parameter list");
                     $$ = 0;
                     ABORT_PARSE;
                   }
@@ -1390,12 +1127,12 @@
 
 return_list     : '[' ']'
                   {
-                    lexer_flags.looking_at_return_list = false;
+                    curr_lexer->looking_at_return_list = false;
                     $$ = new tree_parameter_list ();
                   }
                 | return_list1
                   {
-                    lexer_flags.looking_at_return_list = false;
+                    curr_lexer->looking_at_return_list = false;
                     if ($1->validate (tree_parameter_list::out))
                       $$ = $1;
                     else
@@ -1403,7 +1140,7 @@
                   }
                 | '[' return_list1 ']'
                   {
-                    lexer_flags.looking_at_return_list = false;
+                    curr_lexer->looking_at_return_list = false;
                     if ($2->validate (tree_parameter_list::out))
                       $$ = $2;
                     else
@@ -1427,10 +1164,11 @@
 script_file     : SCRIPT_FILE opt_list END_OF_INPUT
                   {
                     tree_statement *end_of_script
-                      = make_end ("endscript", input_line_number,
-                                  current_input_column);
-
-                    make_script ($2, 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;
                   }
@@ -1456,20 +1194,20 @@
                   {
                     $$ = $3;
 
-                    if (reading_classdef_file || lexer_flags.parsing_classdef)
-                      lexer_flags.maybe_classdef_get_set_method = true;
+                    if (reading_classdef_file || curr_lexer->parsing_classdef)
+                      curr_lexer->maybe_classdef_get_set_method = true;
                   }
                 ;
 
 function        : function_beg function1
                   {
-                    $$ = finish_function (0, $2, $1);
-                    recover_from_parsing_function ();
+                    $$ = curr_parser->finish_function (0, $2, $1);
+                    curr_parser->recover_from_parsing_function ();
                   }
                 | function_beg return_list '=' function1
                   {
-                    $$ = finish_function ($2, $4, $1);
-                    recover_from_parsing_function ();
+                    $$ = curr_parser->finish_function ($2, $4, $1);
+                    curr_parser->recover_from_parsing_function ();
                   }
                 ;
 
@@ -1477,23 +1215,23 @@
                   {
                     std::string id_name = $1->name ();
 
-                    lexer_flags.parsed_function_name.top () = true;
-                    lexer_flags.maybe_classdef_get_set_method = false;
+                    curr_lexer->parsed_function_name.top () = true;
+                    curr_lexer->maybe_classdef_get_set_method = false;
 
                     $$ = $1;
                   }
                 | GET '.' identifier
                   {
-                    lexer_flags.parsed_function_name.top () = true;
-                    lexer_flags.maybe_classdef_get_set_method = false;
-                    lexer_flags.parsing_classdef_get_method = true;
+                    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
                   {
-                    lexer_flags.parsed_function_name.top () = true;
-                    lexer_flags.maybe_classdef_get_set_method = false;
-                    lexer_flags.parsing_classdef_set_method = true;
+                    curr_lexer->parsed_function_name.top () = true;
+                    curr_lexer->maybe_classdef_get_set_method = false;
+                    curr_lexer->parsing_classdef_set_method = true;
                     $$ = $3;
                   }
                 ;
@@ -1504,22 +1242,22 @@
 
                     delete $1;
 
-                    if (! ($$ = frob_function (fname, $2)))
+                    if (! ($$ = curr_parser->frob_function (fname, $2)))
                       ABORT_PARSE;
                   }
                 ;
 
 function2       : param_list opt_sep opt_list function_end
-                  { $$ = start_function ($1, $3, $4); }
+                  { $$ = curr_parser->start_function ($1, $3, $4); }
                 | opt_sep opt_list function_end
-                  { $$ = start_function (0, $2, $3); }
+                  { $$ = curr_parser->start_function (0, $2, $3); }
                 ;
 
 function_end    : END
                   {
-                    endfunction_found = true;
-                    if (end_token_ok ($1, token::function_end))
-                      $$ = make_end ("endfunction", $1->line (), $1->column ());
+                    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;
                   }
@@ -1528,13 +1266,13 @@
 // A lot of tests are based on the assumption that this is OK
 //                  if (reading_script_file)
 //                    {
-//                      yyerror ("function body open at end of script");
+//                      curr_parser->bison_error ("function body open at end of script");
 //                      YYABORT;
 //                    }
 
-                    if (endfunction_found)
+                    if (curr_parser->endfunction_found)
                       {
-                        yyerror ("inconsistent function endings -- "
+                        curr_parser->bison_error ("inconsistent function endings -- "
                                  "if one function is explicitly ended, "
                                  "so must all the others");
                         YYABORT;
@@ -1543,18 +1281,19 @@
                     if (! (reading_fcn_file || reading_script_file
                            || get_input_from_eval_string))
                       {
-                        yyerror ("function body open at end of input");
+                        curr_parser->bison_error ("function body open at end of input");
                         YYABORT;
                       }
 
                     if (reading_classdef_file)
                       {
-                        yyerror ("classdef body open at end of input");
+                        curr_parser->bison_error ("classdef body open at end of input");
                         YYABORT;
                       }
 
-                    $$ = make_end ("endfunction", input_line_number,
-                                   current_input_column);
+                    $$ = curr_parser->make_end ("endfunction",
+                                                curr_lexer->input_line_number,
+                                                curr_lexer->current_input_column);
                   }
                 ;
 
@@ -1564,7 +1303,7 @@
 
 classdef_file   : CLASSDEF_FILE classdef opt_sep END_OF_INPUT
                   {
-                    classdef_object = $2;
+                    curr_parser->classdef_object = $2;
                     $$ = 0;
                   }
                 ;
@@ -1577,19 +1316,19 @@
                   {
                     if (! reading_classdef_file)
                       {
-                        yyerror ("classdef must appear inside a file containing only a class definition");
+                        curr_parser->bison_error ("classdef must appear inside a file containing only a class definition");
                         YYABORT;
                       }
 
-                    lexer_flags.parsing_classdef = true;
+                    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
                   {
-                    lexer_flags.parsing_classdef = false;
-                    if (! ($$ = make_classdef ($1, $3, $4, $5, $7, $9, $2)))
+                    curr_lexer->parsing_classdef = false;
+                    if (! ($$ = curr_parser->make_classdef ($1, $3, $4, $5, $7, $9, $2)))
                       ABORT_PARSE;
                   }
                 ;
@@ -1613,7 +1352,7 @@
                   { $$ = new tree_classdef_attribute ($1); }
                 | identifier '=' decl_param_init expression
                   {
-                    lexer_flags.looking_at_initializer_expression = false;
+                    curr_lexer->looking_at_initializer_expression = false;
                     $$ = new tree_classdef_attribute ($1, $4);
                   }
                 | EXPR_NOT identifier
@@ -1675,7 +1414,8 @@
 properties_block
                 : PROPERTIES stash_comment opt_attr_list opt_sep property_list opt_sep END
                   {
-                    if (! ($$ = make_classdef_properties_block ($1, $3, $5, $7, $2)))
+                    if (! ($$ = curr_parser->make_classdef_properties_block
+                                               ($1, $3, $5, $7, $2)))
                       ABORT_PARSE;
                   }
                 ;
@@ -1694,14 +1434,15 @@
                   { $$ = new tree_classdef_property ($1); }
                 | identifier '=' decl_param_init expression ';'
                   {
-                    lexer_flags.looking_at_initializer_expression = false;
+                    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 (! ($$ = make_classdef_methods_block ($1, $3, $5, $7, $2)))
+                    if (! ($$ = curr_parser->make_classdef_methods_block
+                                               ($1, $3, $5, $7, $2)))
                       ABORT_PARSE;
                   }
                 ;
@@ -1728,7 +1469,8 @@
 
 events_block    : EVENTS stash_comment opt_attr_list opt_sep events_list opt_sep END
                   {
-                    if (! ($$ = make_classdef_events_block ($1, $3, $5, $7, $2)))
+                    if (! ($$ = curr_parser->make_classdef_events_block
+                                               ($1, $3, $5, $7, $2)))
                       ABORT_PARSE;
                   }
                 ;
@@ -1748,7 +1490,8 @@
 
 enum_block      : ENUMERATION stash_comment opt_attr_list opt_sep enum_list opt_sep END
                   {
-                    if (! ($$ = make_classdef_enum_block ($1, $3, $5, $7, $2)))
+                    if (! ($$ = curr_parser->make_classdef_enum_block
+                                               ($1, $3, $5, $7, $2)))
                       ABORT_PARSE;
                   }
                 ;
@@ -1775,7 +1518,7 @@
                 ;
 
 parse_error     : LEXICAL_ERROR
-                  { yyerror ("parse error"); }
+                  { curr_parser->bison_error ("parse error"); }
                 | error
                 ;
 
@@ -1825,55 +1568,25 @@
 
 // Generic error messages.
 
+#undef curr_lexer
+
 static void
-yyerror (const char *s)
+yyerror (octave_parser *curr_parser, const char *s)
 {
-  int err_col = current_input_column - 1;
-
-  std::ostringstream output_buf;
-
-  if (reading_fcn_file || reading_script_file || reading_classdef_file)
-    output_buf << "parse error near line " << 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 ());
+  curr_parser->bison_error (s);
+}
+
+int
+octave_parser::run (void)
+{
+  return octave_parse (this);
 }
 
 // Error mesages for mismatched end tokens.
 
-static void
-end_error (const char *type, token::end_tok_type ettype, int l, int c)
+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";
@@ -1924,8 +1637,8 @@
 
 // Check to see that end tokens are properly matched.
 
-static bool
-end_token_ok (token *tok, token::end_tok_type expected)
+bool
+octave_parser::end_token_ok (token *tok, token::end_tok_type expected)
 {
   bool retval = true;
 
@@ -1935,7 +1648,7 @@
     {
       retval = false;
 
-      yyerror ("parse error");
+      bison_error ("parse error");
 
       int l = tok->line ();
       int c = tok->column ();
@@ -1994,8 +1707,8 @@
 // Maybe print a warning if an assignment expression is used as the
 // test in a logical expression.
 
-static void
-maybe_warn_assign_as_truth_value (tree_expression *expr)
+void
+octave_parser::maybe_warn_assign_as_truth_value (tree_expression *expr)
 {
   if (expr->is_assignment_expression ()
       && expr->paren_count () < 2)
@@ -2014,8 +1727,8 @@
 
 // Maybe print a warning about switch labels that aren't constants.
 
-static void
-maybe_warn_variable_switch_label (tree_expression *expr)
+void
+octave_parser::maybe_warn_variable_switch_label (tree_expression *expr)
 {
   if (! expr->is_constant ())
     {
@@ -2121,8 +1834,8 @@
 
 // Finish building a range.
 
-static tree_expression *
-finish_colon_expression (tree_colon_expression *e)
+tree_expression *
+octave_parser::finish_colon_expression (tree_colon_expression *e)
 {
   tree_expression *retval = e;
 
@@ -2185,8 +1898,8 @@
 
 // Make a constant.
 
-static tree_constant *
-make_constant (int op, token *tok_val)
+tree_constant *
+octave_parser::make_constant (int op, token *tok_val)
 {
   int l = tok_val->line ();
   int c = tok_val->column ();
@@ -2248,8 +1961,8 @@
 
 // Make a function handle.
 
-static tree_fcn_handle *
-make_fcn_handle (token *tok_val)
+tree_fcn_handle *
+octave_parser::make_fcn_handle (token *tok_val)
 {
   int l = tok_val->line ();
   int c = tok_val->column ();
@@ -2261,12 +1974,13 @@
 
 // Make an anonymous function handle.
 
-static tree_anon_fcn_handle *
-make_anon_fcn_handle (tree_parameter_list *param_list, tree_statement *stmt)
+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 = input_line_number;
-  int c = current_input_column;
+  int l = curr_lexer->input_line_number;
+  int c = curr_lexer->current_input_column;
 
   tree_parameter_list *ret_list = 0;
 
@@ -2294,9 +2008,9 @@
 
 // Build a binary expression.
 
-static tree_expression *
-make_binary_op (int op, tree_expression *op1, token *tok_val,
-                tree_expression *op2)
+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;
 
@@ -2398,9 +2112,9 @@
 
 // Build a boolean expression.
 
-static tree_expression *
-make_boolean_op (int op, tree_expression *op1, token *tok_val,
-                 tree_expression *op2)
+tree_expression *
+octave_parser::make_boolean_op (int op, tree_expression *op1, token *tok_val,
+                                tree_expression *op2)
 {
   tree_boolean_expression::type t;
 
@@ -2430,8 +2144,8 @@
 
 // Build a prefix expression.
 
-static tree_expression *
-make_prefix_op (int op, tree_expression *op1, token *tok_val)
+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;
 
@@ -2473,8 +2187,8 @@
 
 // Build a postfix expression.
 
-static tree_expression *
-make_postfix_op (int op, tree_expression *op1, token *tok_val)
+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;
 
@@ -2512,10 +2226,13 @@
 
 // Build an unwind-protect command.
 
-static tree_command *
-make_unwind_command (token *unwind_tok, tree_statement_list *body,
-                     tree_statement_list *cleanup, token *end_tok,
-                     octave_comment_list *lc, octave_comment_list *mc)
+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;
 
@@ -2526,7 +2243,7 @@
       int l = unwind_tok->line ();
       int c = unwind_tok->column ();
 
-      retval = new tree_unwind_protect_command (body, cleanup,
+      retval = new tree_unwind_protect_command (body, cleanup_stmts,
                                                 lc, mc, tc, l, c);
     }
 
@@ -2535,10 +2252,12 @@
 
 // Build a try-catch command.
 
-static tree_command *
-make_try_command (token *try_tok, tree_statement_list *body,
-                  tree_statement_list *cleanup, token *end_tok,
-                  octave_comment_list *lc, octave_comment_list *mc)
+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;
 
@@ -2549,7 +2268,7 @@
       int l = try_tok->line ();
       int c = try_tok->column ();
 
-      retval = new tree_try_catch_command (body, cleanup,
+      retval = new tree_try_catch_command (body, cleanup_stmts,
                                            lc, mc, tc, l, c);
     }
 
@@ -2558,10 +2277,10 @@
 
 // Build a while command.
 
-static tree_command *
-make_while_command (token *while_tok, tree_expression *expr,
-                    tree_statement_list *body, token *end_tok,
-                    octave_comment_list *lc)
+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;
 
@@ -2571,7 +2290,7 @@
     {
       octave_comment_list *tc = octave_comment_buffer::get_comment ();
 
-      lexer_flags.looping--;
+      curr_lexer->looping--;
 
       int l = while_tok->line ();
       int c = while_tok->column ();
@@ -2584,9 +2303,11 @@
 
 // Build a do-until command.
 
-static tree_command *
-make_do_until_command (token *until_tok, tree_statement_list *body,
-                       tree_expression *expr, octave_comment_list *lc)
+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;
 
@@ -2594,7 +2315,7 @@
 
   octave_comment_list *tc = octave_comment_buffer::get_comment ();
 
-  lexer_flags.looping--;
+  curr_lexer->looping--;
 
   int l = until_tok->line ();
   int c = until_tok->column ();
@@ -2606,11 +2327,13 @@
 
 // Build a for command.
 
-static tree_command *
-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 *
+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;
 
@@ -2620,7 +2343,7 @@
     {
       octave_comment_list *tc = octave_comment_buffer::get_comment ();
 
-      lexer_flags.looping--;
+      curr_lexer->looping--;
 
       int l = for_tok->line ();
       int c = for_tok->column ();
@@ -2637,7 +2360,7 @@
       else
         {
           if (parfor)
-            yyerror ("invalid syntax for parfor statement");
+            bison_error ("invalid syntax for parfor statement");
           else
             retval = new tree_complex_for_command (lhs, expr, body,
                                                    lc, tc, l, c);
@@ -2649,8 +2372,8 @@
 
 // Build a break command.
 
-static tree_command *
-make_break_command (token *break_tok)
+tree_command *
+octave_parser::make_break_command (token *break_tok)
 {
   tree_command *retval = 0;
 
@@ -2664,8 +2387,8 @@
 
 // Build a continue command.
 
-static tree_command *
-make_continue_command (token *continue_tok)
+tree_command *
+octave_parser::make_continue_command (token *continue_tok)
 {
   tree_command *retval = 0;
 
@@ -2679,8 +2402,8 @@
 
 // Build a return command.
 
-static tree_command *
-make_return_command (token *return_tok)
+tree_command *
+octave_parser::make_return_command (token *return_tok)
 {
   tree_command *retval = 0;
 
@@ -2694,8 +2417,9 @@
 
 // Start an if command.
 
-static tree_if_command_list *
-start_if_command (tree_expression *expr, tree_statement_list *list)
+tree_if_command_list *
+octave_parser::start_if_command (tree_expression *expr,
+                                 tree_statement_list *list)
 {
   maybe_warn_assign_as_truth_value (expr);
 
@@ -2706,9 +2430,9 @@
 
 // Finish an if command.
 
-static tree_if_command *
-finish_if_command (token *if_tok, tree_if_command_list *list,
-                   token *end_tok, octave_comment_list *lc)
+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;
 
@@ -2738,9 +2462,10 @@
 
 // Build an elseif clause.
 
-static tree_if_clause *
-make_elseif_clause (token *elseif_tok, tree_expression *expr,
-                    tree_statement_list *list, octave_comment_list *lc)
+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);
 
@@ -2752,10 +2477,10 @@
 
 // Finish a switch command.
 
-static tree_switch_command *
-finish_switch_command (token *switch_tok, tree_expression *expr,
-                       tree_switch_case_list *list, token *end_tok,
-                       octave_comment_list *lc)
+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;
 
@@ -2785,9 +2510,10 @@
 
 // Build a switch case.
 
-static tree_switch_case *
-make_switch_case (token *case_tok, tree_expression *expr,
-                  tree_statement_list *list, octave_comment_list *lc)
+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);
 
@@ -2799,9 +2525,9 @@
 
 // Build an assignment to a variable.
 
-static tree_expression *
-make_assign_op (int op, tree_argument_list *lhs, token *eq_tok,
-                tree_expression *rhs)
+tree_expression *
+octave_parser::make_assign_op (int op, tree_argument_list *lhs, token *eq_tok,
+                               tree_expression *rhs)
 {
   tree_expression *retval = 0;
 
@@ -2888,15 +2614,16 @@
   else if (t == octave_value::op_asn_eq)
     return new tree_multi_assignment (lhs, rhs, false, l, c);
   else
-    yyerror ("computed multiple assignment not allowed");
+    bison_error ("computed multiple assignment not allowed");
 
   return retval;
 }
 
 // Define a script.
 
-static void
-make_script (tree_statement_list *cmds, tree_statement *end_script)
+void
+octave_parser::make_script (tree_statement_list *cmds,
+                            tree_statement *end_script)
 {
   std::string doc_string;
 
@@ -2929,9 +2656,10 @@
 
 // Begin defining a function.
 
-static octave_user_function *
-start_function (tree_parameter_list *param_list, tree_statement_list *body,
-                tree_statement *end_fcn_stmt)
+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.
 
@@ -2954,16 +2682,17 @@
   return fcn;
 }
 
-static tree_statement *
-make_end (const std::string& type, int l, int c)
+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.
 
-static octave_user_function *
-frob_function (const std::string& fname, octave_user_function *fcn)
+octave_user_function *
+octave_parser::frob_function (const std::string& fname,
+                              octave_user_function *fcn)
 {
   std::string id_name = fname;
 
@@ -2972,7 +2701,7 @@
   // file.  Matlab doesn't provide a diagnostic (it ignores the stated
   // name).
   if (! autoloading && reading_fcn_file
-      && current_function_depth == 1 && ! parsing_subfunctions)
+      && 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
@@ -3007,24 +2736,24 @@
       if (fcn_file_from_relative_lookup)
         fcn->mark_relative ();
 
-      if (current_function_depth > 1 || parsing_subfunctions)
+      if (curr_fcn_depth > 1 || parsing_subfunctions)
         {
           fcn->stash_parent_fcn_name (curr_fcn_file_name);
 
-          if (current_function_depth > 1)
+          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 (lexer_flags.parsing_class_method)
+      if (curr_lexer->parsing_class_method)
         {
-          if (current_class_name == id_name)
+          if (curr_class_name == id_name)
             fcn->mark_as_class_constructor ();
           else
             fcn->mark_as_class_method ();
 
-          fcn->stash_dispatch_class (current_class_name);
+          fcn->stash_dispatch_class (curr_class_name);
         }
 
       std::string nm = fcn->fcn_file_name ();
@@ -3044,9 +2773,10 @@
     }
 
   fcn->stash_function_name (id_name);
-  fcn->stash_fcn_location (input_line_number, current_input_column);
-
-  if (! help_buf.empty () && current_function_depth == 1
+  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 ());
@@ -3054,16 +2784,17 @@
       help_buf.pop ();
     }
 
-  if (reading_fcn_file && current_function_depth == 1
+  if (reading_fcn_file && curr_fcn_depth == 1
       && ! parsing_subfunctions)
     primary_fcn_ptr = fcn;
 
   return fcn;
 }
 
-static tree_function_def *
-finish_function (tree_parameter_list *ret_list,
-                 octave_user_function *fcn, octave_comment_list *lc)
+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;
 
@@ -3086,7 +2817,7 @@
 
       fcn->define_ret_list (ret_list);
 
-      if (current_function_depth > 1 || parsing_subfunctions)
+      if (curr_fcn_depth > 1 || parsing_subfunctions)
         {
           fcn->mark_as_subfunction ();
 
@@ -3103,10 +2834,10 @@
                                                primary_fcn_scope);
         }
 
-      if (current_function_depth == 1 && fcn)
+      if (curr_fcn_depth == 1 && fcn)
         symbol_table::update_nest (fcn->scope ());
 
-      if (! reading_fcn_file && current_function_depth == 1)
+      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
@@ -3131,38 +2862,204 @@
   return retval;
 }
 
-static void
-recover_from_parsing_function (void)
+void
+octave_parser::recover_from_parsing_function (void)
 {
   if (parser_symtab_context.empty ())
     panic_impossible ();
 
   parser_symtab_context.pop ();
 
-  if (reading_fcn_file && current_function_depth == 1
+  if (reading_fcn_file && curr_fcn_depth == 1
       && ! parsing_subfunctions)
     parsing_subfunctions = true;
 
-  current_function_depth--;
+  curr_fcn_depth--;
   function_scopes.pop_back ();
 
-  lexer_flags.defining_func--;
-  lexer_flags.parsed_function_name.pop ();
-  lexer_flags.looking_at_return_list = false;
-  lexer_flags.looking_at_parameter_list = false;
+  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.
 
-static tree_index_expression *
-make_index_expression (tree_expression *expr, tree_argument_list *args,
-                       char type)
+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 ())
     {
-      yyerror ("invalid use of empty argument (~) in index expression");
+      bison_error ("invalid use of empty argument (~) in index expression");
       return retval;
     }
 
@@ -3188,8 +3085,9 @@
 
 // Make an indirect reference expression.
 
-static tree_index_expression *
-make_indirect_ref (tree_expression *expr, const std::string& elt)
+tree_index_expression *
+octave_parser::make_indirect_ref (tree_expression *expr,
+                                  const std::string& elt)
 {
   tree_index_expression *retval = 0;
 
@@ -3210,15 +3108,15 @@
   else
     retval = new tree_index_expression (expr, elt, l, c);
 
-  lexer_flags.looking_at_indirect_ref = false;
+  curr_lexer->looking_at_indirect_ref = false;
 
   return retval;
 }
 
 // Make an indirect reference expression with dynamic field name.
 
-static tree_index_expression *
-make_indirect_ref (tree_expression *expr, tree_expression *elt)
+tree_index_expression *
+octave_parser::make_indirect_ref (tree_expression *expr, tree_expression *elt)
 {
   tree_index_expression *retval = 0;
 
@@ -3239,15 +3137,16 @@
   else
     retval = new tree_index_expression (expr, elt, l, c);
 
-  lexer_flags.looking_at_indirect_ref = false;
+  curr_lexer->looking_at_indirect_ref = false;
 
   return retval;
 }
 
 // Make a declaration command.
 
-static tree_decl_command *
-make_decl_command (int tok, token *tok_val, tree_decl_init_list *lst)
+tree_decl_command *
+octave_parser::make_decl_command (int tok, token *tok_val,
+                                  tree_decl_init_list *lst)
 {
   tree_decl_command *retval = 0;
 
@@ -3261,7 +3160,7 @@
       break;
 
     case PERSISTENT:
-      if (current_function_depth > 0)
+      if (curr_fcn_depth > 0)
         retval = new tree_persistent_command (lst, l, c);
       else
         {
@@ -3281,18 +3180,18 @@
   return retval;
 }
 
-static tree_argument_list *
-validate_matrix_row (tree_argument_list *row)
+tree_argument_list *
+octave_parser::validate_matrix_row (tree_argument_list *row)
 {
   if (row && row->has_magic_tilde ())
-    yyerror ("invalid use of tilde (~) in matrix expression");
+    bison_error ("invalid use of tilde (~) in matrix expression");
   return row;
 }
 
 // Finish building a matrix list.
 
-static tree_expression *
-finish_matrix (tree_matrix *m)
+tree_expression *
+octave_parser::finish_matrix (tree_matrix *m)
 {
   tree_expression *retval = m;
 
@@ -3335,16 +3234,16 @@
 
 // Finish building a cell list.
 
-static tree_expression *
-finish_cell (tree_cell *c)
+tree_expression *
+octave_parser::finish_cell (tree_cell *c)
 {
   return finish_matrix (c);
 }
 
-static void
-maybe_warn_missing_semi (tree_statement_list *t)
+void
+octave_parser::maybe_warn_missing_semi (tree_statement_list *t)
 {
-  if (current_function_depth > 0)
+  if (curr_fcn_depth > 0)
     {
       tree_statement *tmp = t->back ();
 
@@ -3356,9 +3255,9 @@
     }
 }
 
-static tree_statement_list *
-set_stmt_print_flag (tree_statement_list *list, char sep,
-                     bool warn_missing_semi)
+tree_statement_list *
+octave_parser::set_stmt_print_flag (tree_statement_list *list, char sep,
+                                    bool warn_missing_semi)
 {
   tree_statement *tmp = list->back ();
 
@@ -3393,15 +3292,16 @@
   return list;
 }
 
-static tree_statement_list *
-make_statement_list (tree_statement *stmt)
+tree_statement_list *
+octave_parser::make_statement_list (tree_statement *stmt)
 {
   return new tree_statement_list (stmt);
 }
 
-static tree_statement_list *
-append_statement_list (tree_statement_list *list, char sep,
-                       tree_statement *stmt, bool warn_missing_semi)
+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);
 
@@ -3410,164 +3310,50 @@
   return list;
 }
 
-static tree_funcall *
-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);
-}
-
-static tree_funcall *
-make_meta_class_query (const std::string& package_nm,
-                       const std::string& class_nm,
-                       int l, int c)
+void
+octave_parser::bison_error (const char *s)
+
 {
-  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.
-
-static tree_classdef *
-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)
+  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 ())
     {
-      yyerror ("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);
+      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 << "^";
     }
 
-  return retval;
-}
-
-static tree_classdef_properties_block *
-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;
-}
-
-static tree_classdef_methods_block *
-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;
-}
-
-static tree_classdef_events_block *
-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;
-}
-
-static tree_classdef_enum_block *
-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;
+  output_buf << "\n";
+
+  std::string msg = output_buf.str ();
+
+  parse_error ("%s", msg.c_str ());
 }
 
 static void
@@ -3619,9 +3405,6 @@
         }
     }
 
-  if (c == '\n')
-    input_line_number++;
-
   return c;
 }
 
@@ -3629,20 +3412,53 @@
 stdio_stream_reader : public stream_reader
 {
 public:
-  stdio_stream_reader (FILE *f_arg) : stream_reader (), f (f_arg) { }
-
-  int getc (void) { return ::text_getc (f); }
+
+  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')
-      input_line_number--;
+      {   
+        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&);
@@ -3661,11 +3477,7 @@
         {
         case ' ':
         case '\t':
-          current_input_column++;
-          break;
-
         case '\n':
-          current_input_column = 1;
           break;
 
         default:
@@ -3699,7 +3511,8 @@
  }
 
 static std::string
-gobble_leading_white_space (FILE *ffile, bool& eof)
+gobble_leading_white_space (FILE *ffile, bool& eof, int& line_num,
+                            int& column_num)
 {
   std::string help_txt;
 
@@ -3710,7 +3523,7 @@
 
   std::string txt;
 
-  stdio_stream_reader stdio_reader (ffile);
+  stdio_stream_reader stdio_reader (ffile, line_num, column_num);
 
   while (true)
     {
@@ -3719,7 +3532,7 @@
       if (eof)
         break;
 
-      txt = grab_comment_block (stdio_reader, true, eof);
+      txt = CURR_LEXER->grab_comment_block (stdio_reader, true, eof);
 
       if (txt.empty ())
         break;
@@ -3739,6 +3552,15 @@
   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)
 {
@@ -3760,8 +3582,8 @@
 
 static octave_function *
 parse_fcn_file (const std::string& ff, const std::string& dispatch_type,
-                bool force_script = false, bool require_file = true,
-                const std::string& warn_for = std::string ())
+                bool require_file, bool force_script, bool autoload,    
+                bool relative_lookup, const std::string& warn_for)
 {
   unwind_protect frame;
 
@@ -3775,27 +3597,11 @@
 
   frame.protect_var (ff_instream);
 
-  frame.protect_var (input_line_number);
-  frame.protect_var (current_input_column);
   frame.protect_var (reading_fcn_file);
   frame.protect_var (line_editing);
-  frame.protect_var (current_class_name);
-  frame.protect_var (current_function_depth);
-  frame.protect_var (function_scopes);
-  frame.protect_var (max_function_depth);
-  frame.protect_var (parsing_subfunctions);
-  frame.protect_var (endfunction_found);
-
-  input_line_number = 1;
-  current_input_column = 1;
+
   reading_fcn_file = true;
   line_editing = false;
-  current_class_name = dispatch_type;
-  current_function_depth = 0;
-  function_scopes.clear ();
-  max_function_depth = 0;
-  parsing_subfunctions = false;
-  endfunction_found = false;
 
   frame.add_fcn (command_history::ignore_entries,
                  command_history::ignoring_entries ());
@@ -3810,7 +3616,21 @@
     {
       bool eof;
 
-      std::string help_txt = gobble_leading_white_space (ffile, 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);
@@ -3820,15 +3640,12 @@
           std::string file_type;
 
           frame.protect_var (get_input_from_eval_string);
-          frame.protect_var (parser_end_of_input);
           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;
-          parser_end_of_input = false;
 
           if (! force_script && looking_at_function_keyword (ffile))
             {
@@ -3861,22 +3678,6 @@
               reading_script_file = true;
             }
 
-          YY_BUFFER_STATE old_buf = current_buffer ();
-          YY_BUFFER_STATE new_buf = create_buffer (ffile);
-
-          frame.add_fcn (switch_to_buffer, old_buf);
-          frame.add_fcn (delete_buffer, new_buf);
-
-          switch_to_buffer (new_buf);
-
-          frame.protect_var (primary_fcn_ptr);
-          primary_fcn_ptr = 0;
-
-          frame.protect_var (classdef_object);
-          classdef_object = 0;
-
-          reset_parser ();
-
           // Do this with an unwind-protect cleanup function so that
           // the forced variables will be unmarked in the event of an
           // interrupt.
@@ -3887,19 +3688,19 @@
             help_buf.push (help_txt);
 
           if (reading_script_file)
-            prep_lexer_for_script_file ();
+            curr_parser->curr_lexer->prep_for_script_file ();
           else if (reading_classdef_file)
-            prep_lexer_for_classdef_file ();
+            curr_parser->curr_lexer->prep_for_classdef_file ();
           else
-            prep_lexer_for_function_file ();
-
-          lexer_flags.parsing_class_method = ! dispatch_type.empty ();
+            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 = yyparse ();
+          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
@@ -3907,11 +3708,11 @@
 
           frame.add_fcn (cleanup_statement_list, &global_command);
 
-          fcn_ptr = primary_fcn_ptr;
+          fcn_ptr = curr_parser->primary_fcn_ptr;
 
           if (status == 0)
             {
-              if (reading_classdef_file && classdef_object)
+              if (reading_classdef_file && curr_parser->classdef_object)
                 {
                   // Convert parse tree for classdef object to
                   // meta.class info (and stash it in the symbol
@@ -3920,7 +3721,7 @@
                   if (fcn_ptr)
                     panic_impossible ();
 
-                  fcn_ptr = classdef_object->make_meta_class ();
+                  fcn_ptr = curr_parser->classdef_object->make_meta_class ();
                 }
             }
           else
@@ -3931,12 +3732,15 @@
         }
       else
         {
+          int l = curr_parser->curr_lexer->input_line_number;
+          int c = curr_parser->curr_lexer->current_input_column;
+
           tree_statement *end_of_script
-            = make_end ("endscript", input_line_number, current_input_column);
-
-          make_script (0, end_of_script);
-
-          fcn_ptr = primary_fcn_ptr;
+            = 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)
@@ -3971,7 +3775,9 @@
 
           if (retval.empty ())
             {
-              octave_function *fcn = parse_fcn_file (file, "");
+              octave_function *fcn = parse_fcn_file (file, "", true,
+                                                     false, false,
+                                                     false, "");
 
               if (fcn)
                 {
@@ -4049,9 +3855,7 @@
 
   std::string file;
 
-  frame.protect_var (fcn_file_from_relative_lookup);
-
-  fcn_file_from_relative_lookup = false;
+  bool relative_lookup = false;
 
   file = nm;
 
@@ -4067,13 +3871,7 @@
         nm = nm.substr (pos+1);
     }
 
-  if (autoload)
-    {
-      frame.protect_var (autoloading);
-      autoloading = true;
-    }
-
-  fcn_file_from_relative_lookup = ! octave_env::absolute_pathname (file);
+  relative_lookup = ! octave_env::absolute_pathname (file);
 
   file = octave_env::make_absolute (file);
 
@@ -4084,7 +3882,7 @@
       if (autoload && ! fcn_name.empty ())
         nm = fcn_name;
 
-      retval = octave_dynamic_loader::load_oct (nm, file, fcn_file_from_relative_lookup);
+      retval = octave_dynamic_loader::load_oct (nm, file, relative_lookup);
     }
   else if (len > 4 && file.substr (len-4, len-1) == ".mex")
     {
@@ -4097,10 +3895,11 @@
       curr_fcn_file_full_name = file.substr (0, len - 2);
 
       octave_function *tmpfcn = parse_fcn_file (file.substr (0, len - 2),
-                                                dispatch_type, autoloading,
-                                                false);
-
-      retval = octave_dynamic_loader::load_mex (nm, file, fcn_file_from_relative_lookup);
+                                                dispatch_type, false,
+                                                autoload, autoload,
+                                                relative_lookup, "");
+
+      retval = octave_dynamic_loader::load_mex (nm, file, relative_lookup);
 
       if (tmpfcn)
         retval->document (tmpfcn->doc_string ());
@@ -4116,7 +3915,8 @@
       curr_fcn_file_name = nm;
       curr_fcn_file_full_name = file;
 
-      retval = parse_fcn_file (file, dispatch_type, autoloading);
+      retval = parse_fcn_file (file, dispatch_type, true, autoload,
+                               autoload, relative_lookup, "");
     }
 
   if (retval)
@@ -4319,8 +4119,9 @@
 
   if (! error_state)
     {
-      octave_function *fcn = parse_fcn_file (file_full_name, "", true,
-                                             require_file, warn_for);
+      octave_function *fcn = parse_fcn_file (file_full_name, "",
+                                             require_file, true, false,
+                                             false, warn_for);
 
       if (! error_state)
         {
@@ -4631,50 +4432,30 @@
 
   unwind_protect frame;
 
-  frame.protect_var (input_line_number);
-  frame.protect_var (current_input_column);
+  // 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 (input_from_eval_string_pending);
-  frame.protect_var (parser_end_of_input);
   frame.protect_var (line_editing);
   frame.protect_var (current_eval_string);
-  frame.protect_var (current_function_depth);
-  frame.protect_var (function_scopes);
-  frame.protect_var (max_function_depth);
-  frame.protect_var (parsing_subfunctions);
-  frame.protect_var (endfunction_found);
   frame.protect_var (reading_fcn_file);
   frame.protect_var (reading_script_file);
   frame.protect_var (reading_classdef_file);
 
-  input_line_number = 1;
-  current_input_column = 1;
   get_input_from_eval_string = true;
-  input_from_eval_string_pending = true;
-  parser_end_of_input = false;
   line_editing = false;
-  current_function_depth = 0;
-  function_scopes.clear ();
-  max_function_depth = 0;
-  parsing_subfunctions = false;
-  endfunction_found = false;
   reading_fcn_file = false;
   reading_script_file = false;
   reading_classdef_file = false;
 
   current_eval_string = s;
 
-  YY_BUFFER_STATE old_buf = current_buffer ();
-  YY_BUFFER_STATE new_buf = create_buffer (0);
-
-  frame.add_fcn (switch_to_buffer, old_buf);
-  frame.add_fcn (delete_buffer, new_buf);
-
-  switch_to_buffer (new_buf);
-
   do
     {
-      reset_parser ();
+      curr_parser->reset ();
 
       frame.protect_var (global_command);
 
@@ -4686,7 +4467,7 @@
       symbol_table::scope_id scope = symbol_table::top_scope ();
       frame.add_fcn (symbol_table::unmark_forced_variables, scope);
 
-      parse_status = yyparse ();
+      parse_status = curr_parser->run ();
 
       tree_statement_list *command_list = global_command;
 
@@ -4748,7 +4529,7 @@
                   || tree_continue_command::continuing)
                 break;
             }
-          else if (parser_end_of_input)
+          else if (curr_parser->end_of_input)
             break;
         }
     }
--- a/libinterp/parse-tree/parse.h	Mon Feb 11 15:45:26 2013 -0500
+++ b/libinterp/parse-tree/parse.h	Thu Feb 28 02:04:24 2013 -0500
@@ -28,28 +28,61 @@
 #include <string>
 
 #include <stack>
+#include <vector>
+#include <map>
 
-extern void reset_parser (void);
-extern int octave_lex (void);
-extern int octave_parse (void);
+#include "lex.h"
+#include "symtab.h"
+#include "token.h"
 
+class octave_comment_list;
+class octave_function;
+class octave_user_function;
 class tree;
-class tree_matrix;
+class tree_anon_fcn_handle;
+class tree_argument_list;
+class tree_cell;
+class tree_classdef;
+class tree_classdef_attribute_list;
+class tree_classdef_body;
+class tree_classdef_enum_block;
+class tree_classdef_enum_list;
+class tree_classdef_events_block;
+class tree_classdef_events_list;
+class tree_classdef_methods_block;
+class tree_classdef_methods_list;
+class tree_classdef_properties_block;
+class tree_classdef_property_list;
+class tree_classdef_superclass_list;
+class tree_colon_expression;
+class tree_command;
+class tree_constant;
+class tree_decl_command;
+class tree_decl_init_list;
+class tree_expression;
+class tree_fcn_handle;
+class tree_funcall;
+class tree_function_def;
 class tree_identifier;
+class tree_if_clause;
+class tree_if_command;
+class tree_if_command_list;
+class tree_index_expression;
+class tree_matrix;
+class tree_matrix;
+class tree_parameter_list;
+class tree_statement;
 class tree_statement_list;
-class octave_function;
+class tree_statement_listtree_statement;
+class tree_switch_case;
+class tree_switch_case_list;
+class tree_switch_command;
 
 #include "oct-obj.h"
 
 // Nonzero means print parser debugging info (-d).
 extern int octave_debug;
 
-// The current input line number.
-extern int input_line_number;
-
-// The column of the current token.
-extern int current_input_column;
-
 // Buffer for help text snagged from function files.
 extern std::stack<std::string> help_buf;
 
@@ -62,10 +95,6 @@
 // TRUE means input is coming from startup file.
 extern bool input_from_startup_file;
 
-// Name of the current class when we are parsing class methods or
-// constructors.
-extern std::string current_class_name;
-
 extern OCTINTERP_API std::string
 get_help_from_file (const std::string& nm, bool& symbol_found,
                     std::string& file);
@@ -113,4 +142,320 @@
 
 extern OCTINTERP_API void cleanup_statement_list (tree_statement_list **lst);
 
+// Global access to currently active lexer.
+// FIXME -- to be removed after more parser+lexer refactoring.
+extern lexical_feedback *CURR_LEXER;
+
+class
+octave_parser
+{
+public:
+
+  octave_parser (void)
+    : end_of_input (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),
+      classdef_object (0), curr_lexer (new lexical_feedback ())
+  {
+    CURR_LEXER = curr_lexer;
+  }
+
+  ~octave_parser (void)
+  {
+    delete curr_lexer;
+  }
+
+  void reset (void)
+  {
+    curr_lexer->reset ();
+  }
+
+  int run (void);
+
+  // Error mesages for mismatched end tokens.
+  void end_error (const char *type, token::end_tok_type ettype, int l, int c);
+
+  // Check to see that end tokens are properly matched.
+  bool end_token_ok (token *tok, token::end_tok_type expected);
+
+  // Maybe print a warning if an assignment expression is used as the
+  // test in a logical expression.
+  void maybe_warn_assign_as_truth_value (tree_expression *expr);
+
+  // Maybe print a warning about switch labels that aren't constants.
+  void maybe_warn_variable_switch_label (tree_expression *expr);
+
+  // Finish building a range.
+  tree_expression *finish_colon_expression (tree_colon_expression *e);
+
+  // Build a constant.
+  tree_constant *make_constant (int op, token *tok_val);
+
+  // Build a function handle.
+  tree_fcn_handle *make_fcn_handle (token *tok_val);
+
+  // Build an anonymous function handle.
+  tree_anon_fcn_handle *
+  make_anon_fcn_handle (tree_parameter_list *param_list, tree_statement *stmt);
+
+  // Build a binary expression.
+  tree_expression *
+  make_binary_op (int op, tree_expression *op1, token *tok_val,
+                  tree_expression *op2);
+
+  // Build a boolean expression.
+  tree_expression *
+  make_boolean_op (int op, tree_expression *op1, token *tok_val,
+                   tree_expression *op2);
+
+  // Build a prefix expression.
+  tree_expression *
+  make_prefix_op (int op, tree_expression *op1, token *tok_val);
+
+  // Build a postfix expression.
+  tree_expression *
+  make_postfix_op (int op, tree_expression *op1, token *tok_val);
+
+  // Build an unwind-protect command.
+  tree_command *
+  make_unwind_command (token *unwind_tok, tree_statement_list *body,
+                       tree_statement_list *cleanup, token *end_tok,
+                       octave_comment_list *lc, octave_comment_list *mc);
+
+  // Build a try-catch command.
+  tree_command *
+  make_try_command (token *try_tok, tree_statement_list *body,
+                    tree_statement_list *cleanup, token *end_tok,
+                    octave_comment_list *lc, octave_comment_list *mc);
+
+  // Build a while command.
+  tree_command *
+  make_while_command (token *while_tok, tree_expression *expr,
+                      tree_statement_list *body, token *end_tok,
+                      octave_comment_list *lc);
+
+  // Build a do-until command.
+  tree_command *
+  make_do_until_command (token *until_tok, tree_statement_list *body,
+                         tree_expression *expr, octave_comment_list *lc);
+
+  // Build a for command.
+  tree_command *
+  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);
+
+  // Build a break command.
+  tree_command *make_break_command (token *break_tok);
+
+  // Build a continue command.
+  tree_command *make_continue_command (token *continue_tok);
+
+  // Build a return command.
+  tree_command *make_return_command (token *return_tok);
+
+  // Start an if command.
+  tree_if_command_list *
+  start_if_command (tree_expression *expr, tree_statement_list *list);
+
+  // Finish an if command.
+  tree_if_command *
+  finish_if_command (token *if_tok, tree_if_command_list *list,
+                     token *end_tok, octave_comment_list *lc);
+
+  // Build an elseif clause.
+  tree_if_clause *
+  make_elseif_clause (token *elseif_tok, tree_expression *expr,
+                      tree_statement_list *list, octave_comment_list *lc);
+
+  // Finish a switch command.
+  tree_switch_command *
+  finish_switch_command (token *switch_tok, tree_expression *expr,
+                         tree_switch_case_list *list, token *end_tok,
+                         octave_comment_list *lc);
+
+  // Build a switch case.
+  tree_switch_case *
+  make_switch_case (token *case_tok, tree_expression *expr,
+                    tree_statement_list *list, octave_comment_list *lc);
+
+  // Build an assignment to a variable.
+  tree_expression *
+  make_assign_op (int op, tree_argument_list *lhs, token *eq_tok,
+                  tree_expression *rhs);
+
+  // Define a script.
+  void make_script (tree_statement_list *cmds, tree_statement *end_script);
+
+  // Begin defining a function.
+  octave_user_function *
+  start_function (tree_parameter_list *param_list, tree_statement_list *body,
+                  tree_statement *end_function);
+
+  // Create a no-op statement for end_function.
+  tree_statement *make_end (const std::string& type, int l, int c);
+
+  // Do most of the work for defining a function.
+  octave_user_function *
+  frob_function (const std::string& fname, octave_user_function *fcn);
+
+  // Finish defining a function.
+  tree_function_def *
+  finish_function (tree_parameter_list *ret_list,
+                   octave_user_function *fcn, octave_comment_list *lc);
+
+  // Reset state after parsing function.
+  void
+  recover_from_parsing_function (void);
+
+  tree_funcall *
+  make_superclass_ref (const std::string& method_nm,
+                       const std::string& package_nm,
+                       const std::string& class_nm,
+                       int l, int c);
+
+  tree_funcall *
+  make_meta_class_query (const std::string& package_nm,
+                         const std::string& class_nm,
+                         int l, int c);
+
+  tree_classdef *
+  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_properties_block *
+  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_methods_block *
+  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_events_block *
+  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_enum_block *
+  make_classdef_enum_block (token *tok_val,
+                            tree_classdef_attribute_list *a,
+                            tree_classdef_enum_list *elist,
+                            token *end_tok, octave_comment_list *lc);
+
+  // Make an index expression.
+  tree_index_expression *
+  make_index_expression (tree_expression *expr,
+                         tree_argument_list *args, char type);
+
+  // Make an indirect reference expression.
+  tree_index_expression *
+  make_indirect_ref (tree_expression *expr, const std::string&);
+
+  // Make an indirect reference expression with dynamic field name.
+  tree_index_expression *
+  make_indirect_ref (tree_expression *expr, tree_expression *field);
+
+  // Make a declaration command.
+  tree_decl_command *
+  make_decl_command (int tok, token *tok_val, tree_decl_init_list *lst);
+
+  // Validate argument list forming a matrix or cell row.
+  tree_argument_list *validate_matrix_row (tree_argument_list *row);
+
+  // Finish building a matrix list.
+  tree_expression *finish_matrix (tree_matrix *m);
+
+  // Finish building a cell list.
+  tree_expression *finish_cell (tree_cell *c);
+
+  // Maybe print a warning.  Duh.
+  void maybe_warn_missing_semi (tree_statement_list *);
+
+  // Set the print flag for a statement based on the separator type.
+  tree_statement_list *
+  set_stmt_print_flag (tree_statement_list *, char, bool);
+
+  // Create a statement list.
+  tree_statement_list *make_statement_list (tree_statement *stmt);
+
+  // Append a statement to an existing statement list.
+  tree_statement_list *
+  append_statement_list (tree_statement_list *list, char sep,
+                         tree_statement *stmt, bool warn_missing_semi);
+
+  // 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;
+
+  // TRUE means we are in the process of autoloading a function.
+  bool autoloading;
+
+  // TRUE means the current function file was found in a relative path
+  // element.
+  bool fcn_file_from_relative_lookup;
+
+  // FALSE if we are still at the primary function. Subfunctions can
+  // only be declared inside function files.
+  bool parsing_subfunctions;
+
+  // Maximum function depth detected.  Used to determine whether
+  // we have nested functions or just implicitly ended subfunctions.
+  int max_fcn_depth;
+
+  // = 0 currently outside any function.
+  // = 1 inside the primary function or a subfunction.
+  // > 1 means we are looking at a function definition that seems to be
+  //     inside a function. Note that the function still might not be a
+  //     nested function.
+  int curr_fcn_depth;
+
+  // Scope where we install all subfunctions and nested functions. Only
+  // used while reading function files.
+  symbol_table::scope_id primary_fcn_scope;
+
+  // Name of the current class when we are parsing class methods or
+  // constructors.
+  std::string curr_class_name;
+
+  // A stack holding the nested function scopes being parsed.
+  // We don't use std::stack, because we want the clear method. Also, we
+  // must access one from the top
+  std::vector<symbol_table::scope_id> function_scopes;
+
+  // Pointer to the primary user function or user script function.
+  octave_function *primary_fcn_ptr;
+
+  // Pointer to the classdef object we just parsed, if any.
+  tree_classdef *classdef_object;
+
+  // State of the lexer.
+  lexical_feedback *curr_lexer;
+
+  // For unwind protect.
+  static void cleanup (octave_parser *parser) { delete parser; }
+
+private:
+
+  // No copying!
+
+  octave_parser (const octave_parser&);
+
+  octave_parser& operator = (const octave_parser&);
+};
+
 #endif
--- a/libinterp/parse-tree/pt-id.cc	Mon Feb 11 15:45:26 2013 -0500
+++ b/libinterp/parse-tree/pt-id.cc	Thu Feb 28 02:04:24 2013 -0500
@@ -59,7 +59,8 @@
 }
 
 octave_value_list
-tree_identifier::rvalue (int nargout)
+tree_identifier::rvalue (int nargout,
+                         const std::list<octave_lvalue> *lvalue_list)
 {
   octave_value_list retval;
 
@@ -91,7 +92,9 @@
         {
           octave_value_list tmp_args;
 
-          retval = val.do_multi_index_op (nargout, tmp_args);
+          retval = (lvalue_list
+                    ? val.do_multi_index_op (nargout, tmp_args, lvalue_list)
+                    : val.do_multi_index_op (nargout, tmp_args));
         }
       else
         {
--- a/libinterp/parse-tree/pt-id.h	Mon Feb 11 15:45:26 2013 -0500
+++ b/libinterp/parse-tree/pt-id.h	Thu Feb 28 02:04:24 2013 -0500
@@ -104,7 +104,13 @@
 
   octave_value rvalue1 (int nargout = 1);
 
-  octave_value_list rvalue (int nargout);
+  octave_value_list rvalue (int nargout)
+  {
+    return rvalue (nargout, 0);
+  }
+
+  octave_value_list rvalue (int nargout,
+                            const std::list<octave_lvalue> *lvalue_list);
 
   octave_lvalue lvalue (void);
 
--- a/libinterp/parse-tree/pt-mat.cc	Mon Feb 11 15:45:26 2013 -0500
+++ b/libinterp/parse-tree/pt-mat.cc	Thu Feb 28 02:04:24 2013 -0500
@@ -402,7 +402,7 @@
               first_elem = false;
               dv = this_elt_dv;
             }
-          else if (! dv.hvcat (this_elt_dv, 1))
+          else if ((! any_class) && (! dv.hvcat (this_elt_dv, 1)))
             {
               eval_error ("horizontal dimensions mismatch", dv, this_elt_dv);
               break;
@@ -644,7 +644,7 @@
                 dv(1) = this_elt_nc;
               dv(0) += this_elt_nr;
             }
-          else if (! dv.hvcat (this_elt_dv, 0))
+          else if ((!any_class) && (!dv.hvcat (this_elt_dv, 0)))
             {
               eval_error ("vertical dimensions mismatch", dv, this_elt_dv);
               return;
--- a/libinterp/parse-tree/token.h	Mon Feb 11 15:45:26 2013 -0500
+++ b/libinterp/parse-tree/token.h	Thu Feb 28 02:04:24 2013 -0500
@@ -25,6 +25,8 @@
 
 #include <string>
 
+#include "symtab.h"
+
 class
 token
 {
--- a/liboctave/Makefile.am	Mon Feb 11 15:45:26 2013 -0500
+++ b/liboctave/Makefile.am	Thu Feb 28 02:04:24 2013 -0500
@@ -135,5 +135,7 @@
 
 nobase_liboctavetests_DATA = $(TST_FILES)
 
-DISTCLEANFILES += $(BUILT_INCS)
+DISTCLEANFILES += \
+  $(BUILT_INCS) \
+  $(TST_FILES)
 
--- a/liboctave/cruft/mkf77def.in	Mon Feb 11 15:45:26 2013 -0500
+++ b/liboctave/cruft/mkf77def.in	Thu Feb 28 02:04:24 2013 -0500
@@ -25,19 +25,19 @@
 F77_APPEND_UNDERSCORE="@F77_APPEND_UNDERSCORE@"
 F77_APPEND_EXTRA_UNDERSCORE="@F77_APPEND_EXTRA_UNDERSCORE@"
 
-if $F77_TOLOWER; then
+if test x$F77_TOLOWER = xyes; then
   case_cmd="tolower";
 else
   case_cmd="toupper";
 fi
 
-if $F77_APPEND_UNDERSCORE; then
+if test x$F77_APPEND_UNDERSCORE = xyes; then
   uscore="_";
 else
   uscore="";
 fi
 
-if $F77_APPEND_EXTRA_UNDERSCORE; then
+if test x$F77_APPEND_EXTRA_UNDERSCORE = xyes; then
   awkcmd="$AWK '{ if (\$0 ~ /_/) extra = \"_\"; else extra = \"\"; printf (\"%s%s%s\n\", $case_cmd (\$0), \"$uscore\", extra); }'"
 else
   awkcmd="$AWK '{ printf (\"%s%s\n\", tolower (\$0), \"$uscore\"); }'"
--- a/liboctave/util/data-conv.cc	Mon Feb 11 15:45:26 2013 -0500
+++ b/liboctave/util/data-conv.cc	Thu Feb 28 02:04:24 2013 -0500
@@ -487,7 +487,8 @@
       if (len > 0) \
         { \
           OCTAVE_LOCAL_BUFFER (TYPE, ptr, len); \
-          stream.read (reinterpret_cast<char *>  (ptr), size * len); \
+          std::streamsize n_bytes = size * len; \
+          stream.read (reinterpret_cast<char *> (ptr), n_bytes); \
           if (swap) \
             swap_bytes< size > (ptr, len); \
           for (octave_idx_type i = 0; i < len; i++) \
@@ -509,7 +510,8 @@
           OCTAVE_LOCAL_BUFFER (TYPE, ptr, len); \
           for (octave_idx_type i = 0; i < len; i++) \
             ptr[i] = static_cast <TYPE> (data[i]);         \
-          stream.write (reinterpret_cast<char *> (ptr), size * len); \
+          std::streamsize n_bytes = size * len; \
+          stream.write (reinterpret_cast<char *> (ptr), n_bytes); \
         } \
     } \
   while (0)
@@ -1008,7 +1010,6 @@
     }
 }
 
-
 void
 read_doubles (std::istream& is, double *data, save_type type,
               octave_idx_type len, bool swap,
@@ -1043,7 +1044,8 @@
     case LS_FLOAT:
       {
         OCTAVE_LOCAL_BUFFER (float, ptr, len);
-        is.read (reinterpret_cast<char *> (ptr), 4 * len);
+        std::streamsize n_bytes = 4 * len;
+        is.read (reinterpret_cast<char *> (ptr), n_bytes);
         do_float_format_conversion (ptr, len, fmt);
         for (octave_idx_type i = 0; i < len; i++)
           data[i] = ptr[i];
@@ -1052,7 +1054,8 @@
 
     case LS_DOUBLE: // No conversion necessary.
       {
-        is.read (reinterpret_cast<char *> (data), 8 * len);
+        std::streamsize n_bytes = 8 * static_cast<std::streamsize> (len);
+        is.read (reinterpret_cast<char *> (data), n_bytes);
         do_double_format_conversion (data, len, fmt);
 
         for (int i = 0; i < len; i++)
@@ -1098,14 +1101,18 @@
       break;
 
     case LS_FLOAT: // No conversion necessary.
-      is.read (reinterpret_cast<char *> (data), 4 * len);
-      do_float_format_conversion (data, len, fmt);
+      {
+        std::streamsize n_bytes = 4 * len;
+        is.read (reinterpret_cast<char *> (data), n_bytes);
+        do_float_format_conversion (data, len, fmt);
+      }
       break;
 
     case LS_DOUBLE:
       {
         OCTAVE_LOCAL_BUFFER (double, ptr, len);
-        is.read (reinterpret_cast<char *> (ptr), 8 * len);
+        std::streamsize n_bytes = 8 * len;
+        is.read (reinterpret_cast<char *> (ptr), n_bytes);
         do_double_format_conversion (ptr, len, fmt);
         for (octave_idx_type i = 0; i < len; i++)
           data[i] = ptr[i];
@@ -1156,7 +1163,8 @@
       {
         char tmp_type = static_cast<char> (type);
         os.write (&tmp_type, 1);
-        os.write (reinterpret_cast <const char *> (data), 8 * len);
+        std::streamsize n_bytes = 8 * static_cast<std::streamsize> (len);
+        os.write (reinterpret_cast <const char *> (data), n_bytes);
       }
       break;
 
@@ -1201,7 +1209,8 @@
       {
         char tmp_type = static_cast<char> (type);
         os.write (&tmp_type, 1);
-        os.write (reinterpret_cast <const char *> (data), 4 * len);
+        std::streamsize n_bytes = 4 * len;
+        os.write (reinterpret_cast <const char *> (data), n_bytes);
       }
       break;
 
--- a/m4/acinclude.m4	Mon Feb 11 15:45:26 2013 -0500
+++ b/m4/acinclude.m4	Thu Feb 28 02:04:24 2013 -0500
@@ -370,10 +370,10 @@
     LDFLAGS="$m4_toupper([$1])_LDFLAGS $LDFLAGS"
     LIBS="$m4_toupper([$1])_LIBS $LIBS"
     m4_ifnblank([$6], [AC_LANG_PUSH($6)])
-    ac_octave_$1_check_for_lib=false
-    m4_ifblank([$4], [ac_octave_$1_check_for_lib=true],
-               [AC_CHECK_HEADERS([$4], [ac_octave_$1_check_for_lib=true; break])])
-    if $ac_octave_$1_check_for_lib; then
+    ac_octave_$1_check_for_lib=no
+    m4_ifblank([$4], [ac_octave_$1_check_for_lib=yes],
+               [AC_CHECK_HEADERS([$4], [ac_octave_$1_check_for_lib=yes; break])])
+    if test $ac_octave_$1_check_for_lib = yes; then
       AC_CACHE_CHECK([for $5 in $m4_toupper([$1])_LIBS],
         [octave_cv_lib_$1],
         [AC_LINK_IFELSE([AC_LANG_CALL([], [$5])],
@@ -1159,16 +1159,16 @@
 dnl readline.
 dnl
 AC_DEFUN([OCTAVE_ENABLE_READLINE], [
-  USE_READLINE=true
+  USE_READLINE=yes
   READLINE_LIBS=
   AC_ARG_ENABLE([readline],
     [AS_HELP_STRING([--disable-readline],
       [use readline library])],
     [if test "$enableval" = no; then
-       USE_READLINE=false
+       USE_READLINE=no
        warn_readline="command editing and history features require GNU Readline"
      fi])
-  if $USE_READLINE; then
+  if test $USE_READLINE = yes; then
     dnl RHEL 5 and older systems require termlib set before enabling readline
     AC_REQUIRE([OCTAVE_CHECK_LIB_TERMLIB])
     ac_octave_save_LIBS="$LIBS"
@@ -1672,15 +1672,15 @@
   AC_REQUIRE([OCTAVE_PROG_TEXI2DVI])
   AC_CHECK_PROG(TEXI2PDF, texi2pdf, texi2pdf, [])
   if test -z "$TEXI2PDF"; then
-    ac_octave_missing=true;
+    ac_octave_texi2pdf_missing=yes;
     if test -n "$TEXI2DVI"; then
       TEXI2PDF="$TEXI2DVI --pdf"
-      ac_octave_missing=false;
+      ac_octave_texi2pdf_missing=no;
     fi
   else
-    ac_octave_missing=false;
+    ac_octave_texi2pdf_missing=no;
   fi
-  if $ac_octave_missing; then
+  if test $ac_octave_texi2pdf_missing = yes; then
     TEXI2PDF='$(top_srcdir)/build-aux/missing texi2pdf'
     warn_texi2pdf="
 
--- a/scripts/io/strread.m	Mon Feb 11 15:45:26 2013 -0500
+++ b/scripts/io/strread.m	Thu Feb 28 02:04:24 2013 -0500
@@ -39,7 +39,7 @@
 ## @item %s
 ## The word is parsed as a string.
 ##
-## @itemx %f
+## @item  %f
 ## @itemx %n
 ## The word is parsed as a number and converted to double.
 ##
--- a/scripts/io/textread.m	Mon Feb 11 15:45:26 2013 -0500
+++ b/scripts/io/textread.m	Thu Feb 28 02:04:24 2013 -0500
@@ -1,4 +1,4 @@
-## Copyright (C) 2009-2012 Eric Chassande-Mottin, CNRS (France)
+## Copyright (C) 2009-2013 Eric Chassande-Mottin, CNRS (France)
 ##
 ## This file is part of Octave.
 ##
@@ -79,10 +79,22 @@
 
   ## Skip header lines if requested
   headerlines = find (strcmpi (varargin, "headerlines"), 1);
-  ## Beware of zero valued headerline, fskipl would skip to EOF
-  if (! isempty (headerlines) && (varargin{headerlines + 1} > 0))
-    fskipl (fid, varargin{headerlines + 1});
-    varargin(headerlines:headerlines+1) = [];
+  if (! isempty (headerlines))
+    ## Beware of missing or wrong headerline value
+    if (headerlines  == numel (varargin)
+       || ! isnumeric (varargin{headerlines + 1}))
+      error ("missing or illegal value for 'headerlines'" );
+    endif
+    ## Avoid conveying floats to fskipl
+    varargin{headerlines + 1} = round (varargin{headerlines + 1});
+    ## Beware of zero valued headerline, fskipl would skip to EOF
+    if (varargin{headerlines + 1} > 0)
+      fskipl (fid, varargin{headerlines + 1});
+      varargin(headerlines:headerlines+1) = [];
+      nargin = nargin - 2;
+    elseif (varargin{headerlines + 1} < 0)
+      warning ("textread: negative headerline value ignored");
+    endif
   endif
   st_pos = ftell (fid);
 
@@ -98,7 +110,7 @@
   if (! isempty (endofline))
     ## 'endofline' option set by user.
     if (! ischar (varargin{endofline + 1}));
-      error ("textread: character value required for EndOfLine");
+      error ("character value required for EndOfLine");
     endif
   else
     ## Determine EOL from file.  Search for EOL candidates in first BUFLENGTH chars
@@ -188,4 +200,6 @@
 %!error textread (1)
 %!error <arguments must be strings> textread (1, "%f")
 %!error <arguments must be strings> textread ("fname", 1)
-
+%!error <missing or illegal value for> textread (file_in_loadpath ("textread.m"), "", "headerlines")
+%!error <missing or illegal value for> textread (file_in_loadpath ("textread.m"), "", "headerlines", 'hh')
+%!error <character value required for> textread (file_in_loadpath ("textread.m"), "%s", "endofline", true)
--- a/scripts/io/textscan.m	Mon Feb 11 15:45:26 2013 -0500
+++ b/scripts/io/textscan.m	Thu Feb 28 02:04:24 2013 -0500
@@ -1,4 +1,4 @@
-## Copyright (C) 2010-2012 Ben Abbott <bpabbott@mac.com>
+## Copyright (C) 2010-2013 Ben Abbott <bpabbott@mac.com>
 ##
 ## This file is part of Octave.
 ##
@@ -167,14 +167,23 @@
     st_pos = ftell (fid);
     ## Skip header lines if requested
     headerlines = find (strcmpi (args, "headerlines"), 1);
-    ## Beware of zero valued headerline, fskipl would skip to EOF
-    if (! isempty (headerlines) && (args{headerlines + 1} > 0))
-      fskipl (fid, args{headerlines + 1});
-      args(headerlines:headerlines+1) = [];
-      st_pos = ftell (fid);
+    if (! isempty (headerlines))
+      ## Beware of missing or wrong headerline value
+      if (headerlines  == numel (args)
+         || ! isnumeric (args{headerlines + 1}))
+        error ("Missing or illegal value for 'headerlines'" );
+      endif
+      ## Avoid conveying floats to fskipl
+      args{headerlines + 1} = round (args{headerlines + 1});
+      if (args{headerlines + 1} > 0)
+        ## Beware of zero valued headerline, fskipl would skip to EOF
+        fskipl (fid, args{headerlines + 1});
+        args(headerlines:headerlines+1) = [];
+        st_pos = ftell (fid);
+      elseif (args{headerlines + 1} < 0)
+        warning ("textscan.m: negative headerline value ignored");
+      endif
     endif
-    ## Read a first file chunk. Rest follows after endofline processing
-    [str, count] = fscanf (fid, "%c", BUFLENGTH);
   endif
 
   ## Check for empty result
@@ -497,3 +506,7 @@
 %!   rh = strtrim (rh);
 %!   assert (strcmp (lh, rh));
 %! end
+
+%!error <missing or illegal value for> textread (file_in_loadpath ("textscan.m"), "", "headerlines")
+%!error <missing or illegal value for> textread (file_in_loadpath ("textscan.m"), "", "headerlines", 'hh')
+%!error <character value required for> textread (file_in_loadpath ("textscan.m"), "", "endofline", true)
--- a/scripts/plot/__gnuplot_drawnow__.m	Mon Feb 11 15:45:26 2013 -0500
+++ b/scripts/plot/__gnuplot_drawnow__.m	Thu Feb 28 02:04:24 2013 -0500
@@ -23,10 +23,10 @@
 
 ## Author: jwe
 
-function __gnuplot_drawnow__ (h, term, file, mono, debug_file)
+function __gnuplot_drawnow__ (h, term, file, mono = false, debug_file)
 
-  if (nargin < 4)
-    mono = false;
+  if (nargin < 1 || nargin > 5 || nargin == 2)
+    print_usage ();
   endif
 
   if (nargin >= 3 && nargin <= 5)
@@ -39,7 +39,7 @@
       plot_stream = __gnuplot_open_stream__ (2, h);
       gnuplot_supports_term = __gnuplot_has_terminal__ (term, plot_stream);
       if (gnuplot_supports_term)
-        enhanced = gnuplot_set_term (plot_stream (1), true, h, term, file);
+        enhanced = gnuplot_set_term (plot_stream(1), true, h, term, file);
         __go_draw_figure__ (h, plot_stream(1), enhanced, mono);
         if (nargin == 5)
           fid = fopen (debug_file, "wb");
@@ -47,7 +47,7 @@
           __go_draw_figure__ (h, fid, enhanced, mono);
         endif
       else
-        error ("__gnuplot_drawnow__: the gnuplot terminal, \"%s\", is not available",
+        error ('__gnuplot_drawnow__: the gnuplot terminal, "%s", is not available',
                gnuplot_trim_term (term));
       endif
     unwind_protect_cleanup
@@ -65,7 +65,7 @@
         fclose (fid);
       endif
     end_unwind_protect
-  elseif (nargin == 1)
+  else  # nargin == 1
     ##  Graphics terminal for display.
     plot_stream = get (h, "__plot_stream__");
     if (isempty (plot_stream))
@@ -78,13 +78,13 @@
     if (strcmp (term, "dumb"))
       ## popen2 eats stdout of gnuplot, use temporary file instead
       dumb_tmp_file = tmpnam ();
-      enhanced = gnuplot_set_term (plot_stream (1), new_stream, h, ...
+      enhanced = gnuplot_set_term (plot_stream(1), new_stream, h,
                                    term, dumb_tmp_file);
     else
-      enhanced = gnuplot_set_term (plot_stream (1), new_stream, h, term);
+      enhanced = gnuplot_set_term (plot_stream(1), new_stream, h, term);
     endif
-    __go_draw_figure__ (h, plot_stream (1), enhanced, mono);
-    fflush (plot_stream (1));
+    __go_draw_figure__ (h, plot_stream(1), enhanced, mono);
+    fflush (plot_stream(1));
     if (strcmp (term, "dumb"))
       fid = -1;
       while (fid < 0)
@@ -94,17 +94,14 @@
       ## reprint the plot on screen
       [a, count] = fscanf (fid, '%c', Inf);
       fclose (fid);
-      if (count>0)
-        if (a(1)==12)
-          ## avoid ^L at the beginning
-          a = a(2:end);
+      if (count > 0)
+        if (a(1) == 12)
+          a = a(2:end);  # avoid ^L at the beginning
         endif
         puts (a);
       endif
       unlink (dumb_tmp_file);
     endif
-  else
-    print_usage ();
   endif
 
 endfunction
@@ -117,9 +114,8 @@
     term = gnuplot_default_term (plot_stream);
     opts_str = "";
   else
-    ## Get the one word terminal id and save the remaining as options to
-    ## be passed on to gnuplot.  The terminal may respect the graphics
-    ## toolkit.
+    ## Get the one word terminal id and save the remaining as options to be
+    ## passed on to gnuplot.  The terminal may respect the graphics toolkit.
     [term, opts_str] = gnuplot_trim_term (term);
     term = lower (term);
     if (strcmp (term, "lua"))
@@ -149,7 +145,7 @@
       ## Generate gnuplot title string for plot windows.
       if (output_to_screen (term) && ! strcmp (term, "dumb"))
         fig.numbertitle = get (h, "numbertitle");
-        fig.name = strrep (get (h, "name"), "\"", "\\\"");
+        fig.name = strrep (get (h, "name"), '"', '\"');
         if (strcmp (get (h, "numbertitle"), "on"))
           title_str = sprintf ("Figure %d", h);
         else
@@ -161,11 +157,11 @@
           title_str = fig.name;
         endif
         if (! isempty (title_str))
-          title_str = sprintf ("title \"%s\"", title_str);
+          title_str = sprintf ('title "%s"', title_str);
         endif
         if (strcmp (term, "aqua"))
           ## Adjust axes-label and tick-label spacing.
-          opts_str = sprintf ("%s font \"%s,%d\"", opts_str,
+          opts_str = sprintf ('%s font "%s,%d"', opts_str,
                               get (0, "defaultaxesfontname"),
                               get (0, "defaultaxesfontsize") / 1.5);
         endif
@@ -195,8 +191,8 @@
         if (all (gnuplot_size > 0))
           terminals_with_size = {"canvas", "emf", "epslatex", "fig", ...
                                  "gif", "jpeg", "latex", "pbm", "pdf", ...
-                                 "pdfcairo", "postscript", "png", "pngcairo", ...
-                                 "pstex", "pslatex", "svg", "tikz"};
+                                 "pdfcairo", "postscript", "png", ...
+                                 "pngcairo", "pstex", "pslatex", "svg", "tikz"};
           if (__gnuplot_has_feature__ ("windows_figure_position"))
             terminals_with_size{end+1} = "windows";
           endif
@@ -207,27 +203,27 @@
             terminals_with_size{end+1} = "wxt";
           endif
           switch (term)
-          case terminals_with_size
-            size_str = sprintf ("size %.12g,%.12g", gnuplot_size);
-          case "tikz"
-            size_str = sprintf ("size %gin,%gin", gnuplot_size);
-          case "dumb"
-            new_stream = 1;
-            if (! isempty (getenv ("COLUMNS")) && ! isempty (getenv ("LINES")))
-              ## Let dumb use full text screen size (minus prompt lines).
-              n = sprintf ("%i", -2 - length (find (sprintf ("%s", PS1) == "\n")));
-              ## n = the number of times \n appears in PS1
-              size_str = ["size ", getenv("COLUMNS"), ",", getenv("LINES"), n];
-            else
-              ## Use the gnuplot default.
+            case terminals_with_size
+              size_str = sprintf ("size %.12g,%.12g", gnuplot_size);
+            case "tikz"
+              size_str = sprintf ("size %gin,%gin", gnuplot_size);
+            case "dumb"
+              new_stream = 1;
+              if (! isempty (getenv ("COLUMNS")) && ! isempty (getenv ("LINES")))
+                ## Let dumb use full text screen size (minus prompt lines).
+                n = sprintf ("%i", -2 - length (find (sprintf ("%s", PS1) == "\n")));
+                ## n = the number of times \n appears in PS1
+                size_str = ["size ", getenv("COLUMNS"), ",", getenv("LINES"), n];
+              else
+                ## Use the gnuplot default.
+                size_str = "";
+              endif
+            case {"aqua", "fig", "corel"}
+              size_str = sprintf ("size %g %g", gnuplot_size);
+            case "dxf"
               size_str = "";
-            endif
-          case {"aqua", "fig", "corel"}
-            size_str = sprintf ("size %g %g", gnuplot_size);
-          case "dxf"
-            size_str = "";
-          otherwise
-            size_str = "";
+            otherwise
+              size_str = "";
           endswitch
           if ((strncmpi (term, "x11", 3)
                && __gnuplot_has_feature__ ("x11_figure_position"))
@@ -269,34 +265,44 @@
     endif
 
     ## Set the gnuplot terminal (type, enhanced, title, options & size).
-    term_str = sprintf ("set terminal %s", term);
+    term_str = ["set terminal " term];
     if (! isempty (enh_str))
-      term_str = sprintf ("%s %s", term_str, enh_str);
+      term_str = [term_str " " enh_str];
     endif
     if (! isempty (title_str))
-      term_str = sprintf ("%s %s", term_str, title_str);
+      term_str = [term_str " " title_str];
     endif
     if (isempty (strfind (term, "corel")))
       if (! isempty (size_str) && new_stream)
         ## size_str comes after other options to permit specification of
         ## the canvas size for terminals cdr/corel.
-        term_str = sprintf ("%s %s", term_str, size_str);
+        term_str = [term_str " " size_str];
       endif
       if (nargin > 3 && ischar (opts_str))
         ## Options must go last.
-        term_str = sprintf ("%s %s", term_str, opts_str);
+        term_str = [term_str " " opts_str];
       endif
     else
       if (nargin > 3 && ischar (opts_str))
         ## Options must go last.
-        term_str = sprintf ("%s %s", term_str, opts_str);
+        term_str = [term_str " " opts_str];
       endif
       if (! isempty (size_str) && new_stream)
         ## size_str comes after other options to permit specification of
         ## the canvas size for terminals cdr/corel.
-        term_str = sprintf ("%s %s", term_str, size_str);
+        term_str = [term_str " " size_str];
       endif
     endif
+    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"})))
+        term_str = [term_str " dashed"];
+      endif
+    end
 
     ## Work around the gnuplot feature of growing the x11 window and
     ## flickering window (x11, windows, & wxt) when the mouse and
@@ -321,7 +327,9 @@
         endif
       endif
     endif
-    fprintf (plot_stream, "set termoption dashed\n")
+    if (__gnuplot_has_feature__ ("has_termoption_dashed"))
+      fprintf (plot_stream, "set termoption dashed\n")
+    endif
   else
     ## gnuplot will pick up the GNUTERM environment variable itself
     ## so no need to set the terminal type if not also setting the
@@ -331,7 +339,7 @@
 endfunction
 
 function term = gnuplot_default_term (plot_stream)
-  term = getenv ("GNUTERM");
+  term = lower (getenv ("GNUTERM"));
   ## If not specified, guess the terminal type.
   if (isempty (term) || ! __gnuplot_has_terminal__ (term, plot_stream))
     if (isguirunning () && __gnuplot_has_terminal__ ("qt", plot_stream))
@@ -350,35 +358,31 @@
 
 function [term, opts] = gnuplot_trim_term (string)
   ## Extract the terminal type and terminal options (from print.m)
-  string = deblank (string);
-  n = strfind (string, ' ');
-  if (isempty (n))
-    term = string;
-    opts = "";
-  else
-    term = string(1:(n-1));
-    opts = string((n+1):end);
+  string = strtrim (string);
+  [term, opts] = strtok (string, ' ');
+  if (! isempty (opts))
+    opts(1) = "";  # trim extra space from strtok
   endif
 endfunction
 
 function have_enhanced = gnuplot_is_enhanced_term (plot_stream, term)
-  persistent enhanced_terminals;
-  if (isempty (enhanced_terminals))
-    ## Don't include pstex, pslatex or epslatex here as the TeX commands
-    ## should not be interpreted in that case.
-    enhanced_terminals = {"aqua", "canvas", "dumb", "emf", "gif", "jpeg", ...
-                          "pdf", "pdfcairo", "pm", "png", "pngcairo", ...
-                          "postscript", "qt", "svg", "windows", "wxt", "x11"};
-  endif
+  ## Don't include pstex, pslatex or epslatex here as the TeX commands
+  ## should not be interpreted in that case.
+  persistent enhanced_terminals = {"aqua", "canvas", "dumb", "emf", "gif", ...
+                                   "jpeg", "pdf", "pdfcairo", "pm", "png", ...
+                                   "pngcairo", "postscript", "qt", "svg",  ...
+                                   "windows", "wxt", "x11"};
+
   if (nargin < 2)
     ## Determine the default gnuplot terminal.
     term = gnuplot_default_term (plot_stream);
   endif
-  have_enhanced = any (strncmp (enhanced_terminals, term, min (numel (term), 3)));
+  have_enhanced = any (strcmp (term, enhanced_terminals));
 endfunction
 
 function ret = output_to_screen (term)
-  ret = any (strcmpi ({"aqua", "dumb", "pm", "qt", "windows", "wxt", "x11"}, term));
+  ret = any (strcmpi (term, 
+                     {"aqua", "dumb", "pm", "qt", "windows", "wxt", "x11"}));
 endfunction
 
 function retval = have_non_legend_axes (h)
--- a/scripts/plot/gnuplot_binary.in	Mon Feb 11 15:45:26 2013 -0500
+++ b/scripts/plot/gnuplot_binary.in	Thu Feb 28 02:04:24 2013 -0500
@@ -22,8 +22,9 @@
 ## Query or set the name of the program invoked by the plot command
 ## when the graphics toolkit is set to "gnuplot".  Additional arguments to
 ## pass to the external plotting program may also be given.
-## The default value is @code{"gnuplot"} without additional arguments.
+## The default value is @code{"gnuplot"} with no additional arguments.
 ## @xref{Installation}.
+## @seealso{graphics_toolkit}
 ## @end deftypefn
 
 ## Author: jwe
@@ -39,23 +40,26 @@
   endif
 
   if (nargin == 1)
-    if (ischar (new_prog))
-      if (! isempty (new_prog))
-	gp_binary = new_prog;
-      else
-	error ("gnuplot_binary: value must not be empty");
-      endif
-    else
-      error ("gnuplot_binary: expecting program to be a character string");
+    if (! ischar (new_prog) || isempty (new_prog))
+      error ("gnuplot_binary: NEW_PROG must be a non-empty string");
     endif
+    gp_binary = new_prog;
   endif
 
   if (nargin > 1)
-    if (iscellstr (varargin))
-      gp_args = varargin;
-    else
-      error ("gnuplot_binary: expecting arguments to be character strings");
+    if (! iscellstr (varargin))
+      error ("gnuplot_binary: arguments must be character strings");
     endif
+    gp_args = varargin;
   endif
 
 endfunction
+
+
+%!test
+%! orig_val = gnuplot_binary ();
+%! old_val = gnuplot_binary ("X");
+%! assert (orig_val, old_val);
+%! assert (gnuplot_binary (), "X");
+%! gnuplot_binary (orig_val);
+%! assert (gnuplot_binary (), orig_val);
--- a/scripts/plot/legend.m	Mon Feb 11 15:45:26 2013 -0500
+++ b/scripts/plot/legend.m	Thu Feb 28 02:04:24 2013 -0500
@@ -87,7 +87,7 @@
 ## @item "hide"
 ##   Hide legend on the plot
 ##
-## @itemx "toggle"
+## @item "toggle"
 ##   Toggles between "hide" and "show"
 ##
 ## @item "boxon"
@@ -102,7 +102,7 @@
 ## @item "right"
 ##   Place label text to the right of the keys
 ##
-## @itemx "off"
+## @item  "off"
 ##   Delete the legend object
 ## @end table
 ##
--- a/scripts/plot/newplot.m	Mon Feb 11 15:45:26 2013 -0500
+++ b/scripts/plot/newplot.m	Thu Feb 28 02:04:24 2013 -0500
@@ -17,13 +17,17 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} newplot ()
+## @deftypefn  {Function File} {} newplot ()
+## @deftypefnx {Function File} {@var{h} =} newplot ()
 ## Prepare graphics engine to produce a new plot.  This function is
 ## called at the beginning of all high-level plotting functions.
 ## It is not normally required in user programs.
+##
+## The optional return value @var{h} is a graphics handle to the created
+## axes (not figure).
 ## @end deftypefn
 
-function newplot ()
+function h = newplot ()
 
   if (nargin == 0)
     cf = gcf ();
@@ -59,6 +63,9 @@
       otherwise
         error ("newplot: unrecognized nextplot property for current axes");
     endswitch
+    if (nargout > 0)
+      h = ca;
+    endif
   else
     print_usage ();
   endif
@@ -70,7 +77,8 @@
 %! hf = figure ("visible", "off");
 %! unwind_protect
 %!   p = plot ([0, 1]);
-%!   newplot;
+%!   ha = newplot ();
+%!   assert (ha, gca);
 %!   assert (isempty (get (gca, "children")));
 %! unwind_protect_cleanup
 %!   close (hf);
--- a/scripts/plot/plotmatrix.m	Mon Feb 11 15:45:26 2013 -0500
+++ b/scripts/plot/plotmatrix.m	Thu Feb 28 02:04:24 2013 -0500
@@ -164,9 +164,9 @@
   border = [0.130, 0.110, 0.225, 0.185] .* [xsize, ysize, xsize, ysize];
   border(3:4) = - border(3:4) - border(1:2);
 
-  for i = 1 : n
-    for j = 1 : m
-      pos = [xsize * (j - 1) + xoff, ysize * (n - i) + yoff, xsize, ysize];
+  for i = 1 : m
+    for j = 1 : n
+      pos = [xsize * (i - 1) + xoff, ysize * (n - j) + yoff, xsize, ysize];
       tmp = axes ("outerposition", pos, "position", pos + border,
                   "parent", parent);
       if (i == j && have_hist)
--- a/scripts/plot/print.m	Mon Feb 11 15:45:26 2013 -0500
+++ b/scripts/plot/print.m	Thu Feb 28 02:04:24 2013 -0500
@@ -207,11 +207,10 @@
 ## is sent to a file the size is determined by the plot box defined by
 ## the figure's "paperposition" property.
 ##
-## @itemx -append
-##   Append Postscript or PDF output to a pre-existing file of the
-## same type.
+## @item -append
+##   Append Postscript or PDF output to a pre-existing file of the same type.
 ##
-## @itemx -r@var{NUM}
+## @item -r@var{NUM}
 ##   Resolution of bitmaps in pixels per inch.  For both metafiles and
 ## SVG the default is the screen resolution; for other formats it is 150 dpi.
 ## To specify screen resolution, use "-r0".
--- a/scripts/plot/private/__gnuplot_get_var__.m	Mon Feb 11 15:45:26 2013 -0500
+++ b/scripts/plot/private/__gnuplot_get_var__.m	Thu Feb 28 02:04:24 2013 -0500
@@ -24,17 +24,11 @@
 ## Author: Ben Abbott <bpabbott@mac.com>
 ## Created: 2009-02-07
 
-function gp_var_value = __gnuplot_get_var__ (h, gp_var_name, fmt)
+function gp_var_value = __gnuplot_get_var__ (h, gp_var_name, fmt = "")
 
-  if (nargin == 0)
-    h = gcf ();
-  endif
   if (nargin < 2)
     print_usage ();
   endif
-  if (nargin < 3)
-    fmt = '';
-  endif
 
   if (numel (h) == 1 && isfigure (h))
     if (isempty (get (gcf, "__plot_stream__")))
@@ -65,8 +59,8 @@
     ## Mode: 6*8*8 ==  0600
     [err, msg] = mkfifo (gpin_name, 6*8*8);
 
-    if (err != 0)
-      error ("__gnuplot_get_var__: Can not make fifo (%s)", msg);
+    if (err)
+      error ("__gnuplot_get_var__: Can not make FIFO (%s)", msg);
     endif
   endif
 
@@ -79,18 +73,18 @@
   unwind_protect
 
     ## Notes: Variables may be undefined if user closes gnuplot by "q"
-    ## or Alt-F4. Further, this abrupt close also requires the leading
+    ## or Alt-F4.  Further, this abrupt close also requires the leading
     ## "\n" on the next line.
     if (use_mkfifo)
       fprintf (ostream, "\nset print \"%s\";\n", gpin_name);
       fflush (ostream);
       [gpin, err] = fopen (gpin_name, "r");
-      if (err != 0)
+      if (err)
         ## Try a second time, and then give an error.
         [gpin, err] = fopen (gpin_name, "r");
       endif
-      if (err != 0)
-        error ("__gnuplot_get_var__: can not open fifo");
+      if (err)
+        error ("__gnuplot_get_var__: can not open FIFO");
       endif
       gp_cmd = sprintf ("\nif (exists(\"%s\")) print %s; else print NaN\n",
                         gp_var_name(1:n), gp_var_name);
@@ -126,7 +120,7 @@
 
       str = {};
       while (isempty (str))
-        str = char (fread (istream)');
+        str = fread (istream, "*char")';
         if (isempty (str))
           sleep (0.05);
         else
@@ -138,8 +132,7 @@
     endif
 
     ## Strip out EOLs and the continuation character "|"
-    str(str=="\n") = "";
-    str(str=="\r") = "";
+    str(str=="\n" | str=="\r") = "";
     n_continue = strfind (str, " \\ ");
     if (! isempty (n_continue))
       str(n_continue+1) = "";
--- a/scripts/plot/private/__gnuplot_ginput__.m	Mon Feb 11 15:45:26 2013 -0500
+++ b/scripts/plot/private/__gnuplot_ginput__.m	Thu Feb 28 02:04:24 2013 -0500
@@ -31,6 +31,10 @@
 
 function [x, y, button] = __gnuplot_ginput__ (f, n)
 
+  if (compare_versions (__gnuplot_version__ (), "4.0", "<="))
+    error ("ginput: version %s of gnuplot not supported", gnuplot_version ());
+  endif
+
   ostream = get (f, "__plot_stream__");
   if (numel (ostream) < 1)
     error ("ginput: stream to gnuplot not open");
@@ -46,10 +50,6 @@
     ostream = ostream(1);
   endif
 
-  if (compare_versions (__gnuplot_version__ (), "4.0", "<="))
-    error ("ginput: version %s of gnuplot not supported", gnuplot_version ());
-  endif
-
   if (nargin == 1)
     x = zeros (100, 1);
     y = zeros (100, 1);
@@ -66,7 +66,7 @@
     ##Mode: 6*8*8 ==  0600
     [err, msg] = mkfifo (gpin_name, 6*8*8);
 
-    if (err != 0)
+    if (err)
       error ("ginput: Can not open fifo (%s)", msg);
     endif
   endif
@@ -84,8 +84,8 @@
         fprintf (ostream, "set print \"%s\";\n", gpin_name);
         fflush (ostream);
         [gpin, err] = fopen (gpin_name, "r");
-        if (err != 0)
-          error ("ginput: Can not open fifo (%s)", msg);
+        if (err)
+          error ("ginput: Can not open FIFO (%s)", msg);
         endif
         fputs (ostream, "pause mouse any;\n\n");
         fputs (ostream, "\nif (exists(\"MOUSE_KEY\") && exists(\"MOUSE_X\")) print MOUSE_X, MOUSE_Y, MOUSE_KEY; else print \"0 0 -1\"\n");
@@ -98,7 +98,7 @@
         [x(k), y(k), button(k), count] = fscanf (gpin, "%f %f %d", "C");
         fclose (gpin);
       else
-        fprintf (ostream, "set print \"-\";\n");
+        fputs (ostream, "set print \"-\";\n");
         fflush (ostream);
         fputs (ostream, "pause mouse any;\n\n");
         fputs (ostream, "\nif (exists(\"MOUSE_KEY\") && exists(\"MOUSE_X\")) print \"OCTAVE: \", MOUSE_X, MOUSE_Y, MOUSE_KEY; else print \"0 0 -1\"\n");
@@ -109,7 +109,7 @@
 
         str = {};
         while (isempty (str))
-          str = char (fread (istream)');
+          str = fread (istream, "*char")';
           if (isempty (str))
             sleep (0.05);
           else
--- a/scripts/plot/private/__gnuplot_has_feature__.m	Mon Feb 11 15:45:26 2013 -0500
+++ b/scripts/plot/private/__gnuplot_has_feature__.m	Thu Feb 28 02:04:24 2013 -0500
@@ -25,17 +25,18 @@
 ## Created: 2009-01-27
 
 function res = __gnuplot_has_feature__ (feature)
-  persistent features has_features
-  features = {"x11_figure_position",
-              "wxt_figure_size",
-              "transparent_patches",
-              "transparent_surface",
-              "epslatex_implies_eps_filesuffix",
-              "epslatexstandalone_terminal",
-              "screen_coordinates_for_{lrtb}margin",
-              "variable_GPVAL_TERMINALS",
-              "key_has_font_properties",
-              "windows_figure_position"};
+  persistent features = {"x11_figure_position",
+                         "wxt_figure_size",
+                         "transparent_patches",
+                         "transparent_surface",
+                         "epslatex_implies_eps_filesuffix",
+                         "epslatexstandalone_terminal",
+                         "screen_coordinates_for_{lrtb}margin",
+                         "variable_GPVAL_TERMINALS",
+                         "key_has_font_properties",
+                         "windows_figure_position",
+                         "has_termoption_dashed"};
+  persistent has_features;
 
   if (isempty (has_features))
     try
@@ -44,9 +45,9 @@
       ## Don't throw an error if gnuplot isn't installed
       gnuplot_version = "0.0.0";
     end_try_catch
-    versions = {"4.2.5", "4.4", "4.4", "4.4", "4.2", "4.2", "4.4", "4.4", "4.4", "4.4"};
-    operators = {">=", ">=", ">=", ">=", ">=", ">=", ">=", ">=", ">=", ">="};
-    have_features = logical (zeros (size (features)));
+    versions = {"4.2.5", "4.4", "4.4", "4.4", "4.2", "4.2", "4.4", "4.4", "4.4", "4.4", "4.3"};
+    operators = {">=", ">=", ">=", ">=", ">=", ">=", ">=", ">=", ">=", ">=", ">="};
+    have_features = false (size (features));
     for n = 1 : numel (have_features)
       has_features(n) = compare_versions (gnuplot_version, versions{n}, operators{n});
     endfor
@@ -58,5 +59,6 @@
   else
     res = has_features(n);
   endif
+
 endfunction
 
--- a/scripts/plot/private/__gnuplot_has_terminal__.m	Mon Feb 11 15:45:26 2013 -0500
+++ b/scripts/plot/private/__gnuplot_has_terminal__.m	Thu Feb 28 02:04:24 2013 -0500
@@ -25,11 +25,10 @@
 ## Created: 2010-09-13
 
 function gnuplot_supports_term = __gnuplot_has_terminal__ (term, plot_stream)
-  term = deblank (term);
-  n = find (term == " ", 1);
-  if (! isempty (n))
-    term = term(1:n-1);
-  endif
+
+  term = strtrim (term);
+  term = lower (strtok (term, " "));
+
   if (__gnuplot_has_feature__ ("variable_GPVAL_TERMINALS"))
     if (nargin < 2)
       plot_stream = __gnuplot_open_stream__ (2);
@@ -59,6 +58,8 @@
                            "svg", "texdraw", "tgif", "tkcanvas", ...
                            "tpic", "windows", "x11", "xlib", "xterm"};
   endif
-  gnuplot_supports_term = any (strcmpi (available_terminals, term));
+
+  gnuplot_supports_term = any (strcmp (term, available_terminals));
+
 endfunction
 
--- a/scripts/plot/private/__gnuplot_print__.m	Mon Feb 11 15:45:26 2013 -0500
+++ b/scripts/plot/private/__gnuplot_print__.m	Thu Feb 28 02:04:24 2013 -0500
@@ -51,15 +51,15 @@
   switch (lower (opts.devopt))
   case {"eps", "eps2", "epsc", "epsc2"}
     if (any (strcmp (opts.devopt, {"eps", "epsc"})))
-      gp_opts = sprintf ("%s level1", gp_opts);
+      gp_opts = [gp_opts " level1"];
     endif
     if (opts.tight_flag || ! isempty (opts.preview))
       tmp_file = strcat (tmpnam (), ".eps");
       eps_drawnow (opts, tmp_file, gp_opts);
       if (dos_shell)
-        cleanup = sprintf (" & del %s", strrep (tmp_file, '/', '\'));
+        cleanup = [" & del " strrep(tmp_file, '/', '\')];
       else
-        cleanup = sprintf (" ; rm %s", tmp_file);
+        cleanup = [" ; rm " tmp_file];
       endif
       pipeline = {sprintf("%s %s",
                           opts.epstool_cmd (opts, tmp_file, opts.name),
@@ -89,33 +89,33 @@
     if (__gnuplot_has_feature__ ("epslatex_implies_eps_filesuffix"))
       suffix = "tex";
     else
-      %% Gnuplot 4.0 wants a ".eps" suffix.
+      ## Gnuplot 4.0 wants a ".eps" suffix.
       suffix = "eps";
     endif
-    local_drawnow (sprintf ("%s %s", term, gp_opts),
+    local_drawnow ([term " " gp_opts],
                    strcat (name, ".", suffix), opts);
   case "tikz"
     if (__gnuplot_has_terminal__ ("tikz"))
-      local_drawnow (sprintf ("lua tikz %s", gp_opts), opts.name, opts);
+      local_drawnow (["lua tikz " gp_opts], opts.name, opts);
     else
       error (sprintf ("print:no%soutput", opts.devopt),
              "print.m: '%s' output is not available for gnuplot-%s",
              upper (opts.devopt), __gnuplot_version__ ());
     endif
   case "svg"
-    local_drawnow (sprintf ("svg dynamic %s", gp_opts), opts.name, opts);
+    local_drawnow (["svg dynamic " gp_opts], opts.name, opts);
   case {"aifm", "corel", "eepic", "emf", "fig"}
-    local_drawnow (sprintf ("%s %s", opts.devopt, gp_opts), opts.name, opts);
+    local_drawnow ([opts.devopt " " gp_opts], opts.name, opts);
   case {"pdfcairo", "pngcairo"}
     if (__gnuplot_has_terminal__ (opts.devopt))
-      local_drawnow (sprintf ("%s %s", opts.devopt, gp_opts), opts.name, opts);
+      local_drawnow ([opts.devopt " " gp_opts], opts.name, opts);
     else
       error (sprintf ("print:no%soutput", opts.devopt),
              "print.m: '%s' output is not available for gnuplot-%s",
              upper (opts.devopt), __gnuplot_version__ ());
     endif
   case {"canvas", "dxf", "hpgl", "mf", "gif", "pstricks", "texdraw"}
-    local_drawnow (sprintf ("%s %s", opts.devopt, gp_opts), opts.name, opts);
+    local_drawnow ([opts.devopt " " gp_opts], opts.name, opts);
   case opts.ghostscript.device
     gp_opts = font_spec (opts, "devopt", "eps");
     opts.ghostscript.output = opts.name;
@@ -124,9 +124,9 @@
     [cmd_gs, cmd_cleanup] = __ghostscript__ (opts.ghostscript);
     if (opts.send_to_printer || isempty (opts.name))
       cmd_lpr = opts.lpr_cmd (opts);
-      cmd = sprintf ("%s | %s", cmd_gs, cmd_lpr);
+      cmd = [cmd_gs " | " cmd_lpr];
     else
-      cmd = sprintf ("%s", cmd_gs);
+      cmd = cmd_gs;
     endif
     if (dos_shell)
       cmd = sprintf ("%s & del %s", cmd, strrep (opts.ghostscript.source, '/', '\'));
@@ -135,9 +135,9 @@
     endif
     if (! isempty (cmd_cleanup))
       if (dos_shell)
-        pipeline = {sprintf("%s & %s", cmd, cmd_cleanup)};
+        pipeline = {[cmd " & " cmd_cleanup]};
       else
-        pipeline = {sprintf("%s ; %s", cmd, cmd_cleanup)};
+        pipeline = {[cmd " ; " cmd_cleanup]};
       endif
     else
       pipeline = {cmd};
@@ -170,14 +170,11 @@
 function eps_drawnow (opts, epsfile, gp_opts)
   [h, fontsize] = get_figure_text_objs (opts);
   unwind_protect
-    for n = 1:numel (h)
-      set (h(n), "fontsize", 2 * fontsize{n});
-    endfor
-    local_drawnow (sprintf ("postscript eps %s", gp_opts), epsfile, opts);
+    fontsize_2x = cellfun (@(x) 2*x, fontsize, "uniformoutput", false);
+    set (h, {"fontsize"}, fontsize_2x);
+    local_drawnow (["postscript eps " gp_opts], epsfile, opts);
   unwind_protect_cleanup
-    for n = 1:numel (h)
-      set (h(n), "fontsize", fontsize{n});
-    endfor
+    set (h, {"fontsize"}, fontsize);
   end_unwind_protect
 endfunction
 
@@ -203,9 +200,9 @@
   switch (opts.devopt)
   case "cgm"
     if (! isempty (opts.font) && ! isempty (opts.fontsize))
-      f = sprintf ("font ""%s,%d""", opts.font, opts.fontsize);
+      f = sprintf ('font "%s,%d"', opts.font, opts.fontsize);
     elseif (! isempty (opts.font))
-      f = sprintf ("font ""%s""", opts.font);
+      f = sprintf ('font "%s"', opts.font);
     elseif (! isempty (opts.fontsize))
       f = sprintf ("%d", opts.fontsize);
     endif
@@ -215,39 +212,39 @@
     ## Compensate for the half scale. This will produce the proper
     ## spacing for the requested fontsize.
     if (! isempty (opts.font) && ! isempty (opts.fontsize))
-      f = sprintf ("font ""%s,%d""", opts.font, 2 * opts.fontsize);
+      f = sprintf ('font "%s,%d"', opts.font, 2 * opts.fontsize);
     elseif (! isempty (opts.font))
-      f = sprintf ("font ""%s""", opts.font);
+      f = sprintf ('font "%s"', opts.font);
     elseif (! isempty (opts.fontsize))
       f = sprintf ("%d", 2 * opts.fontsize);
     endif
   case "svg"
     if (! isempty (opts.font) && ! isempty (opts.fontsize))
       fontsize = round (opts.fontsize * 0.75);
-      f = sprintf ("fname ""%s"" fsize %d", opts.font, fontsize);
+      f = sprintf ('fname "%s" fsize %d', opts.font, fontsize);
     elseif (! isempty (opts.font))
-      f = sprintf ("fname ""%s""", opts.font);
+      f = sprintf ('fname "%s"', opts.font);
     elseif (! isempty (opts.fontsize))
       fontsize = round (opts.fontsize * 0.75);
       f = sprintf ("%s fsize %d", f, fontsize);
     endif
   case "pdf"
     if (! isempty (opts.font) && ! isempty (opts.fontsize))
-      f = sprintf ("font ""%s,%d""", opts.font, opts.fontsize);
+      f = sprintf ('font "%s,%d"', opts.font, opts.fontsize);
     elseif (! isempty (opts.font))
-      f = sprintf ("font ""%s""", opts.font);
+      f = sprintf ('font "%s"', opts.font);
     elseif (! isempty (opts.fontsize))
       f = sprintf ("fsize %d", f, opts.fontsize);
     endif
   case {"pdfcairo", "pngcairo"}
     if (! isempty (opts.font))
-      f = sprintf ("font ""%s""", opts.font);
+      f = sprintf ('font "%s"', opts.font);
     endif
   case {"epslatex", "epslatexstandalone"}
     if (! isempty (opts.font) && ! isempty (opts.fontsize))
-      f = sprintf ("font ""%s,%d""", opts.font, opts.fontsize);
+      f = sprintf ('font "%s,%d"', opts.font, opts.fontsize);
     elseif (! isempty (opts.font))
-      f = sprintf ("font ""%s""", opts.font);
+      f = sprintf ('font "%s"', opts.font);
     elseif (! isempty (opts.fontsize))
       f = sprintf ("%d", opts.fontsize);
     endif
@@ -257,17 +254,17 @@
     endif
   case {"gif", "jpeg", "png"}
     if (! isempty (opts.font) && ! isempty (opts.fontsize))
-      f = sprintf ("font ""%s ,%d""", opts.font, opts.fontsize);
+      f = sprintf ('font "%s ,%d"', opts.font, opts.fontsize);
     elseif (! isempty (opts.font))
-      f = sprintf ("font ""%s""", opts.font);
+      f = sprintf ('font "%s"', opts.font);
     elseif (! isempty (opts.fontsize))
-      f = sprintf ("font ""%d""", opts.fontsize);
+      f = sprintf ('font "%d"', opts.fontsize);
     endif
   case "emf"
     if (! isempty (opts.font) && ! isempty (opts.fontsize))
-      f = sprintf ("""%s"" %d", opts.font, opts.fontsize);
+      f = sprintf ('"%s" %d', opts.font, opts.fontsize);
     elseif (! isempty (opts.font))
-      f = sprintf ("""%s""", opts.font);
+      f = sprintf ('"%s"', opts.font);
     elseif (! isempty (opts.fontsize))
       f = sprintf ("%d", opts.fontsize);
     endif
--- a/scripts/plot/private/__gnuplot_version__.m	Mon Feb 11 15:45:26 2013 -0500
+++ b/scripts/plot/private/__gnuplot_version__.m	Thu Feb 28 02:04:24 2013 -0500
@@ -30,12 +30,12 @@
   persistent __version__ = "";
 
   if (isempty (__version__))
-    [status, output] = system (sprintf ("\"%s\" --version", gnuplot_binary ()));
+    [status, output] = system (sprintf ('"%s" --version', gnuplot_binary ()));
     if (status != 0)
       ## This message ends in a newline so that the traceback messages
       ## are skipped and people might actually see the message, read it,
-      ## comprehend it, actually take the advice it gives, and stop
-      ## asking us why plotting fails when gnuplot is not found.
+      ## comprehend it, take the advice it gives, and stop asking us
+      ## why plotting fails when gnuplot is not found.
       error ("you must have gnuplot installed to display graphics; if you have gnuplot installed in a non-standard location, see the 'gnuplot_binary' function\n");
     endif
     output = strrep (output, "gnuplot", "");
--- a/scripts/plot/stemleaf.m	Mon Feb 11 15:45:26 2013 -0500
+++ b/scripts/plot/stemleaf.m	Thu Feb 28 02:04:24 2013 -0500
@@ -203,7 +203,7 @@
 
     ## stems -+ 0 have to be handled as special cases.
     for xi = 1:nx
-      if(signbit(stems(kx)) == 1)
+      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)));
--- a/scripts/statistics/distributions/binopdf.m	Mon Feb 11 15:45:26 2013 -0500
+++ b/scripts/statistics/distributions/binopdf.m	Thu Feb 28 02:04:24 2013 -0500
@@ -64,6 +64,12 @@
                   + x(k).*log (p(k)) + (n(k)-x(k)).*log (1-p(k)));
   endif
 
+  ## Special case inputs
+  ksp = k & (p == 0) & (x == 0);
+  pdf(ksp) = 1; 
+  ksp = k & (p == 1) & (x == n);
+  pdf(ksp) = 1; 
+
 endfunction
 
 
@@ -82,6 +88,11 @@
 %!assert (binopdf (x, 2, 0.5*[0 -1 NaN 3 1]), [0 NaN NaN NaN 0])
 %!assert (binopdf ([x, NaN], 2, 0.5), [y, NaN], tol)
 
+## Test Special input values
+%!assert (binopdf (0, 3, 0), 1);
+%!assert (binopdf (2, 2, 1), 1);
+%!assert (binopdf (1, 2, 1), 0);
+
 %% Test class of input preserved
 %!assert (binopdf (single ([x, NaN]), 2, 0.5), single ([y, NaN]))
 %!assert (binopdf ([x, NaN], single (2), 0.5), single ([y, NaN]))
--- a/scripts/time/datetick.m	Mon Feb 11 15:45:26 2013 -0500
+++ b/scripts/time/datetick.m	Thu Feb 28 02:04:24 2013 -0500
@@ -22,13 +22,12 @@
 ## @deftypefnx {Function File} {} datetick (@var{axis}, @var{form})
 ## @deftypefnx {Function File} {} datetick (@dots{}, "keeplimits")
 ## @deftypefnx {Function File} {} datetick (@dots{}, "keepticks")
-## @deftypefnx {Function File} {} datetick (@dots{ax}, @dots{})
-## Add date formatted tick labels to an axis.  The axis the apply the
-## ticks to is determined by @var{axis} that can take the values "x",
-## "y" or "z".  The default value is "x".  The formatting of the labels is
-## determined by the variable @var{form}, that can either be a string in
-## the format needed by @code{dateform}, or a positive integer that can
-## be accepted by @code{datestr}.
+## @deftypefnx {Function File} {} datetick (@var{hax}, @dots{})
+## Add date formatted tick labels to an axis.  The axis to apply the
+## ticks to is determined by @var{axis} which can take the values "x",
+## "y", or "z".  The default value is "x".  The formatting of the labels is
+## determined by the variable @var{form}, which can either be a string or
+## positive integer that @code{datestr} accepts.
 ## @seealso{datenum, datestr}
 ## @end deftypefn
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/classes/@CPrecedenceTester1/CPrecedenceTester1.m	Thu Feb 28 02:04:24 2013 -0500
@@ -0,0 +1,8 @@
+function x = CPrecedenceTester1()
+
+  x = struct('useless_data', pi);
+  x = class(x, 'CPrecedenceTester1');
+
+  % don't change anything as far as precedence is concerned
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/classes/@CPrecedenceTester1/tattack.m	Thu Feb 28 02:04:24 2013 -0500
@@ -0,0 +1,5 @@
+function s = tattack(x, y)
+  
+  s = 'CPrecedenceTester1';
+  
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/classes/@CPrecedenceTester2/CPrecedenceTester2.m	Thu Feb 28 02:04:24 2013 -0500
@@ -0,0 +1,15 @@
+function x = CPrecedenceTester2(flag)
+
+  x = struct('useless_data', pi^2);
+  x = class(x, 'CPrecedenceTester2');
+
+  switch flag,
+    case 1, % CPrecedencetester2 > Snork
+      superiorto('Snork');
+    case 2, % CPrecedencetester2 < Snork
+      inferiorto('Snork');
+    otherwise,
+      error('Incorrect value for argument flag: %d', flag);
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/classes/@CPrecedenceTester2/tattack.m	Thu Feb 28 02:04:24 2013 -0500
@@ -0,0 +1,5 @@
+function s = tattack(x, y)
+  
+  s = 'CPrecedenceTester2';
+  
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/classes/@CPrecedenceTester3/CPrecedenceTester3.m	Thu Feb 28 02:04:24 2013 -0500
@@ -0,0 +1,15 @@
+function x = CPrecedenceTester3(flag)
+
+  x = struct('useless_data', pi^3);
+  x = class(x, 'CPrecedenceTester3');
+
+  switch flag,
+    case 1, % CPrecedencetester3 > Snork
+      superiorto('Snork');
+    case 2, % CPrecedencetester3 < Snork
+      inferiorto('Snork');
+    otherwise,
+      error('Incorrect value for argument flag: %d', flag);
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/classes/@CPrecedenceTester3/tattack.m	Thu Feb 28 02:04:24 2013 -0500
@@ -0,0 +1,5 @@
+function s = tattack(x, y)
+  
+  s = 'CPrecedenceTester3';
+  
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/classes/@Snork/tattack.m	Thu Feb 28 02:04:24 2013 -0500
@@ -0,0 +1,5 @@
+function s = tattack(x, y)
+  
+  s = 'Snork';
+  
+end
--- a/test/classes/classes.tst	Mon Feb 11 15:45:26 2013 -0500
+++ b/test/classes/classes.tst	Thu Feb 28 02:04:24 2013 -0500
@@ -304,6 +304,10 @@
 %!assert (s1 >= (x1 - 1))
 %!assert (x1 >= (s1 - 1))
 
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Testing horizontal & vertical concatenation %%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
 %% Test overloaded vertcat() for the Snork class
 %% See bug #38170 (http://savannah.gnu.org/bugs/?38170)
 %!test   s = [s1; s2];  assert (isa (s, 'Snork') && isequal (s.gick, [x1; x2]));
@@ -316,3 +320,43 @@
 %!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 with the Blork class, where neither vertcat() nor horzcat() is overloaded
+%!shared x1, x2, x3
+%!test x1 = Blork();
+%!test x2 = [x1 x1];
+%!assert (isa (x2, 'Blork') && isequal (size (x2), [1 2]));
+%!test x2 = [x1 51];
+%!assert (isa (x2, 'Blork') && isequal (size (x2), [1 2]));
+%!test x3 = [x2; x2];
+%!assert (isa (x3, 'Blork') && isequal (size (x3), [2 2]));
+%!test x3 = [x2; [51 x1]];
+%!assert (isa (x3, 'Blork') && isequal (size (x3), [2 2]));
+%!error <dimension mismatch> x4 = [x1  x3];
+%!error <dimension mismatch> x4 = [x1; x3];
+
+%%%%%%%%%%%%%%%%%%%%%%%%
+%% Testing precedence %%
+%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% default: leftmost object wins
+%!shared A, B
+%!test A = Snork(rand(2));
+%!test B = CPrecedenceTester1();  % no call to inferiorto/superiorto
+%!assert (isequal (tattack (A, B), 'Snork'))
+%!assert (isequal (tattack (B, A), 'CPrecedenceTester1'))  % idem
+
+%!shared A, B
+%!test A = Snork(rand(2));
+%!test B = CPrecedenceTester2(1);  % CPrecedenceTester2 > Snork
+%!assert (isequal (tattack (A, B), 'CPrecedenceTester2'))
+%!assert (isequal (tattack (B, A), 'CPrecedenceTester2'))
+%% Trying to change to CPrecendenceTester < Snork
+%!error D = CPrecedenceTester2(2);
+
+%!shared A, B
+%!test A = Snork(rand(2));
+%!test B = CPrecedenceTester3(2);  % CPrecedenceTester3 < Snork
+%!assert (isequal (tattack (A, B), 'Snork'))
+%!assert (isequal (tattack (B, A), 'Snork'))
+%% Trying to change to CPrecendenceTester3 > Snork
+%!error D = CPrecedenceTester3(1);
--- a/test/classes/module.mk	Mon Feb 11 15:45:26 2013 -0500
+++ b/test/classes/module.mk	Thu Feb 28 02:04:24 2013 -0500
@@ -1,14 +1,18 @@
-classes_FCN_FILES = \
+class_Blork_FCN_FILES = \
   classes/@Blork/Blork.m \
   classes/@Blork/bleek.m \
   classes/@Blork/display.m \
   classes/@Blork/get.m \
-  classes/@Blork/set.m \
+  classes/@Blork/set.m
+
+class_Cork_FCN_FILES = \
   classes/@Cork/Cork.m \
   classes/@Cork/click.m \
   classes/@Cork/display.m \
   classes/@Cork/get.m \
-  classes/@Cork/set.m \
+  classes/@Cork/set.m
+
+class_Dork_FCN_FILES = \
   classes/@Dork/Dork.m \
   classes/@Dork/bling.m \
   classes/@Dork/display.m \
@@ -16,7 +20,9 @@
   classes/@Dork/get.m \
   classes/@Dork/getStash.m \
   classes/@Dork/private/myStash.m \
-  classes/@Dork/set.m \
+  classes/@Dork/set.m
+
+class_Gork_FCN_FILES = \
   classes/@Gork/Gork.m \
   classes/@Gork/cork.m \
   classes/@Gork/display.m \
@@ -24,16 +30,22 @@
   classes/@Gork/get.m \
   classes/@Gork/set.m \
   classes/@Gork/subsasgn.m \
-  classes/@Gork/subsref.m \
+  classes/@Gork/subsref.m
+
+class_Pork_FCN_FILES = \
   classes/@Pork/Pork.m \
   classes/@Pork/bling.m \
   classes/@Pork/display.m \
   classes/@Pork/get.m \
   classes/@Pork/gurk.m \
   classes/@Pork/private/myStash.m \
-  classes/@Pork/set.m \
+  classes/@Pork/set.m
+
+class_Sneetch_FCN_FILES = \
   classes/@Sneetch/Sneetch.m \
-  classes/@Sneetch/display.m \
+  classes/@Sneetch/display.m
+
+class_Snork_FCN_FILES = \
   classes/@Snork/Snork.m \
   classes/@Snork/cack.m \
   classes/@Snork/display.m \
@@ -68,7 +80,9 @@
   classes/@Snork/times.m \
   classes/@Snork/uminus.m \
   classes/@Snork/uplus.m \
-  classes/@Snork/vertcat.m \
+  classes/@Snork/vertcat.m
+
+class_Spork_FCN_FILES = \
   classes/@Spork/Spork.m \
   classes/@Spork/cack.m \
   classes/@Spork/display.m \
@@ -78,7 +92,32 @@
   classes/@Spork/loadobj.m \
   classes/@Spork/private/myStash.m \
   classes/@Spork/saveobj.m \
-  classes/@Spork/set.m \
+  classes/@Spork/set.m
+
+class_CPrecedenceTester1_FCN_FILES = \
+  classes/@CPrecedenceTester1/CPrecedenceTester1.m \
+  classes/@CPrecedenceTester1/tattack.m
+
+class_CPrecedenceTester2_FCN_FILES = \
+  classes/@CPrecedenceTester2/CPrecedenceTester2.m \
+  classes/@CPrecedenceTester2/tattack.m
+
+class_CPrecedenceTester3_FCN_FILES = \
+  classes/@CPrecedenceTester3/CPrecedenceTester3.m \
+  classes/@CPrecedenceTester3/tattack.m
+
+classes_FCN_FILES = \
+  $(class_Blork_FCN_FILES) \
+  $(class_Cork_FCN_FILES) \
+  $(class_Dork_FCN_FILES) \
+  $(class_Gork_FCN_FILES) \
+  $(class_Pork_FCN_FILES) \
+  $(class_Sneetch_FCN_FILES) \
+  $(class_Snork_FCN_FILES) \
+  $(class_Spork_FCN_FILES) \
+  $(class_CPrecedenceTester1_FCN_FILES) \
+  $(class_CPrecedenceTester2_FCN_FILES) \
+  $(class_CPrecedenceTester3_FCN_FILES) \
   classes/classes.tst
 
 FCN_FILES += $(classes_FCN_FILES)
--- a/test/index.tst	Mon Feb 11 15:45:26 2013 -0500
+++ b/test/index.tst	Thu Feb 28 02:04:24 2013 -0500
@@ -210,3 +210,20 @@
 %!error <attempted to use a complex scalar as an index> x(i)
 %!error <attempted to use a complex scalar as an index> x(j)
 %!error <attempted to use a complex scalar as an index> x(1+i)
+
+## bug #38357
+%!shared d, dd
+%! d = diag ([1, 2, 3]);
+%! dd = diag ([1, 2, 3], 6, 3);
+%!assert (d(1), 1);
+%!assert (dd(1), 1);
+%!assert (d(3, 3), 3);
+%!assert (dd(3, 3), 3);
+%!assert (d(2), 0);
+%!assert (dd(2), 0);
+%!assert (dd(6,1), 0);
+%!error d(6,6);
+%!error dd(6,6);
+%!error d(3,6);
+%!error dd(3,6);
+