changeset 15096:909a2797935b

maint: Move interp source code without DEFUNs to interp-core/ dir. * src/Makefile.am, interpfcn/module.mk, operators/module.mk, parse-tree/module.mk: Update build system by moving source lists and rules to the correct directory. * Cell.cc, Cell.h, c-file-ptr-stream.cc, c-file-ptr-stream.h, comment-list.cc, comment-list.h, cutils.c, cutils.h, defun-dld.h, defun-int.h, display.cc, display.h, dynamic-ld.cc, dynamic-ld.h, gl-render.cc, gl-render.h, gl2ps-renderer.cc, gl2ps-renderer.h, gl2ps.c, gl2ps.h, gripes.cc, gripes.h, jit-ir.cc, jit-ir.h, jit-typeinfo.cc, jit-typeinfo.h, jit-util.cc, jit-util.h, ls-ascii-helper.cc, ls-ascii-helper.h, ls-hdf5.cc, ls-hdf5.h, ls-mat-ascii.cc, ls-mat-ascii.h, ls-mat4.cc, ls-mat4.h, ls-mat5.cc, ls-mat5.h, ls-oct-binary.cc, ls-oct-binary.h, ls-utils.cc, ls-utils.h, matherr.c, mex.cc, mex.h, mexproto.h, module.mk, mxarray.in.h, oct-errno.h, oct-errno.in.cc, oct-fstrm.cc, oct-fstrm.h, oct-hdf5.h, oct-iostrm.cc, oct-iostrm.h, oct-lvalue.cc, oct-lvalue.h, oct-map.cc, oct-map.h, oct-obj.cc, oct-obj.h, oct-prcstrm.cc, oct-prcstrm.h, oct-procbuf.cc, oct-procbuf.h, oct-stdstrm.h, oct-stream.cc, oct-stream.h, oct-strstrm.cc, oct-strstrm.h, oct.h, procstream.cc, procstream.h, pt-jit.cc, pt-jit.h, siglist.c, siglist.h, sparse-xdiv.cc, sparse-xdiv.h, sparse-xpow.cc, sparse-xpow.h, txt-eng-ft.cc, txt-eng-ft.h, txt-eng.h, unwind-prot.cc, unwind-prot.h, xdiv.cc, xdiv.h, xgl2ps.c, xnorm.cc, xnorm.h, xpow.cc, xpow.h, zfstream.cc, zfstream.h: Move from src/ dir to src/interp-core dir. * ops.h: Move to operators/ directory. * octave.gperf, token.cc, token.h: Move to parse-tree directory.
author Rik <rik@octave.org>
date Fri, 03 Aug 2012 13:18:21 -0700
parents 9df70a18aa27
children 7c7b9ea23a86 b9b6a310ad97 d7f8b0b91cb2
files src/Cell.cc src/Cell.h src/Makefile.am src/c-file-ptr-stream.cc src/c-file-ptr-stream.h src/comment-list.cc src/comment-list.h src/cutils.c src/cutils.h src/defun-dld.h src/defun-int.h src/display.cc src/display.h src/dynamic-ld.cc src/dynamic-ld.h src/gl-render.cc src/gl-render.h src/gl2ps-renderer.cc src/gl2ps-renderer.h src/gl2ps.c src/gl2ps.h src/gripes.cc src/gripes.h src/interp-core/Cell.cc src/interp-core/Cell.h src/interp-core/c-file-ptr-stream.cc src/interp-core/c-file-ptr-stream.h src/interp-core/comment-list.cc src/interp-core/comment-list.h src/interp-core/cutils.c src/interp-core/cutils.h src/interp-core/defun-dld.h src/interp-core/defun-int.h src/interp-core/display.cc src/interp-core/display.h src/interp-core/dynamic-ld.cc src/interp-core/dynamic-ld.h src/interp-core/gl-render.cc src/interp-core/gl-render.h src/interp-core/gl2ps-renderer.cc src/interp-core/gl2ps-renderer.h src/interp-core/gl2ps.c src/interp-core/gl2ps.h src/interp-core/gripes.cc src/interp-core/gripes.h src/interp-core/jit-ir.cc src/interp-core/jit-ir.h src/interp-core/jit-typeinfo.cc src/interp-core/jit-typeinfo.h src/interp-core/jit-util.cc src/interp-core/jit-util.h src/interp-core/ls-ascii-helper.cc src/interp-core/ls-ascii-helper.h src/interp-core/ls-hdf5.cc src/interp-core/ls-hdf5.h src/interp-core/ls-mat-ascii.cc src/interp-core/ls-mat-ascii.h src/interp-core/ls-mat4.cc src/interp-core/ls-mat4.h src/interp-core/ls-mat5.cc src/interp-core/ls-mat5.h src/interp-core/ls-oct-binary.cc src/interp-core/ls-oct-binary.h src/interp-core/ls-utils.cc src/interp-core/ls-utils.h src/interp-core/matherr.c src/interp-core/mex.cc src/interp-core/mex.h src/interp-core/mexproto.h src/interp-core/module.mk src/interp-core/mxarray.in.h src/interp-core/oct-errno.h src/interp-core/oct-errno.in.cc src/interp-core/oct-fstrm.cc src/interp-core/oct-fstrm.h src/interp-core/oct-hdf5.h src/interp-core/oct-iostrm.cc src/interp-core/oct-iostrm.h src/interp-core/oct-lvalue.cc src/interp-core/oct-lvalue.h src/interp-core/oct-map.cc src/interp-core/oct-map.h src/interp-core/oct-obj.cc src/interp-core/oct-obj.h src/interp-core/oct-prcstrm.cc src/interp-core/oct-prcstrm.h src/interp-core/oct-procbuf.cc src/interp-core/oct-procbuf.h src/interp-core/oct-stdstrm.h src/interp-core/oct-stream.cc src/interp-core/oct-stream.h src/interp-core/oct-strstrm.cc src/interp-core/oct-strstrm.h src/interp-core/oct.h src/interp-core/procstream.cc src/interp-core/procstream.h src/interp-core/pt-jit.cc src/interp-core/pt-jit.h src/interp-core/siglist.c src/interp-core/siglist.h src/interp-core/sparse-xdiv.cc src/interp-core/sparse-xdiv.h src/interp-core/sparse-xpow.cc src/interp-core/sparse-xpow.h src/interp-core/txt-eng-ft.cc src/interp-core/txt-eng-ft.h src/interp-core/txt-eng.h src/interp-core/unwind-prot.cc src/interp-core/unwind-prot.h src/interp-core/xdiv.cc src/interp-core/xdiv.h src/interp-core/xgl2ps.c src/interp-core/xnorm.cc src/interp-core/xnorm.h src/interp-core/xpow.cc src/interp-core/xpow.h src/interp-core/zfstream.cc src/interp-core/zfstream.h src/interpfcn/module.mk src/jit-ir.cc src/jit-ir.h src/jit-typeinfo.cc src/jit-typeinfo.h src/jit-util.cc src/jit-util.h src/ls-ascii-helper.cc src/ls-ascii-helper.h src/ls-hdf5.cc src/ls-hdf5.h src/ls-mat-ascii.cc src/ls-mat-ascii.h src/ls-mat4.cc src/ls-mat4.h src/ls-mat5.cc src/ls-mat5.h src/ls-oct-binary.cc src/ls-oct-binary.h src/ls-utils.cc src/ls-utils.h src/matherr.c src/mex.cc src/mex.h src/mexproto.h src/mxarray.in.h src/oct-errno.h src/oct-errno.in.cc src/oct-fstrm.cc src/oct-fstrm.h src/oct-hdf5.h src/oct-iostrm.cc src/oct-iostrm.h src/oct-lvalue.cc src/oct-lvalue.h src/oct-map.cc src/oct-map.h src/oct-obj.cc src/oct-obj.h src/oct-prcstrm.cc src/oct-prcstrm.h src/oct-procbuf.cc src/oct-procbuf.h src/oct-stdstrm.h src/oct-stream.cc src/oct-stream.h src/oct-strstrm.cc src/oct-strstrm.h src/oct.h src/octave.gperf src/operators/module.mk src/operators/ops.h src/ops.h src/parse-tree/module.mk src/parse-tree/octave.gperf src/parse-tree/token.cc src/parse-tree/token.h src/procstream.cc src/procstream.h src/pt-jit.cc src/pt-jit.h src/siglist.c src/siglist.h src/sparse-xdiv.cc src/sparse-xdiv.h src/sparse-xpow.cc src/sparse-xpow.h src/token.cc src/token.h src/txt-eng-ft.cc src/txt-eng-ft.h src/txt-eng.h src/unwind-prot.cc src/unwind-prot.h src/xdiv.cc src/xdiv.h src/xgl2ps.c src/xnorm.cc src/xnorm.h src/xpow.cc src/xpow.h src/zfstream.cc src/zfstream.h
diffstat 201 files changed, 50230 insertions(+), 50198 deletions(-) [+]
line wrap: on
line diff
--- a/src/Cell.cc	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,320 +0,0 @@
-/*
-
-Copyright (C) 1999-2012 John W. Eaton
-Copyright (C) 2009-2010 VZLU Prague
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "idx-vector.h"
-
-#include "Cell.h"
-#include "error.h"
-#include "gripes.h"
-#include "oct-obj.h"
-
-Cell::Cell (const octave_value_list& ovl)
-  : Array<octave_value> (ovl.cell_value ())
-{
-}
-
-Cell::Cell (const string_vector& sv, bool trim)
-  : Array<octave_value> ()
-{
-  octave_idx_type n = sv.length ();
-
-  if (n > 0)
-    {
-      resize (dim_vector (n, 1));
-
-      for (octave_idx_type i = 0; i < n; i++)
-        {
-          std::string s = sv[i];
-
-          if (trim)
-            {
-              size_t pos = s.find_last_not_of (' ');
-
-              s = (pos == std::string::npos) ? "" : s.substr (0, pos+1);
-            }
-
-          elem(i,0) = s;
-        }
-    }
-}
-
-Cell::Cell (const std::list<std::string>& lst)
-  : Array<octave_value> ()
-{
-  size_t n = lst.size ();
-
-  if (n > 0)
-    {
-      resize (dim_vector (n, 1));
-
-      octave_idx_type i = 0;
-
-      for (std::list<std::string>::const_iterator it = lst.begin ();
-           it != lst.end (); it++)
-        {
-          elem(i++,0) = *it;
-        }
-    }
-}
-
-Cell::Cell (const Array<std::string>& sa)
-  : Array<octave_value> (sa.dims ())
-{
-  octave_idx_type n = sa.numel ();
-
-  octave_value *dst = fortran_vec ();
-  const std::string *src = sa.data ();
-
-  for (octave_idx_type i = 0; i < n; i++)
-    dst[i] = src[i];
-}
-
-// Set size to DV, filling with [].  Then fill with as many elements of
-// SV as possible.
-
-Cell::Cell (const dim_vector& dv, const string_vector& sv, bool trim)
-  : Array<octave_value> (dv, Matrix ())
-{
-  octave_idx_type n = sv.length ();
-
-  if (n > 0)
-    {
-      octave_idx_type m = numel ();
-
-      octave_idx_type len = n > m ? m : n;
-
-      for (octave_idx_type i = 0; i < len; i++)
-        {
-          std::string s = sv[i];
-
-          if (trim)
-            {
-              size_t pos = s.find_last_not_of (' ');
-
-              s = (pos == std::string::npos) ? "" : s.substr (0, pos+1);
-            }
-
-          elem(i) = s;
-        }
-    }
-}
-
-bool
-Cell::is_cellstr (void) const
-{
-  bool retval = true;
-
-  octave_idx_type n = numel ();
-
-  for (octave_idx_type i = 0; i < n; i++)
-    {
-      if (! elem(i).is_string ())
-        {
-          retval = false;
-          break;
-        }
-    }
-
-  return retval;
-}
-
-Array<std::string>
-Cell::cellstr_value (void) const
-{
-  Array<std::string> retval (dims ());
-
-  octave_idx_type n = numel ();
-
-  for (octave_idx_type i = 0; i < n; i++)
-    retval.xelem (i) = elem (i).string_value ();
-
-  return retval;
-}
-
-Cell
-Cell::index (const octave_value_list& idx_arg, bool resize_ok) const
-{
-  Cell retval;
-
-  octave_idx_type n = idx_arg.length ();
-
-  switch (n)
-    {
-    case 0:
-      retval = *this;
-      break;
-
-    case 1:
-      {
-        idx_vector i = idx_arg(0).index_vector ();
-
-        if (! error_state)
-          retval = Array<octave_value>::index (i, resize_ok, Matrix ());
-      }
-      break;
-
-    case 2:
-      {
-        idx_vector i = idx_arg(0).index_vector ();
-
-        if (! error_state)
-          {
-            idx_vector j = idx_arg(1).index_vector ();
-
-            if (! error_state)
-              retval = Array<octave_value>::index (i, j, resize_ok, Matrix ());
-          }
-      }
-      break;
-
-    default:
-      {
-        Array<idx_vector> iv (dim_vector (n, 1));
-
-        for (octave_idx_type i = 0; i < n; i++)
-          {
-            iv(i) = idx_arg(i).index_vector ();
-
-            if (error_state)
-              break;
-          }
-
-        if (!error_state)
-          retval = Array<octave_value>::index (iv, resize_ok, Matrix ());
-      }
-      break;
-    }
-
-  return retval;
-}
-
-void
-Cell::assign (const octave_value_list& idx_arg, const Cell& rhs,
-              const octave_value& fill_val)
-
-{
-  octave_idx_type len = idx_arg.length ();
-
-  Array<idx_vector> ra_idx (dim_vector (len, 1));
-
-  for (octave_idx_type i = 0; i < len; i++)
-    ra_idx(i) = idx_arg(i).index_vector ();
-
-  Array<octave_value>::assign (ra_idx, rhs, fill_val);
-}
-
-void
-Cell::delete_elements (const octave_value_list& idx_arg)
-
-{
-  octave_idx_type len = idx_arg.length ();
-
-  Array<idx_vector> ra_idx (dim_vector (len, 1));
-
-  for (octave_idx_type i = 0; i < len; i++)
-    ra_idx.xelem (i) = idx_arg(i).index_vector ();
-
-  Array<octave_value>::delete_elements (ra_idx);
-}
-
-octave_idx_type
-Cell::nnz (void) const
-{
-  gripe_wrong_type_arg ("nnz", "cell array");
-  return -1;
-}
-
-Cell
-Cell::column (octave_idx_type i) const
-{
-  Cell retval;
-
-  if (ndims () < 3)
-    {
-      if (i < 0 || i >= cols ())
-        error ("invalid column selection");
-      else
-        {
-          octave_idx_type nr = rows ();
-
-          retval.resize (dim_vector (nr, 1));
-
-          for (octave_idx_type j = 0; j < nr; j++)
-            retval.xelem (j) = elem (j, i);
-        }
-    }
-  else
-    error ("Cell::column: requires 2-d cell array");
-
-  return retval;
-}
-
-Cell
-Cell::concat (const Cell& rb, const Array<octave_idx_type>& ra_idx)
-{
-  return insert (rb, ra_idx);
-}
-
-Cell&
-Cell::insert (const Cell& a, octave_idx_type r, octave_idx_type c)
-{
-  Array<octave_value>::insert (a, r, c);
-  return *this;
-}
-
-Cell&
-Cell::insert (const Cell& a, const Array<octave_idx_type>& ra_idx)
-{
-  Array<octave_value>::insert (a, ra_idx);
-  return *this;
-}
-
-Cell
-Cell::map (ctype_mapper fcn) const
-{
-  Cell retval (dims ());
-  octave_value *r = retval.fortran_vec ();
-
-  const octave_value *p = data ();
-
-  for (octave_idx_type i = 0; i < numel (); i++)
-    r[i] = ((p++)->*fcn) ();
-
-  return retval;
-}
-
-Cell
-Cell::diag (octave_idx_type k) const
-{
-  return Array<octave_value>::diag (k);
-}
-
-Cell
-Cell::diag (octave_idx_type m, octave_idx_type n) const
-{
-  return Array<octave_value>::diag (m, n);
-}
--- a/src/Cell.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,150 +0,0 @@
-/*
-
-Copyright (C) 1999-2012 John W. Eaton
-Copyright (C) 2009-2010 VZLU Prague
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#if !defined (Cell_h)
-#define Cell_h 1
-
-#include <string>
-
-#include "Array.h"
-#include "oct-alloc.h"
-#include "str-vec.h"
-#include "ov.h"
-
-class octave_value_list;
-
-class
-OCTINTERP_API
-Cell : public Array<octave_value>
-{
-public:
-
-  Cell (void)
-    : Array<octave_value> (dim_vector (0, 0)) { }
-
-  Cell (const octave_value& val)
-    : Array<octave_value> (dim_vector (1, 1), val) { }
-
-  Cell (const octave_value_list& ovl);
-
-  Cell (octave_idx_type n, octave_idx_type m,
-        const octave_value& val = Matrix ())
-    : Array<octave_value> (dim_vector (n, m), val) { }
-
-  Cell (const dim_vector& dv, const octave_value& val = Matrix ())
-    : Array<octave_value> (dv, val) { }
-
-  Cell (const Array<octave_value>& c)
-    : Array<octave_value> (c) { }
-
-  Cell (const Array<octave_value>& c, octave_idx_type nr, octave_idx_type nc)
-    : Array<octave_value> (c, dim_vector (nr, nc)) { }
-
-  Cell (const string_vector& sv, bool trim = false);
-
-  Cell (const std::list<std::string>& lst);
-
-  Cell (const Array<std::string>& sa);
-
-  Cell (const dim_vector& dv, const string_vector& sv, bool trim = false);
-
-  Cell (const Cell& c)
-    : Array<octave_value> (c) { }
-
-  bool is_cellstr (void) const;
-
-  Array<std::string> cellstr_value (void) const;
-
-  using Array<octave_value>::index;
-
-  Cell index (const octave_value_list& idx, bool resize_ok = false) const;
-
-  using Array<octave_value>::delete_elements;
-
-  void delete_elements (const octave_value_list& idx);
-
-  using Array<octave_value>::assign;
-
-  void assign (const octave_value_list& idx, const Cell& rhs,
-               const octave_value& fill_val = Matrix ());
-
-  Cell reshape (const dim_vector& new_dims) const
-    { return Array<octave_value>::reshape (new_dims); }
-
-  octave_idx_type nnz (void) const;
-
-  Cell column (octave_idx_type i) const;
-
-  // FIXME
-  boolMatrix all (int /* dim */ = 0) const { return boolMatrix (); }
-
-  // FIXME
-  boolMatrix any (int /* dim */ = 0) const { return boolMatrix (); }
-
-  Cell concat (const Cell& rb, const Array<octave_idx_type>& ra_idx);
-
-  Cell& insert (const Cell& a, octave_idx_type r, octave_idx_type c);
-  Cell& insert (const Cell& a, const Array<octave_idx_type>& ra_idx);
-
-  // FIXME
-  bool any_element_is_nan (void) const { return false; }
-  bool is_true (void) const { return false; }
-
-  octave_value resize_fill_value (void) const
-  {
-    static Matrix rfv;
-    return rfv;
-  }
-
-  Cell diag (octave_idx_type k = 0) const;
-
-  Cell diag (octave_idx_type m, octave_idx_type n) const;
-
-  Cell xisalnum (void) const { return map (&octave_value::xisalnum); }
-  Cell xisalpha (void) const { return map (&octave_value::xisalpha); }
-  Cell xisascii (void) const { return map (&octave_value::xisascii); }
-  Cell xiscntrl (void) const { return map (&octave_value::xiscntrl); }
-  Cell xisdigit (void) const { return map (&octave_value::xisdigit); }
-  Cell xisgraph (void) const { return map (&octave_value::xisgraph); }
-  Cell xislower (void) const { return map (&octave_value::xislower); }
-  Cell xisprint (void) const { return map (&octave_value::xisprint); }
-  Cell xispunct (void) const { return map (&octave_value::xispunct); }
-  Cell xisspace (void) const { return map (&octave_value::xisspace); }
-  Cell xisupper (void) const { return map (&octave_value::xisupper); }
-  Cell xisxdigit (void) const { return map (&octave_value::xisxdigit); }
-  Cell xtoascii (void) const { return map (&octave_value::xtoascii); }
-  Cell xtolower (void) const { return map (&octave_value::xtolower); }
-  Cell xtoupper (void) const { return map (&octave_value::xtoupper); }
-
-private:
-
-  typedef octave_value (octave_value::*ctype_mapper) (void) const;
-
-  Cell map (ctype_mapper) const;
-};
-
-template<>
-inline Cell octave_value_extract<Cell> (const octave_value& v)
-  { return v.cell_value (); }
-
-#endif
--- a/src/Makefile.am	Fri Aug 03 10:14:57 2012 -0500
+++ b/src/Makefile.am	Fri Aug 03 13:18:21 2012 -0700
@@ -1,4 +1,4 @@
-# Makefile for octave's src directory
+# Makefile for Octave's src directory
 #
 # Copyright (C) 1993-2012 John W. Eaton
 #
@@ -24,10 +24,12 @@
 AM_CPPFLAGS = \
   -I$(top_srcdir)/libcruft/misc \
   -I../liboctave -I$(top_srcdir)/liboctave \
+  -Ioctave-value -I$(srcdir)/octave-value \
+  -Iparse-tree -I$(srcdir)/parse-tree \
+  -Ioperators -I$(srcdir)/operators \
+  -Iinterp-core -I$(srcdir)/interp-core \
   -Iinterpfcn -I$(srcdir)/interpfcn \
   -Icorefcn \
-  -Ioctave-value -I$(srcdir)/octave-value \
-  -Iparse-tree -I$(srcdir)/parse-tree \
   -I. -I$(srcdir) \
   -I../libgnu -I$(top_srcdir)/libgnu \
   @CPPFLAGS@
@@ -66,33 +68,33 @@
 ## $(DEF_FILES), and building those requires all the sources
 ## (except builtins.cc) to be available.
 BUILT_SOURCES = \
-  $(BUILT_SOURCES_EXTRA) \
+  interp-core/mxarray.h \
+  interp-core/oct-errno.cc \
   interpfcn/defaults.h \
+  interpfcn/graphics-props.cc \
   interpfcn/graphics.h \
-  interpfcn/graphics-props.cc \
+  operators/ops.cc \
   parse-tree/lex.cc \
-  mxarray.h \
+  parse-tree/oct-gperf.h \
+  parse-tree/oct-parse.cc \
   oct-conf.h \
-  oct-errno.cc \
-  oct-gperf.h \
-  parse-tree/oct-parse.cc \
-  ops.cc \
   version.h \
+  $(BUILT_SOURCES_EXTRA) \
   builtins.cc
 
 BUILT_DISTFILES = \
-  oct-gperf.h \
+  parse-tree/oct-gperf.h \
   parse-tree/oct-parse.h
 
 ## Files that are created during build process and installed,
 ## BUT not distributed in tarball.
 BUILT_NODISTFILES = \
+  interp-core/mxarray.h \
+  interp-core/oct-errno.cc \
   interpfcn/defaults.h \
   interpfcn/graphics.h \
+  operators/ops.cc \
   oct-conf.h \
-  oct-errno.cc \
-  ops.cc \
-  mxarray.h \
   version.h \
   $(OPT_HANDLERS) \
   $(OPT_INC) \
@@ -101,13 +103,10 @@
 
 EXTRA_DIST = \
   Makefile.in \
-  defaults.in.h \
   DOCSTRINGS \
   find-defun-files.sh \
   gendoc.pl \
   genprops.awk \
-  gl2ps.c \
-  graphics.in.h \
   mk-errno-list \
   mk-pkg-add \
   mkbuiltins \
@@ -115,136 +114,36 @@
   mkoctfile.in.cc \
   mkoctfile.in.sh \
   mkops \
-  mxarray.in.h \
   oct-conf.in.h \
-  oct-errno.in.cc \
   octave-config.in.cc \
   octave-config.in.sh \
-  octave.gperf \
   version.in.h \
   $(BUILT_DISTFILES)
 
-JIT_INCLUDES = \
-  jit-util.h \
-  jit-typeinfo.h \
-  jit-ir.h \
-  pt-jit.h
-
 octinclude_HEADERS = \
-  Cell.h \
-  builtins.h \
-  c-file-ptr-stream.h \
-  comment-list.h \
-  cutils.h \
-  defun-dld.h \
-  defun-int.h \
-  display.h \
-  dynamic-ld.h \
-  gl-render.h \
-  gl2ps.h \
-  gl2ps-renderer.h \
   interpfcn/graphics-props.cc \
-  gripes.h \
-  ls-ascii-helper.h \
-  ls-hdf5.h \
-  ls-mat-ascii.h \
-  ls-mat4.h \
-  ls-mat5.h \
-  ls-oct-binary.h \
-  ls-utils.h \
-  mex.h \
-  mexproto.h \
-  oct-errno.h \
-  oct-fstrm.h \
-  oct-gperf.h \
-  oct-hdf5.h \
-  oct-iostrm.h \
-  oct-lvalue.h \
-  oct-map.h \
-  oct-obj.h \
-  oct-prcstrm.h \
-  oct-procbuf.h \
-  oct-stdstrm.h \
-  oct-stream.h \
-  oct-strstrm.h \
-  oct.h \
+  parse-tree/oct-gperf.h \
+  builtins.h \
   octave.h \
-  ops.h \
-  procstream.h \
-  siglist.h \
-  sparse-xdiv.h \
-  sparse-xpow.h \
-  token.h \
-  txt-eng-ft.h \
-  txt-eng.h \
-  unwind-prot.h \
-  xdiv.h \
-  xnorm.h \
-  xpow.h \
-  zfstream.h \
   $(OV_INCLUDES) \
   $(OV_SPARSE_INCLUDES) \
   $(PT_INCLUDES) \
-  $(INTERPFCN_INCLUDES) \
-  $(JIT_INCLUDES)
+	$(OPERATOR_INCLUDES) \
+  $(INTERP_CORE_INCLUDES) \
+  $(INTERPFCN_INCLUDES)
 
 nodist_octinclude_HEADERS = \
+  interp-core/mxarray.h \
   interpfcn/defaults.h \
   interpfcn/graphics.h \
   oct-conf.h \
-  mxarray.h \
   version.h
 
-JIT_SRC = \
-  jit-util.cc \
-  jit-typeinfo.cc \
-  jit-ir.cc \
-  pt-jit.cc
-
 DIST_SRC = \
-  Cell.cc \
-  c-file-ptr-stream.cc \
-  comment-list.cc \
-  cutils.c \
-  display.cc \
-  dynamic-ld.cc \
-  gl-render.cc \
-  gl2ps-renderer.cc \
-  gripes.cc \
-  ls-ascii-helper.cc \
-  ls-hdf5.cc \
-  ls-mat-ascii.cc \
-  ls-mat4.cc \
-  ls-mat5.cc \
-  ls-oct-binary.cc \
-  ls-utils.cc \
-  matherr.c \
-  mex.cc \
-  oct-fstrm.cc \
-  oct-iostrm.cc \
-  oct-lvalue.cc \
-  oct-map.cc \
-  oct-obj.cc \
-  oct-prcstrm.cc \
-  oct-procbuf.cc \
-  oct-stream.cc \
-  oct-strstrm.cc \
   octave.cc \
-  procstream.cc \
-  siglist.c \
-  sparse-xdiv.cc \
-  sparse-xpow.cc \
-  token.cc \
-  txt-eng-ft.cc \
-  unwind-prot.cc \
-  xdiv.cc \
-  xgl2ps.c \
-  xnorm.cc \
-  xpow.cc \
-  zfstream.cc \
   $(OCTAVE_VALUE_SRC) \
   $(PARSE_TREE_SRC) \
-  $(JIT_SRC) \
+  $(INTERP_CORE_SRC) \
   $(INTERPFCN_SRC) \
   $(COREFCN_SRC)
 
@@ -254,6 +153,7 @@
 include octave-value/module.mk
 include operators/module.mk
 include template-inst/module.mk
+include interp-core/module.mk
 include interpfcn/module.mk
 include corefcn/module.mk
 include dldfcn/module.mk
@@ -277,13 +177,13 @@
   $(TEMPLATE_INST_SRC)
 
 nodist_liboctinterp_la_SOURCES = \
-  builtins.cc \
+  interp-core/mxarray.h \
+  interp-core/oct-errno.cc \
   interpfcn/defaults.h \
   interpfcn/graphics.h \
-  mxarray.h \
+  operators/ops.cc \
+  builtins.cc \
   oct-conf.h \
-  oct-errno.cc \
-  ops.cc \
   version.h \
   $(OPT_INC)
 
@@ -309,8 +209,6 @@
   -bindir $(bindir) \
   $(LIBOCTINTERP_LINK_OPTS)
 
-display.df display.lo: CPPFLAGS += $(X11_FLAGS)
-
 ## FIXME: Does this rule need to be uncommented?
 #fft.df fft.lo fft2.df fft2.lo fftn.df fftn.lo: CPPFLAGS += $(FFTW_XCPPFLAGS)
 
@@ -358,27 +256,12 @@
 ## Special rules:
 ## Mostly for sources which must be built before rest of compilation.
 
-## defaults.h and oct-conf.h must depend on Makefile.  Calling configure
+## oct-conf.h must depend on Makefile.  Calling configure
 ## may change default/config values.  However, calling configure will also
 ## regenerate the Makefiles from Makefile.am and trigger the rules below.
 oct-conf.h: oct-conf.in.h Makefile
 	@$(do_subst_config_vals)
 
-## Don't use a pipeline to process gperf output since if gperf
-## is missing but sed is not, the exit status of the pipeline
-## will still be success and we will end up creating an empty
-## oct-gperf.h file.
-oct-gperf.h: octave.gperf
-	$(GPERF) -t -C -D -G -L C++ -Z octave_kw_hash $< > $@-t1
-	$(SED) 's,lookup\[,gperf_lookup[,' < $@-t1 > $@-t
-	mv $@-t $@
-	rm -f $@-t1
-
-mxarray.h: mxarray.in.h Makefile
-	$(SED) < $< \
-	  -e "s|%OCTAVE_IDX_TYPE%|${OCTAVE_IDX_TYPE}|" > $@-t
-	mv $@-t $@
-
 version.h: version.in.h Makefile
 	$(SED) < $< \
 	  -e "s|%OCTAVE_API_VERSION_NUMBER%|${OCTAVE_API_VERSION_NUMBER}|" \
@@ -392,20 +275,6 @@
 	$(srcdir)/mkbuiltins $(DEF_FILES) > $@-t
 	mv $@-t $@
 
-ops.cc: $(OPERATORS_SRC) mkops
-	$(srcdir)/mkops $(OPERATORS_SRC) > $@-t
-	mv $@-t $@
-
-oct-errno.cc: oct-errno.in.cc Makefile
-	if test -n "$(PERL)"; then \
-	  $(srcdir)/mk-errno-list --perl "$(PERL)" < $< > $@-t; \
-	elif test -n "$(PYTHON)"; then \
-	  $(srcdir)/mk-errno-list --python "$(PYTHON)" < $< > $@-t; \
-	else \
-	  $(SED) '/@SYSDEP_ERRNO_LIST@/D' $< > $@-t; \
-	fi
-	mv $@-t $@
-
 if AMCOND_ENABLE_DYNAMIC_LINKING
 DLDFCN_PKG_ADD_FILE = dldfcn/PKG_ADD
 
@@ -414,12 +283,6 @@
 	mv $@-t $@
 endif
 
-__fltk_uigetfile__.lo __fltk_uigetfile__.o: \
-  AM_CXXFLAGS := $(filter-out $(DLL_CXXDEFS), $(AM_CXXFLAGS) $(GRAPHICS_CFLAGS))
-
-__init_fltk__.lo __init_fltk__.o: \
-  AM_CXXFLAGS := $(filter-out $(DLL_CXXDEFS), $(AM_CXXFLAGS) $(GRAPHICS_CFLAGS))
-
 if AMCOND_BUILD_DOCS
 .DOCSTRINGS: $(ALL_DEF_FILES) gendoc.pl
 	if [ "x$(srcdir)" != "x." ] && [ -f $(srcdir)/DOCSTRINGS ] && [ ! -f DOCSTRINGS ]; then \
--- a/src/c-file-ptr-stream.cc	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,362 +0,0 @@
-/*
-
-Copyright (C) 2000-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <iostream>
-
-#include "c-file-ptr-stream.h"
-
-#ifndef SEEK_SET
-#define SEEK_SET 0
-#endif
-
-#ifndef SEEK_CUR
-#define SEEK_CUR 1
-#endif
-
-#ifndef SEEK_END
-#define SEEK_END 2
-#endif
-
-c_file_ptr_buf::~c_file_ptr_buf (void)
-{
-  buf_close ();
-}
-
-// FIXME -- I'm sure there is room for improvement here...
-
-c_file_ptr_buf::int_type
-c_file_ptr_buf::overflow (int_type c)
-{
-#if defined (CXX_ISO_COMPLIANT_LIBRARY)
-  if (f)
-    return (c != traits_type::eof ()) ? gnulib::fputc (c, f) : flush ();
-  else
-    return traits_type::not_eof (c);
-#else
-  if (f)
-    return (c != EOF) ? gnulib::fputc (c, f) : flush ();
-  else
-    return EOF;
-#endif
-}
-
-c_file_ptr_buf::int_type
-c_file_ptr_buf::underflow_common (bool bump)
-{
-  if (f)
-    {
-      int_type c = gnulib::fgetc (f);
-
-      if (! bump
-#if defined (CXX_ISO_COMPLIANT_LIBRARY)
-          && c != traits_type::eof ())
-#else
-          && c != EOF)
-#endif
-        ungetc (c, f);
-
-      return c;
-    }
-  else
-#if defined (CXX_ISO_COMPLIANT_LIBRARY)
-    return traits_type::eof ();
-#else
-    return EOF;
-#endif
-}
-
-c_file_ptr_buf::int_type
-c_file_ptr_buf::pbackfail (int_type c)
-{
-#if defined (CXX_ISO_COMPLIANT_LIBRARY)
-  return (c != traits_type::eof () && f) ? ungetc (c, f) :
-    traits_type::not_eof (c);
-#else
-  return (c != EOF && f) ? ungetc (c, f) : EOF;
-#endif
-}
-
-std::streamsize
-c_file_ptr_buf::xsputn (const char* s, std::streamsize n)
-{
-  if (f)
-    return gnulib::fwrite (s, 1, n, f);
-  else
-    return 0;
-}
-
-std::streamsize
-c_file_ptr_buf::xsgetn (char *s, std::streamsize n)
-{
-  if (f)
-    return gnulib::fread (s, 1, n, f);
-  else
-    return 0;
-}
-
-static inline int
-seekdir_to_whence (std::ios::seekdir dir)
-{
-  return ((dir == std::ios::beg) ? SEEK_SET :
-          (dir == std::ios::cur) ? SEEK_CUR :
-          (dir == std::ios::end) ? SEEK_END :
-          dir);
-}
-
-std::streampos
-c_file_ptr_buf::seekoff (std::streamoff /* offset */,
-                         std::ios::seekdir /* dir */,
-                         std::ios::openmode)
-{
-  // FIXME
-#if 0
-  if (f)
-    {
-      fseek (f, offset, seekdir_to_whence (dir));
-
-      return ftell (f);
-    }
-  else
-    return 0;
-#endif
-  return -1;
-}
-
-std::streampos
-c_file_ptr_buf::seekpos (std::streampos /* offset */, std::ios::openmode)
-{
-  // FIXME
-#if 0
-  if (f)
-    {
-      fseek (f, offset, SEEK_SET);
-
-      return ftell (f);
-    }
-  else
-    return 0;
-#endif
-  return -1;
-}
-
-int
-c_file_ptr_buf::sync (void)
-{
-  flush ();
-
-  return 0;
-}
-
-int
-c_file_ptr_buf::flush (void)
-{
-  return f ? gnulib::fflush (f) : EOF;
-}
-
-int
-c_file_ptr_buf::buf_close (void)
-{
-  int retval = -1;
-
-  flush ();
-
-  if (f)
-    {
-      retval = cf (f);
-      f = 0;
-    }
-
-  return retval;
-}
-
-int
-c_file_ptr_buf::seek (long offset, int origin)
-{
-  return f ? gnulib::fseek (f, offset, origin) : -1;
-}
-
-long
-c_file_ptr_buf::tell (void)
-{
-  return f ? gnulib::ftell (f) : -1;
-}
-
-int
-c_file_ptr_buf::file_close (FILE *f)
-{
-  return gnulib::fclose (f);
-}
-
-#ifdef HAVE_ZLIB
-
-c_zfile_ptr_buf::~c_zfile_ptr_buf (void)
-{
-  buf_close ();
-}
-
-// FIXME -- I'm sure there is room for improvement here...
-
-c_zfile_ptr_buf::int_type
-c_zfile_ptr_buf::overflow (int_type c)
-{
-#if defined (CXX_ISO_COMPLIANT_LIBRARY)
-  if (f)
-    return (c != traits_type::eof ()) ? gzputc (f, c) : flush ();
-  else
-    return traits_type::not_eof (c);
-#else
-  if (f)
-    return (c != EOF) ? gzputc (f, c) : flush ();
-  else
-    return EOF;
-#endif
-}
-
-c_zfile_ptr_buf::int_type
-c_zfile_ptr_buf::underflow_common (bool bump)
-{
-  if (f)
-    {
-      int_type c = gzgetc (f);
-
-      if (! bump
-#if defined (CXX_ISO_COMPLIANT_LIBRARY)
-          && c != traits_type::eof ())
-#else
-          && c != EOF)
-#endif
-        gzungetc (c, f);
-
-      return c;
-    }
-  else
-#if defined (CXX_ISO_COMPLIANT_LIBRARY)
-    return traits_type::eof ();
-#else
-    return EOF;
-#endif
-}
-
-c_zfile_ptr_buf::int_type
-c_zfile_ptr_buf::pbackfail (int_type c)
-{
-#if defined (CXX_ISO_COMPLIANT_LIBRARY)
-  return (c != traits_type::eof () && f) ? gzungetc (c, f) :
-    traits_type::not_eof (c);
-#else
-  return (c != EOF && f) ? gzungetc (c, f) : EOF;
-#endif
-}
-
-std::streamsize
-c_zfile_ptr_buf::xsputn (const char* s, std::streamsize n)
-{
-  if (f)
-    return gzwrite (f, s, n);
-  else
-    return 0;
-}
-
-std::streamsize
-c_zfile_ptr_buf::xsgetn (char *s, std::streamsize n)
-{
-  if (f)
-    return gzread (f, s, n);
-  else
-    return 0;
-}
-
-std::streampos
-c_zfile_ptr_buf::seekoff (std::streamoff /* offset */,
-                          std::ios::seekdir /* dir */,
-                          std::ios::openmode)
-{
-  // FIXME
-#if 0
-  if (f)
-    {
-      gzseek (f, offset, seekdir_to_whence (dir));
-
-      return gztell (f);
-    }
-  else
-    return 0;
-#endif
-  return -1;
-}
-
-std::streampos
-c_zfile_ptr_buf::seekpos (std::streampos /* offset */, std::ios::openmode)
-{
-  // FIXME
-#if 0
-  if (f)
-    {
-      gzseek (f, offset, SEEK_SET);
-
-      return gztell (f);
-    }
-  else
-    return 0;
-#endif
-  return -1;
-}
-
-int
-c_zfile_ptr_buf::sync (void)
-{
-  flush ();
-
-  return 0;
-}
-
-int
-c_zfile_ptr_buf::flush (void)
-{
-  // FIXME -- do we need something more complex here, passing
-  // something other than 0 for the second argument to gzflush and
-  // checking the return value, etc.?
-
-  return f ? gzflush (f, 0) : EOF;
-}
-
-int
-c_zfile_ptr_buf::buf_close (void)
-{
-  int retval = -1;
-
-  flush ();
-
-  if (f)
-    {
-      retval = cf (f);
-      f = 0;
-    }
-
-  return retval;
-}
-
-#endif
--- a/src/c-file-ptr-stream.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,227 +0,0 @@
-/*
-
-Copyright (C) 2000-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#if !defined (octave_c_file_ptr_stream_h)
-#define octave_c_file_ptr_stream_h 1
-
-#include <cstdio>
-
-#include <iosfwd>
-
-class
-c_file_ptr_buf : public std::streambuf
-{
-public:
-
-#if !defined (CXX_ISO_COMPLIANT_LIBRARY)
-  typedef int int_type;
-#else
-  typedef std::streambuf::int_type int_type;
-#endif
-
-  typedef int (*close_fcn) (FILE *);
-
-  FILE* stdiofile (void) { return f; }
-
-  c_file_ptr_buf (FILE *f_arg, close_fcn cf_arg = file_close)
-    : std::streambuf (), f (f_arg), cf (cf_arg)
-    { }
-
-  ~c_file_ptr_buf (void);
-
-  int_type overflow (int_type);
-
-  int_type underflow (void) { return underflow_common (false); }
-
-  int_type uflow (void) { return underflow_common (true); }
-
-  int_type pbackfail (int_type);
-
-  std::streamsize xsputn (const char*, std::streamsize);
-
-  std::streamsize xsgetn (char *, std::streamsize);
-
-  std::streampos seekoff (std::streamoff, std::ios::seekdir,
-                          std::ios::openmode = std::ios::in | std::ios::out);
-
-  std::streampos seekpos (std::streampos,
-                          std::ios::openmode = std::ios::in | std::ios::out);
-
-  int sync (void);
-
-  int flush (void);
-
-  int buf_close (void);
-
-  int file_number () const { return f ? fileno (f) : -1; }
-
-  int seek (long offset, int origin);
-
-  long tell (void);
-
-  void clear (void) { if (f) clearerr (f); }
-
-  static int file_close (FILE *f);
-
-protected:
-
-  FILE *f;
-
-  close_fcn cf;
-
-private:
-
-  int_type underflow_common (bool);
-
-  // No copying!
-
-  c_file_ptr_buf (const c_file_ptr_buf&);
-
-  c_file_ptr_buf& operator = (const c_file_ptr_buf&);
-};
-
-// FIXME -- the following three classes could probably share
-// some code...
-
-template <typename STREAM_T, typename FILE_T, typename BUF_T>
-class
-c_file_ptr_stream : public STREAM_T
-{
-public:
-
-  c_file_ptr_stream (FILE_T f, typename BUF_T::close_fcn cf = BUF_T::file_close)
-    : STREAM_T (0), buf (new BUF_T (f, cf)) { STREAM_T::init (buf); }
-
-  ~c_file_ptr_stream (void) { delete buf; buf = 0; }
-
-  BUF_T *rdbuf (void) { return buf; }
-
-  void stream_close (void) { if (buf) buf->buf_close (); }
-
-  int seek (long offset, int origin)
-    { return buf ? buf->seek (offset, origin) : -1; }
-
-  long tell (void) { return buf ? buf->tell () : -1; }
-
-  void clear (void) { if (buf) buf->clear (); STREAM_T::clear (); }
-
-private:
-
-  BUF_T *buf;
-
-  // No copying!
-
-  c_file_ptr_stream (const c_file_ptr_stream&);
-
-  c_file_ptr_stream& operator = (const c_file_ptr_stream&);
-};
-
-typedef c_file_ptr_stream<std::istream, FILE *, c_file_ptr_buf> i_c_file_ptr_stream;
-typedef c_file_ptr_stream<std::ostream, FILE *, c_file_ptr_buf> o_c_file_ptr_stream;
-typedef c_file_ptr_stream<std::iostream, FILE *, c_file_ptr_buf> io_c_file_ptr_stream;
-
-#ifdef HAVE_ZLIB
-
-#ifdef HAVE_ZLIB_H
-#include <zlib.h>
-#endif
-
-class
-c_zfile_ptr_buf : public std::streambuf
-{
-public:
-
-#if !defined (CXX_ISO_COMPLIANT_LIBRARY)
-  typedef int int_type;
-#else
-  typedef std::streambuf::int_type int_type;
-#endif
-
-  typedef int (*close_fcn) (gzFile);
-
-  gzFile stdiofile (void) { return f; }
-
-  c_zfile_ptr_buf (gzFile f_arg, close_fcn cf_arg = file_close)
-    : std::streambuf (), f (f_arg), cf (cf_arg)
-    { }
-
-  ~c_zfile_ptr_buf (void);
-
-  int_type overflow (int_type);
-
-  int_type underflow (void) { return underflow_common (false); }
-
-  int_type uflow (void) { return underflow_common (true); }
-
-  int_type pbackfail (int_type);
-
-  std::streamsize xsputn (const char*, std::streamsize);
-
-  std::streamsize xsgetn (char *, std::streamsize);
-
-  std::streampos seekoff (std::streamoff, std::ios::seekdir,
-                          std::ios::openmode = std::ios::in | std::ios::out);
-
-  std::streampos seekpos (std::streampos,
-                          std::ios::openmode = std::ios::in | std::ios::out);
-
-  int sync (void);
-
-  int flush (void);
-
-  int buf_close (void);
-
-  int file_number () const { return -1; }
-
-  int seek (long offset, int origin)
-    { return f ? gzseek (f, offset, origin) : -1; }
-
-  long tell (void) { return f ? gztell (f) : -1; }
-
-  void clear (void) { if (f) gzclearerr (f); }
-
-  static int file_close (gzFile f) { return ::gzclose (f); }
-
-protected:
-
-  gzFile f;
-
-  close_fcn cf;
-
-private:
-
-  int_type underflow_common (bool);
-
-  // No copying!
-
-  c_zfile_ptr_buf (const c_zfile_ptr_buf&);
-
-  c_zfile_ptr_buf& operator = (const c_zfile_ptr_buf&);
-};
-
-typedef c_file_ptr_stream<std::istream, gzFile, c_zfile_ptr_buf> i_c_zfile_ptr_stream;
-typedef c_file_ptr_stream<std::ostream, gzFile, c_zfile_ptr_buf> o_c_zfile_ptr_stream;
-typedef c_file_ptr_stream<std::iostream, gzFile, c_zfile_ptr_buf> io_c_zfile_ptr_stream;
-
-#endif
-
-#endif
--- a/src/comment-list.cc	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,106 +0,0 @@
-/*
-
-Copyright (C) 2000-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "lo-utils.h"
-#include "singleton-cleanup.h"
-
-#include "comment-list.h"
-#include "error.h"
-
-octave_comment_buffer *octave_comment_buffer::instance = 0;
-
-octave_comment_list *
-octave_comment_list::dup (void) const
-{
-  octave_comment_list *new_cl = new octave_comment_list ();
-
-  for (const_iterator p = begin (); p != end (); p++)
-    {
-      const octave_comment_elt elt = *p;
-
-      new_cl->append (elt);
-    }
-
-  return new_cl;
-}
-
-bool
-octave_comment_buffer::instance_ok (void)
-{
-  bool retval = true;
-
-  if (! instance)
-    {
-      instance = new octave_comment_buffer ();
-
-      if (instance)
-        singleton_cleanup_list::add (cleanup_instance);
-    }
-
-  if (! instance)
-    {
-      ::error ("unable to create comment buffer object");
-
-      retval = false;
-    }
-
-  return retval;
-}
-
-void
-octave_comment_buffer::append (const std::string& s,
-                               octave_comment_elt::comment_type t)
-{
-  if (instance_ok ())
-    instance->do_append (s, t);
-}
-
-octave_comment_list *
-octave_comment_buffer::get_comment (void)
-{
-  return (instance_ok ()) ? instance->do_get_comment () : 0;
-}
-
-void
-octave_comment_buffer::do_append (const std::string& s,
-                                  octave_comment_elt::comment_type t)
-{
-  comment_list->append (s, t);
-}
-
-octave_comment_list *
-octave_comment_buffer::do_get_comment (void)
-{
-  octave_comment_list *retval = 0;
-
-  if (comment_list && comment_list->length () > 0)
-    {
-      retval = comment_list;
-      comment_list = new octave_comment_list ();
-    }
-
-  return retval;
-}
--- a/src/comment-list.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,131 +0,0 @@
-/*
-
-Copyright (C) 2000-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#if !defined (octave_comment_list_h)
-#define octave_comment_list_h 1
-
-#include <string>
-
-#include <base-list.h>
-
-extern std::string get_comment_text (void);
-
-extern char *get_comment_text_c_str (void);
-
-extern void save_comment_text (const std::string& text);
-
-class
-octave_comment_elt
-{
-public:
-
-  enum comment_type
-  {
-    unknown,
-    block,
-    end_of_line,
-    doc_string,
-    copyright
-  };
-
-  octave_comment_elt (const std::string& s = std::string (),
-                      comment_type t = unknown)
-    : txt (s), typ (t) { }
-
-  octave_comment_elt (const octave_comment_elt& oc)
-    : txt (oc.txt), typ (oc.typ) { }
-
-  octave_comment_elt& operator = (const octave_comment_elt& oc)
-    {
-      if (this != &oc)
-        {
-          txt = oc.txt;
-          typ = oc.typ;
-        }
-
-      return *this;
-    }
-
-  std::string text (void) const { return txt; }
-
-  comment_type type (void) const { return typ; }
-
-  ~octave_comment_elt (void) { }
-
-private:
-
-  // The text of the comment.
-  std::string txt;
-
-  // The type of comment.
-  comment_type typ;
-};
-
-class
-octave_comment_list : public octave_base_list<octave_comment_elt>
-{
-public:
-
-  octave_comment_list (void) { }
-
-  void append (const octave_comment_elt& elt)
-    { octave_base_list<octave_comment_elt>::append (elt); }
-
-  void append (const std::string& s,
-               octave_comment_elt::comment_type t = octave_comment_elt::unknown)
-    { append (octave_comment_elt (s, t)); }
-
-  octave_comment_list *dup (void) const;
-};
-
-class
-octave_comment_buffer
-{
-public:
-
-  octave_comment_buffer (void)
-    : comment_list (new octave_comment_list ()) { }
-
-  ~octave_comment_buffer (void) { delete comment_list; }
-
-  static bool instance_ok (void);
-
-  static void append
-    (const std::string& s,
-     octave_comment_elt::comment_type t = octave_comment_elt::unknown);
-
-  static octave_comment_list *get_comment (void);
-
-private:
-
-  void do_append (const std::string& s, octave_comment_elt::comment_type t);
-
-  octave_comment_list *do_get_comment (void);
-
-  octave_comment_list *comment_list;
-
-  static octave_comment_buffer *instance;
-
-  static void cleanup_instance (void) { delete instance; instance = 0; }
-};
-
-#endif
--- a/src/cutils.c	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/*
-
-Copyright (C) 1999-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <time.h>
-
-#include <sys/types.h>
-#include <unistd.h>
-
-#include "cutils.h"
-
-void
-octave_sleep (unsigned int seconds)
-{
-  sleep (seconds);
-}
-
-void
-octave_usleep (unsigned int useconds)
-{
-  struct timespec delay;
-  struct timespec remaining;
-
-  unsigned int sec = useconds / 1000000;
-  unsigned int usec = useconds % 1000000;
-
-  delay.tv_sec = sec;
-  delay.tv_nsec = usec * 1000;
-
-  nanosleep (&delay, &remaining);
-}
-
-int
-octave_raw_vsnprintf (char *buf, size_t n, const char *fmt, va_list args)
-{
-  return vsnprintf (buf, n, fmt, args);
-}
--- a/src/cutils.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-/*
-
-Copyright (C) 2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#if !defined (octave_cutils_h)
-#define octave_cutils_h 1
-
-#include <stdarg.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-OCTINTERP_API void octave_sleep (unsigned int seconds);
-
-OCTINTERP_API void octave_usleep (unsigned int useconds);
-
-OCTINTERP_API int
-octave_raw_vsnprintf (char *buf, size_t n, const char *fmt, va_list args);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
--- a/src/defun-dld.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/*
-
-Copyright (C) 1994-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#if !defined (octave_defun_dld_h)
-#define octave_defun_dld_h 1
-
-#if defined (octave_defun_h)
-#error defun.h and defun-dld.h both included in same file!
-#endif
-
-#include "defun-int.h"
-
-// Define a builtin function that may be loaded dynamically at run
-// time.
-//
-// If Octave is not configured for dynamic linking of builtin
-// functions, this is the same as DEFUN, except that it will generate
-// an extra externally visible function.
-//
-// The first DECLARE_FUN is for the benefit of the installer function
-// and the second is for the definition of the function.
-
-#if defined (MAKE_BUILTINS)
-
-#define DEFUN_DLD(name, args_name, nargout_name, doc) \
-  DEFUN_DLD_INTERNAL (name, args_name, nargout_name, doc)
-
-// This one can be used when `name' cannot be used directly (if it is
-// already defined as a macro).  In that case, name is already a
-// quoted string, and the internal name of the function must be passed
-// too (the convention is to use a prefix of "F", so "foo" becomes
-// "Ffoo") as well as the name of the generated installer function
-// (the convention is to use a prefix of "G", so "foo" becomes "Gfoo").
-
-#define DEFUNX_DLD(name, fname, gname, args_name, nargout_name, doc) \
-  DEFUNX_DLD_INTERNAL (name, fname, args_name, nargout_name, doc)
-
-#else
-
-#define DEFUN_DLD(name, args_name, nargout_name, doc) \
-  DECLARE_FUN (name, args_name, nargout_name); \
-  DEFINE_FUN_INSTALLER_FUN (name, doc) \
-  DECLARE_FUN (name, args_name, nargout_name)
-
-#define DEFUNX_DLD(name, fname, gname, args_name, nargout_name, doc) \
-  DECLARE_FUNX (fname, args_name, nargout_name); \
-  DEFINE_FUNX_INSTALLER_FUN (name, fname, gname, doc) \
-  DECLARE_FUNX (fname, args_name, nargout_name)
-
-#endif
-
-#endif
--- a/src/defun-int.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,187 +0,0 @@
-/*
-
-Copyright (C) 1994-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#if !defined (octave_defun_int_h)
-#define octave_defun_int_h 1
-
-#include <string>
-
-#include "ov-builtin.h"
-#include "ov-dld-fcn.h"
-#include "symtab.h"
-#include "version.h"
-
-class octave_value;
-
-extern OCTINTERP_API void print_usage (void);
-extern OCTINTERP_API void print_usage (const std::string&);
-
-extern OCTINTERP_API void check_version (const std::string& version, const std::string& fcn);
-
-extern OCTINTERP_API void
-install_builtin_function (octave_builtin::fcn f, const std::string& name,
-                          const std::string& file, const std::string& doc,
-                          bool can_hide_function = true);
-
-extern OCTINTERP_API void
-install_dld_function (octave_dld_function::fcn f, const std::string& name,
-                      const octave_shlib& shl, const std::string& doc,
-                      bool relative = false);
-
-extern OCTINTERP_API void
-install_mex_function (void *fptr, bool fmex, const std::string& name,
-                      const octave_shlib& shl, bool relative = false);
-
-extern OCTINTERP_API void
-alias_builtin (const std::string& alias, const std::string& name);
-
-// Gets the shlib of the currently executing DLD function, if any.
-extern OCTINTERP_API octave_shlib
-get_current_shlib (void);
-
-// This is a convenience class that calls the above function automatically at
-// construction time. When deriving new classes, you can either use it as a field
-// or as a parent (with multiple inheritance).
-
-class octave_auto_shlib : public octave_shlib
-{
-public:
-  octave_auto_shlib (void)
-    : octave_shlib (get_current_shlib ()) { }
-  octave_auto_shlib (const octave_shlib& shl)
-    : octave_shlib (shl) { }
-};
-
-extern OCTINTERP_API bool
-defun_isargout (int, int);
-
-extern OCTINTERP_API void
-defun_isargout (int, int, bool *);
-
-#define DECLARE_FUNX(name, args_name, nargout_name) \
-  OCTAVE_EXPORT octave_value_list \
-  name (const octave_value_list& args_name, int nargout_name)
-
-#define DECLARE_FUN(name, args_name, nargout_name) \
-  DECLARE_FUNX (F ## name, args_name, nargout_name)
-
-// Define the code that will be used to insert the new function into
-// the symbol table.  We look for this name instead of the actual
-// function so that we can easily install the doc std::string too.
-
-typedef bool (*octave_dld_fcn_installer) (const octave_shlib&, bool relative);
-
-typedef octave_function * (*octave_dld_fcn_getter) (const octave_shlib&, bool relative);
-
-#define DEFINE_FUN_INSTALLER_FUN(name, doc) \
-  DEFINE_FUNX_INSTALLER_FUN(#name, F ## name, G ## name, doc)
-
-#define DEFINE_FUNX_INSTALLER_FUN(name, fname, gname, doc) \
-  extern "C" \
-  OCTAVE_EXPORT \
-  octave_function * \
-  gname (const octave_shlib& shl, bool relative) \
-  { \
-    octave_function *retval = 0; \
- \
-    check_version (OCTAVE_API_VERSION, name); \
- \
-    if (! error_state) \
-      { \
-        octave_dld_function *fcn = octave_dld_function::create (fname, shl, name, doc); \
- \
-        if (relative) \
-          fcn->mark_relative (); \
- \
-        retval = fcn; \
-      } \
- \
-    return retval; \
-  }
-
-// MAKE_BUILTINS is defined to extract function names and related
-// information and create the *.df files that are eventually used to
-// create the builtins.cc file.
-
-#if defined (MAKE_BUILTINS)
-
-// Generate code to install name in the symbol table.  The script
-// mkdefs will create a .def file for every .cc file that uses DEFUN,
-// or DEFCMD.
-
-#define DEFUN_INTERNAL(name, args_name, nargout_name, doc) \
-  BEGIN_INSTALL_BUILTIN \
-    XDEFUN_INTERNAL (name, args_name, nargout_name, doc) \
-  END_INSTALL_BUILTIN
-
-#define DEFCONSTFUN_INTERNAL(name, args_name, nargout_name, doc) \
-  BEGIN_INSTALL_BUILTIN \
-    XDEFCONSTFUN_INTERNAL (name, args_name, nargout_name, doc) \
-  END_INSTALL_BUILTIN
-
-#define DEFUNX_INTERNAL(name, fname, args_name, nargout_name, doc) \
-  BEGIN_INSTALL_BUILTIN \
-    XDEFUNX_INTERNAL (name, fname, args_name, nargout_name, doc) \
-  END_INSTALL_BUILTIN
-
-// Generate code to install name in the symbol table.  The script
-// mkdefs will create a .def file for every .cc file that uses
-// DEFUN_DLD.
-
-#define DEFUN_DLD_INTERNAL(name, args_name, nargout_name, doc) \
-  BEGIN_INSTALL_BUILTIN \
-    XDEFUN_DLD_INTERNAL (name, args_name, nargout_name, doc) \
-  END_INSTALL_BUILTIN
-
-#define DEFUNX_DLD_INTERNAL(name, fname, args_name, nargout_name, doc) \
-  BEGIN_INSTALL_BUILTIN \
-    XDEFUNX_DLD_INTERNAL (name, fname, args_name, nargout_name, doc) \
-  END_INSTALL_BUILTIN
-
-// Generate code for making another name for an existing function.
-
-#define DEFALIAS_INTERNAL(alias, name) \
-  BEGIN_INSTALL_BUILTIN \
-    XDEFALIAS_INTERNAL(alias, name) \
-  END_INSTALL_BUILTIN
-
-#else /* ! MAKE_BUILTINS */
-
-// Generate the first line of the function definition.  This ensures
-// that the internal functions all have the same signature.
-
-#define DEFUN_INTERNAL(name, args_name, nargout_name, doc) \
-  DECLARE_FUN (name, args_name, nargout_name)
-
-#define DEFCONSTFUN_INTERNAL(name, args_name, nargout_name, doc) \
-  DECLARE_FUN (name, args_name, nargout_name)
-
-#define DEFUNX_INTERNAL(name, fname, args_name, nargout_name, doc) \
-  DECLARE_FUNX (fname, args_name, nargout_name)
-
-// No definition is required for an alias.
-
-#define DEFALIAS_INTERNAL(alias, name)
-
-#endif /* ! MAKE_BUILTINS */
-
-#endif
--- a/src/display.cc	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,182 +0,0 @@
-/*
-
-Copyright (C) 2009-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <cstdlib>
-
-#if defined (OCTAVE_USE_WINDOWS_API)
-#include <windows.h>
-#elif defined (HAVE_FRAMEWORK_CARBON)
-#include <Carbon/Carbon.h>
-#elif defined (HAVE_X_WINDOWS)
-#include <X11/Xlib.h>
-#endif
-
-#include "singleton-cleanup.h"
-
-#include "display.h"
-#include "error.h"
-
-display_info *display_info::instance = 0;
-
-#if defined (HAVE_FRAMEWORK_CARBON) && ! defined (HAVE_CARBON_CGDISPLAYBITSPERPIXEL)
-// FIXME - This will only work for MacOS > 10.5. For earlier versions
-// this code is not needed (use CGDisplayBitsPerPixel instead).
-size_t DisplayBitsPerPixel (CGDirectDisplayID display)
-{
-  CGDisplayModeRef mode = CGDisplayCopyDisplayMode (display);
-  CFStringRef pixelEncoding = CGDisplayModeCopyPixelEncoding (mode);
-
-  if (CFStringCompare (pixelEncoding, CFSTR (IO32BitDirectPixels), 0) == 0)
-    return 32;
-  else if (CFStringCompare (pixelEncoding, CFSTR (IO16BitDirectPixels), 0) == 0)
-    return 16;
-  else 
-    return 8;
-}
-#endif
-
-void
-display_info::init (bool query)
-{
-  if (query)
-    {
-#if defined (OCTAVE_USE_WINDOWS_API)
-
-      HDC hdc = GetDC (0);
-
-      if (hdc)
-        {
-          dp = GetDeviceCaps (hdc, BITSPIXEL);
-
-          ht = GetDeviceCaps (hdc, VERTRES);
-          wd = GetDeviceCaps (hdc, HORZRES);
-
-          double ht_mm = GetDeviceCaps (hdc, VERTSIZE);
-          double wd_mm = GetDeviceCaps (hdc, HORZSIZE);
-
-          rx = wd * 25.4 / wd_mm;
-          ry = ht * 25.4 / ht_mm;
-        }
-      else
-        warning ("no graphical display found");
-
-#elif defined (HAVE_FRAMEWORK_CARBON)
-
-      CGDirectDisplayID display = CGMainDisplayID ();
-
-      if (display)
-        {
-#  if defined (HAVE_CARBON_CGDISPLAYBITSPERPIXEL)
-          // For MacOS < 10.7 use the line below
-          dp = CGDisplayBitsPerPixel (display);
-#  else
-          // For MacOS > 10.5 use the line below
-          dp = DisplayBitsPerPixel (display);
-#  endif
-
-          ht = CGDisplayPixelsHigh (display);
-          wd = CGDisplayPixelsWide (display);
-
-          CGSize sz_mm = CGDisplayScreenSize (display);
-          // For MacOS >= 10.6, CGSize is a struct keeping 2 CGFloat values,
-          // but the CGFloat typedef is not present on older systems,
-          // so use double instead.
-          double ht_mm = sz_mm.height;
-          double wd_mm = sz_mm.width;
-
-          rx = wd * 25.4 / wd_mm;
-          ry = ht * 25.4 / ht_mm;
-        }
-      else
-        warning ("no graphical display found");
-
-#elif defined (HAVE_X_WINDOWS)
-
-      const char *display_name = getenv ("DISPLAY");
-
-      if (display_name && *display_name)
-        {
-          Display *display = XOpenDisplay (display_name);
-
-          if (display)
-            {
-              Screen *screen = DefaultScreenOfDisplay (display);
-
-              if (screen)
-                {
-                  dp = DefaultDepthOfScreen (screen);
-
-                  ht = HeightOfScreen (screen);
-                  wd = WidthOfScreen (screen);
-
-                  int screen_number = XScreenNumberOfScreen (screen);
-
-                  double ht_mm = DisplayHeightMM (display, screen_number);
-                  double wd_mm = DisplayWidthMM (display, screen_number);
-
-                  rx = wd * 25.4 / wd_mm;
-                  ry = ht * 25.4 / ht_mm;
-                }
-              else
-                warning ("X11 display has no default screen");
-
-              XCloseDisplay (display);
-            }
-          else
-            warning ("unable to open X11 DISPLAY");
-        }
-      else
-        warning ("X11 DISPLAY environment variable not set");
-#else
-
-      warning ("no graphical display found");
-
-#endif
-    }
-}
-
-bool
-display_info::instance_ok (bool query)
-{
-  bool retval = true;
-
-  if (! instance)
-    {
-      instance = new display_info (query);
-
-      if (instance)
-        singleton_cleanup_list::add (cleanup_instance);
-    }
-
-  if (! instance)
-    {
-      ::error ("unable to create display_info object!");
-
-      retval = false;
-    }
-
-  return retval;
-}
--- a/src/display.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,99 +0,0 @@
-/*
-
-Copyright (C) 2009-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#if !defined (octave_display_h)
-#define octave_display_h 1
-
-class Matrix;
-
-class display_info
-{
-protected:
-
-  display_info (bool query = true)
-    : ht (1), wd (1), dp (0), rx (72), ry (72)
-  {
-    init (query);
-  }
-
-public:
-
-  static int height (void)
-  {
-    return instance_ok () ? instance->do_height () : 0;
-  }
-
-  static int width (void)
-  {
-    return instance_ok () ? instance->do_width () : 0;
-  }
-
-  static int depth (void)
-  {
-    return instance_ok () ? instance->do_depth () : 0;
-  }
-
-  static double x_dpi (void)
-  {
-    return instance_ok () ? instance->do_x_dpi () : 0;
-  }
-
-  static double y_dpi (void)
-  {
-    return instance_ok () ? instance->do_y_dpi () : 0;
-  }
-
-  // To disable querying the window system for defaults, this function
-  // must be called before any other display_info function.
-  static void no_window_system (void)
-  {
-    instance_ok (false);
-  }
-
-private:
-
-  static display_info *instance;
-
-  static void cleanup_instance (void) { delete instance; instance = 0; }
-
-  // Height, width, and depth of the display.
-  int ht;
-  int wd;
-  int dp;
-
-  // X- and Y- Resolution of the display in dots (pixels) per inch.
-  double rx;
-  double ry;
-
-  int do_height (void) const { return ht; }
-  int do_width (void) const { return wd; }
-  int do_depth (void) const { return dp; }
-
-  double do_x_dpi (void) const { return rx; }
-  double do_y_dpi (void) const { return ry; }
-
-  void init (bool query = true);
-
-  static bool instance_ok (bool query = true);
-};
-
-#endif
--- a/src/dynamic-ld.cc	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,582 +0,0 @@
-/*
-
-Copyright (C) 1993-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <iostream>
-#include <list>
-
-#include "file-stat.h"
-#include "oct-env.h"
-#include "oct-time.h"
-#include "singleton-cleanup.h"
-
-#include <defaults.h>
-
-#include "defun.h"
-#include "dynamic-ld.h"
-#include "ov-fcn.h"
-#include "ov-dld-fcn.h"
-#include "ov-mex-fcn.h"
-#include "parse.h"
-#include "unwind-prot.h"
-#include "utils.h"
-#include "variables.h"
-
-#define STRINGIFY(s) STRINGIFY1(s)
-#define STRINGIFY1(s) #s
-
-class
-octave_shlib_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);
-
-  static octave_shlib find_file (const std::string& file_name);
-
-  static void display (void);
-
-private:
-
-  octave_shlib_list (void) : lib_list () { }
-
-  ~octave_shlib_list (void) { }
-
-  void do_append (const octave_shlib& shl);
-
-  void do_remove (octave_shlib& shl, octave_shlib::close_hook cl_hook = 0);
-
-  octave_shlib do_find_file (const std::string& file_name) const;
-
-  void do_display (void) const;
-
-  static octave_shlib_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> lib_list;
-
-  // No copying!
-
-  octave_shlib_list (const octave_shlib_list&);
-
-  octave_shlib_list& operator = (const octave_shlib_list&);
-};
-
-octave_shlib_list *octave_shlib_list::instance = 0;
-
-void
-octave_shlib_list::do_append (const octave_shlib& shl)
-{
-  lib_list.push_back (shl);
-}
-
-void
-octave_shlib_list::do_remove (octave_shlib& shl,
-                              octave_shlib::close_hook cl_hook)
-{
-  for (iterator p = lib_list.begin (); p != lib_list.end (); p++)
-    {
-      if (*p == shl)
-        {
-          // Erase first to avoid potentially invalidating the pointer by the
-          // following hooks.
-          lib_list.erase (p);
-
-          shl.close (cl_hook);
-
-          break;
-        }
-    }
-}
-
-octave_shlib
-octave_shlib_list::do_find_file (const std::string& file_name) const
-{
-  octave_shlib retval;
-
-  for (const_iterator p = lib_list.begin (); p != lib_list.end (); p++)
-    {
-      if (p->file_name () == file_name)
-        {
-          retval = *p;
-          break;
-        }
-    }
-
-  return retval;
-}
-
-void
-octave_shlib_list::do_display (void) const
-{
-  std::cerr << "current shared libraries:" << std::endl;
-  for (const_iterator p = lib_list.begin (); p != lib_list.end (); p++)
-    std::cerr << "  " << p->file_name () << std::endl;
-}
-
-bool
-octave_shlib_list::instance_ok (void)
-{
-  bool retval = true;
-
-  if (! instance)
-    {
-      instance = new octave_shlib_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_shlib_list::append (const octave_shlib& shl)
-{
-  if (instance_ok ())
-    instance->do_append (shl);
-}
-
-void
-octave_shlib_list::remove (octave_shlib& shl,
-                           octave_shlib::close_hook cl_hook)
-{
-  if (instance_ok ())
-    instance->do_remove (shl, cl_hook);
-}
-
-octave_shlib
-octave_shlib_list::find_file (const std::string& file_name)
-{
-  return (instance_ok ())
-    ? instance->do_find_file (file_name) : octave_shlib ();
-}
-
-void
-octave_shlib_list::display (void)
-{
-  if (instance_ok ())
-    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;
-
-bool
-octave_dynamic_loader::instance_ok (void)
-{
-  bool retval = true;
-
-  if (! instance)
-    {
-      instance = new octave_dynamic_loader ();
-
-      if (instance)
-        singleton_cleanup_list::add (cleanup_instance);
-    }
-
-  if (! instance)
-    {
-      ::error ("unable to create dynamic loader object!");
-
-      retval = false;
-    }
-
-  return retval;
-}
-
-static void
-do_clear_function (const std::string& fcn_name)
-{
-  warning_with_id ("Octave:reload-forces-clear", "  %s", fcn_name.c_str ());
-
-  symbol_table::clear_dld_function (fcn_name);
-}
-
-static void
-clear (octave_shlib& oct_file)
-{
-  if (oct_file.number_of_functions_loaded () > 1)
-    {
-      warning_with_id ("Octave:reload-forces-clear",
-                       "reloading %s clears the following functions:",
-                       oct_file.file_name ().c_str ());
-
-      octave_shlib_list::remove (oct_file, do_clear_function);
-    }
-  else
-    octave_shlib_list::remove (oct_file, symbol_table::clear_dld_function);
-}
-
-octave_function *
-octave_dynamic_loader::do_load_oct (const std::string& fcn_name,
-                                    const std::string& file_name,
-                                    bool relative)
-{
-  octave_function *retval = 0;
-
-  unwind_protect frame;
-
-  frame.protect_var (octave_dynamic_loader::doing_load);
-
-  doing_load = true;
-
-  octave_shlib oct_file = octave_shlib_list::find_file (file_name);
-
-  if (oct_file && oct_file.is_out_of_date ())
-    clear (oct_file);
-
-  if (! oct_file)
-    {
-      oct_file.open (file_name);
-
-      if (! error_state && oct_file)
-        octave_shlib_list::append (oct_file);
-    }
-
-  if (! error_state)
-    {
-      if (oct_file)
-        {
-          void *function = oct_file.search (fcn_name, name_mangler);
-
-          if (! function)
-            {
-              // FIXME -- can we determine this C mangling scheme
-              // automatically at run time or configure time?
-
-              function = oct_file.search (fcn_name, name_uscore_mangler);
-            }
-
-          if (function)
-            {
-              octave_dld_fcn_getter f
-                = FCN_PTR_CAST (octave_dld_fcn_getter, function);
-
-              retval = f (oct_file, relative);
-
-              if (! retval)
-                ::error ("failed to install .oct file function `%s'",
-                         fcn_name.c_str ());
-            }
-        }
-      else
-        ::error ("%s is not a valid shared library",
-                 file_name.c_str ());
-    }
-
-  return retval;
-}
-
-octave_function *
-octave_dynamic_loader::do_load_mex (const std::string& fcn_name,
-                                    const std::string& file_name,
-                                    bool /*relative*/)
-{
-  octave_function *retval = 0;
-
-  unwind_protect frame;
-
-  frame.protect_var (octave_dynamic_loader::doing_load);
-
-  doing_load = true;
-
-  octave_shlib mex_file = octave_shlib_list::find_file (file_name);
-
-  if (mex_file && mex_file.is_out_of_date ())
-    clear (mex_file);
-
-  if (! mex_file)
-    {
-      mex_file.open (file_name);
-
-      if (! error_state && mex_file)
-        octave_shlib_list::append (mex_file);
-    }
-
-  if (! error_state)
-    {
-      if (mex_file)
-        {
-          void *function = 0;
-
-          bool have_fmex = false;
-
-          octave_mex_file_list::append (mex_file);
-
-          function = mex_file.search (fcn_name, mex_mangler);
-
-          if (! function)
-            {
-              // FIXME -- can we determine this C mangling scheme
-              // automatically at run time or configure time?
-
-              function = mex_file.search (fcn_name, mex_uscore_mangler);
-
-              if (! function)
-                {
-                  function = mex_file.search (fcn_name, mex_f77_mangler);
-
-                  if (function)
-                    have_fmex = true;
-                }
-            }
-
-          if (function)
-            retval = new octave_mex_function (function, have_fmex,
-                                              mex_file, fcn_name);
-          else
-            ::error ("failed to install .mex file function `%s'",
-                     fcn_name.c_str ());
-        }
-      else
-        ::error ("%s is not a valid shared library",
-                 file_name.c_str ());
-    }
-
-  return retval;
-}
-
-bool
-octave_dynamic_loader::do_remove_oct (const std::string& fcn_name,
-                                      octave_shlib& shl)
-{
-  bool retval = false;
-
-  // We don't need to do anything if this is called because we are in
-  // the process of reloading a .oct file that has changed.
-
-  if (! doing_load)
-    {
-      retval = shl.remove (fcn_name);
-
-      if (shl.number_of_functions_loaded () == 0)
-        octave_shlib_list::remove (shl);
-    }
-
-  return retval;
-}
-
-bool
-octave_dynamic_loader::do_remove_mex (const std::string& fcn_name,
-                                      octave_shlib& shl)
-{
-  bool retval = false;
-
-  // We don't need to do anything if this is called because we are in
-  // the process of reloading a .oct file that has changed.
-
-  if (! doing_load)
-    {
-      retval = shl.remove (fcn_name);
-
-      if (shl.number_of_functions_loaded () == 0)
-        octave_mex_file_list::remove (shl);
-    }
-
-  return retval;
-}
-
-octave_function *
-octave_dynamic_loader::load_oct (const std::string& fcn_name,
-                                  const std::string& file_name,
-                                  bool relative)
-{
-  return (instance_ok ())
-    ? instance->do_load_oct (fcn_name, file_name, relative) : 0;
-}
-
-octave_function *
-octave_dynamic_loader::load_mex (const std::string& fcn_name,
-                                  const std::string& file_name,
-                                  bool relative)
-{
-  return (instance_ok ())
-    ? instance->do_load_mex (fcn_name, file_name, relative) : 0;
-}
-
-bool
-octave_dynamic_loader::remove_oct (const std::string& fcn_name,
-                                   octave_shlib& shl)
-{
-  return (instance_ok ()) ? instance->do_remove_oct (fcn_name, shl) : false;
-}
-
-bool
-octave_dynamic_loader::remove_mex (const std::string& fcn_name,
-                                   octave_shlib& shl)
-{
-  return (instance_ok ()) ? instance->do_remove_mex (fcn_name, shl) : false;
-}
-
-std::string
-octave_dynamic_loader::name_mangler (const std::string& name)
-{
-  return "G" + name;
-}
-
-std::string
-octave_dynamic_loader::name_uscore_mangler (const std::string& name)
-{
-  return "_G" + name;
-}
-
-std::string
-octave_dynamic_loader::mex_mangler (const std::string&)
-{
-  return "mexFunction";
-}
-
-std::string
-octave_dynamic_loader::mex_uscore_mangler (const std::string&)
-{
-  return "_mexFunction";
-}
-
-std::string
-octave_dynamic_loader::mex_f77_mangler (const std::string&)
-{
-  return STRINGIFY (F77_FUNC (mexfunction, MEXFUNCTION));
-}
--- a/src/dynamic-ld.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,100 +0,0 @@
-/*
-
-Copyright (C) 1993-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#if !defined (octave_dynamic_ld_h)
-#define octave_dynamic_ld_h 1
-
-#include <string>
-
-#include "oct-shlib.h"
-
-class octave_function;
-
-class
-octave_dynamic_loader
-{
-protected:
-
-  octave_dynamic_loader (void) { }
-
-public:
-
-  virtual ~octave_dynamic_loader (void) { }
-
-  static octave_function *
-  load_oct (const std::string& fcn_name,
-             const std::string& file_name = std::string (),
-             bool relative = false);
-
-  static octave_function *
-  load_mex (const std::string& fcn_name,
-             const std::string& file_name = std::string (),
-             bool relative = false);
-
-  static bool remove_oct (const std::string& fcn_name, octave_shlib& shl);
-
-  static bool remove_mex (const std::string& fcn_name, octave_shlib& shl);
-
-private:
-
-  // No copying!
-
-  octave_dynamic_loader (const octave_dynamic_loader&);
-
-  octave_dynamic_loader& operator = (const octave_dynamic_loader&);
-
-  static octave_dynamic_loader *instance;
-
-  static void cleanup_instance (void) { delete instance; instance = 0; }
-
-  static bool instance_ok (void);
-
-  octave_function *
-  do_load_oct (const std::string& fcn_name,
-                const std::string& file_name = std::string (),
-                bool relative = false);
-
-  octave_function *
-  do_load_mex (const std::string& fcn_name,
-                const std::string& file_name = std::string (),
-                bool relative = false);
-
-  bool do_remove_oct (const std::string& fcn_name, octave_shlib& shl);
-
-  bool do_remove_mex (const std::string& fcn_name, octave_shlib& shl);
-
-  static bool doing_load;
-
-protected:
-
-  static std::string name_mangler (const std::string& name);
-
-  static std::string name_uscore_mangler (const std::string& name);
-
-  static std::string mex_mangler (const std::string& name);
-
-  static std::string mex_uscore_mangler (const std::string& name);
-
-  static std::string mex_f77_mangler (const std::string& name);
-};
-
-#endif
--- a/src/gl-render.cc	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3039 +0,0 @@
-/*
-
-Copyright (C) 2008-2012 Michael Goffioul
-
-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/>.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#if defined (HAVE_OPENGL)
-
-#include <iostream>
-
-#include <lo-mappers.h>
-#include "oct-locbuf.h"
-#include "oct-refcount.h"
-#include "gl-render.h"
-#include "txt-eng.h"
-#include "txt-eng-ft.h"
-
-#define LIGHT_MODE GL_FRONT_AND_BACK
-
-// Win32 API requires the CALLBACK attributes for
-// GLU callback functions. Define it to empty on
-// other platforms.
-#ifndef CALLBACK
-#define CALLBACK
-#endif
-
-static octave_idx_type
-xmin (octave_idx_type x, octave_idx_type y)
-{
-  return x < y ? x : y;
-}
-
-class
-opengl_texture
-{
-protected:
-  class texture_rep
-  {
-  public:
-    texture_rep (void)
-      : id (), w (), h (), tw (), th (), tx (), ty (),
-        valid (false), count (1)
-    { }
-
-    texture_rep (GLuint id_arg, int w_arg, int h_arg, int tw_arg, int th_arg)
-        : id (id_arg), w (w_arg), h (h_arg), tw (tw_arg), th (th_arg),
-          tx (double(w)/tw), ty (double(h)/th), valid (true),
-          count (1) { }
-
-    ~texture_rep (void)
-      {
-        if (valid)
-          glDeleteTextures (1, &id);
-      }
-
-    void bind (int mode) const
-      { if (valid) glBindTexture (mode, id); }
-
-    void tex_coord (double q, double r) const
-      { if (valid) glTexCoord2d (q*tx, r*ty); }
-
-    GLuint id;
-    int w, h;
-    int tw, th;
-    double tx, ty;
-    bool valid;
-    octave_refcount<int> count;
-  };
-
-  texture_rep *rep;
-
-private:
-  opengl_texture (texture_rep *_rep) : rep (_rep) { }
-
-public:
-  opengl_texture (void) : rep (new texture_rep ()) { }
-
-  opengl_texture (const opengl_texture& tx)
-      : rep (tx.rep)
-    {
-      rep->count++;
-    }
-
-  ~opengl_texture (void)
-    {
-      if (--rep->count == 0)
-        delete rep;
-    }
-
-  opengl_texture& operator = (const opengl_texture& tx)
-    {
-      if (--rep->count == 0)
-        delete rep;
-
-      rep = tx.rep;
-      rep->count++;
-
-      return *this;
-    }
-
-  static opengl_texture create (const octave_value& data);
-
-  void bind (int mode = GL_TEXTURE_2D) const
-    { rep->bind (mode); }
-
-  void tex_coord (double q, double r) const
-    { rep->tex_coord (q, r); }
-
-  bool is_valid (void) const
-    { return rep->valid; }
-};
-
-static int
-next_power_of_2 (int n)
-{
-  int m = 1;
-
-  while (m < n && m < INT_MAX)
-    m <<= 1;
-
-  return m;
-}
-
-opengl_texture
-opengl_texture::create (const octave_value& data)
-{
-  opengl_texture retval;
-
-  dim_vector dv (data.dims ());
-
-  // Expect RGB data
-  if (dv.length () == 3 && dv(2) == 3)
-    {
-      // FIXME -- dim_vectors hold octave_idx_type values.  Should we
-      // check for dimensions larger than intmax?
-      int h = dv(0), w = dv(1), tw, th;
-      GLuint id;
-      bool ok = true;
-
-      tw = next_power_of_2 (w);
-      th = next_power_of_2 (w);
-
-      glGenTextures (1, &id);
-      glBindTexture (GL_TEXTURE_2D, id);
-
-      if (data.is_double_type ())
-        {
-          const NDArray xdata = data.array_value ();
-
-          OCTAVE_LOCAL_BUFFER (float, a, (3*tw*th));
-
-          for (int i = 0; i < h; i++)
-            {
-              for (int j = 0, idx = i*tw*3; j < w; j++, idx += 3)
-                {
-                  a[idx]   = xdata(i,j,0);
-                  a[idx+1] = xdata(i,j,1);
-                  a[idx+2] = xdata(i,j,2);
-                }
-            }
-
-          glTexImage2D (GL_TEXTURE_2D, 0, 3, tw, th, 0,
-                        GL_RGB, GL_FLOAT, a);
-        }
-      else if (data.is_uint8_type ())
-        {
-          const uint8NDArray xdata = data.uint8_array_value ();
-
-          OCTAVE_LOCAL_BUFFER (octave_uint8, a, (3*tw*th));
-
-          for (int i = 0; i < h; i++)
-            {
-              for (int j = 0, idx = i*tw*3; j < w; j++, idx += 3)
-                {
-                  a[idx]   = xdata(i,j,0);
-                  a[idx+1] = xdata(i,j,1);
-                  a[idx+2] = xdata(i,j,2);
-                }
-            }
-
-          glTexImage2D (GL_TEXTURE_2D, 0, 3, tw, th, 0,
-                        GL_RGB, GL_UNSIGNED_BYTE, a);
-        }
-      else
-        {
-          ok = false;
-          warning ("opengl_texture::create: invalid texture data type (expected double or uint8)");
-        }
-
-      if (ok)
-        {
-          glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-          glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-
-          if (glGetError () != GL_NO_ERROR)
-            warning ("opengl_texture::create: OpenGL error while generating texture data");
-          else
-            retval = opengl_texture (new texture_rep (id, w, h, tw, th));
-        }
-    }
-  else
-    warning ("opengl_texture::create: invalid texture data size");
-
-  return retval;
-}
-
-class
-opengl_tesselator
-{
-public:
-#if defined (HAVE_FRAMEWORK_OPENGL) && defined (HAVE_GLUTESSCALLBACK_THREEDOTS)
-  typedef GLvoid (CALLBACK *fcn) (...);
-#else
-  typedef void (CALLBACK *fcn) (void);
-#endif
-
-public:
-
-  opengl_tesselator (void) : glu_tess (0), fill () { init (); }
-
-  virtual ~opengl_tesselator (void)
-    { if (glu_tess) gluDeleteTess (glu_tess); }
-
-  void begin_polygon (bool filled = true)
-    {
-      gluTessProperty (glu_tess, GLU_TESS_BOUNDARY_ONLY,
-                       (filled ? GL_FALSE : GL_TRUE));
-      fill = filled;
-      gluTessBeginPolygon (glu_tess, this);
-    }
-
-  void end_polygon (void) const
-    { gluTessEndPolygon (glu_tess); }
-
-  void begin_contour (void) const
-    { gluTessBeginContour (glu_tess); }
-
-  void end_contour (void) const
-    { gluTessEndContour (glu_tess); }
-
-  void add_vertex (double *loc, void *data) const
-    { gluTessVertex (glu_tess, loc, data); }
-
-protected:
-  virtual void begin (GLenum /*type*/) { }
-
-  virtual void end (void) { }
-
-  virtual void vertex (void */*data*/) { }
-
-  virtual void combine (GLdouble /*c*/[3], void */*data*/[4],
-                        GLfloat /*w*/[4], void **/*out_data*/) { }
-
-  virtual void edge_flag (GLboolean /*flag*/) { }
-
-  virtual void error (GLenum err)
-    { ::error ("OpenGL tesselation error (%d)", err); }
-
-  virtual void init (void)
-    {
-      glu_tess = gluNewTess ();
-
-      gluTessCallback (glu_tess, GLU_TESS_BEGIN_DATA,
-                       reinterpret_cast<fcn> (tess_begin));
-      gluTessCallback (glu_tess, GLU_TESS_END_DATA,
-                       reinterpret_cast<fcn> (tess_end));
-      gluTessCallback (glu_tess, GLU_TESS_VERTEX_DATA,
-                       reinterpret_cast<fcn> (tess_vertex));
-      gluTessCallback (glu_tess, GLU_TESS_COMBINE_DATA,
-                       reinterpret_cast<fcn> (tess_combine));
-      gluTessCallback (glu_tess, GLU_TESS_EDGE_FLAG_DATA,
-                       reinterpret_cast<fcn> (tess_edge_flag));
-      gluTessCallback (glu_tess, GLU_TESS_ERROR_DATA,
-                       reinterpret_cast<fcn> (tess_error));
-    }
-
-  bool is_filled (void) const { return fill; }
-
-private:
-  static void CALLBACK tess_begin (GLenum type, void *t)
-    { reinterpret_cast<opengl_tesselator *> (t)->begin (type); }
-
-  static void CALLBACK tess_end (void *t)
-    { reinterpret_cast<opengl_tesselator *> (t)->end (); }
-
-  static void CALLBACK tess_vertex (void *v, void *t)
-    { reinterpret_cast<opengl_tesselator *> (t)->vertex (v); }
-
-  static void CALLBACK tess_combine (GLdouble c[3], void *v[4], GLfloat w[4],
-                                     void **out,  void *t)
-    { reinterpret_cast<opengl_tesselator *> (t)->combine (c, v, w, out); }
-
-  static void CALLBACK tess_edge_flag (GLboolean flag, void *t)
-    { reinterpret_cast<opengl_tesselator *> (t)->edge_flag (flag); }
-
-  static void CALLBACK tess_error (GLenum err, void *t)
-    { reinterpret_cast<opengl_tesselator *> (t)->error (err); }
-
-private:
-
-  // No copying!
-
-  opengl_tesselator (const opengl_tesselator&);
-
-  opengl_tesselator operator = (const opengl_tesselator&);
-
-  GLUtesselator *glu_tess;
-  bool fill;
-};
-
-class
-vertex_data
-{
-public:
-  class vertex_data_rep
-  {
-  public:
-    Matrix coords;
-    Matrix color;
-    Matrix normal;
-    double alpha;
-    float ambient;
-    float diffuse;
-    float specular;
-    float specular_exp;
-
-    // reference counter
-    octave_refcount<int> count;
-
-    vertex_data_rep (void)
-      : coords (), color (), normal (), alpha (),
-        ambient (), diffuse (), specular (), specular_exp (),count (1) { }
-
-    vertex_data_rep (const Matrix& c, const Matrix& col, const Matrix& n,
-                     double a, float as, float ds, float ss, float se)
-        : coords (c), color (col), normal (n), alpha (a),
-          ambient (as), diffuse (ds), specular (ss), specular_exp (se),
-          count (1) { }
-  };
-
-private:
-  vertex_data_rep *rep;
-
-  vertex_data_rep *nil_rep (void) const
-    {
-      static vertex_data_rep *nr = new vertex_data_rep ();
-
-      return nr;
-    }
-
-public:
-  vertex_data (void) : rep (nil_rep ())
-    { rep->count++; }
-
-  vertex_data (const vertex_data& v) : rep (v.rep)
-    { rep->count++; }
-
-  vertex_data (const Matrix& c, const Matrix& col, const Matrix& n,
-               double a, float as, float ds, float ss, float se)
-      : rep (new vertex_data_rep (c, col, n, a, as, ds, ss, se))
-    { }
-
-  vertex_data (vertex_data_rep *new_rep)
-      : rep (new_rep) { }
-
-  ~vertex_data (void)
-    {
-      if (--rep->count == 0)
-        delete rep;
-    }
-
-  vertex_data& operator = (const vertex_data& v)
-    {
-      if (--rep->count == 0)
-        delete rep;
-
-      rep = v.rep;
-      rep->count++;
-
-      return *this;
-    }
-
-  vertex_data_rep *get_rep (void) const { return rep; }
-};
-
-class
-opengl_renderer::patch_tesselator : public opengl_tesselator
-{
-public:
-  patch_tesselator (opengl_renderer *r, int cmode, int lmode, int idx = 0)
-      : opengl_tesselator (), renderer (r),
-        color_mode (cmode), light_mode (lmode), index (idx),
-        first (true), tmp_vdata ()
-  { }
-
-protected:
-  void begin (GLenum type)
-    {
-      //printf ("patch_tesselator::begin (%d)\n", type);
-      first = true;
-
-      if (color_mode == 2 || light_mode == 2)
-        glShadeModel (GL_SMOOTH);
-      else
-        glShadeModel (GL_FLAT);
-
-      if (is_filled ())
-        renderer->set_polygon_offset (true, 1+index);
-
-      glBegin (type);
-    }
-
-  void end (void)
-    {
-      //printf ("patch_tesselator::end\n");
-      glEnd ();
-      renderer->set_polygon_offset (false);
-    }
-
-  void vertex (void *data)
-    {
-      vertex_data::vertex_data_rep *v
-          = reinterpret_cast<vertex_data::vertex_data_rep *> (data);
-      //printf ("patch_tesselator::vertex (%g, %g, %g)\n", v->coords(0), v->coords(1), v->coords(2));
-
-      // FIXME: why did I need to keep the first vertex of the face
-      // in JHandles? I think it's related to the fact that the
-      // tessellation process might re-order the vertices, such that
-      // the first one you get here might not be the first one of the face;
-      // but I can't figure out the actual reason.
-      if (color_mode > 0 && (first || color_mode == 2))
-        {
-          Matrix col = v->color;
-
-          if (col.numel () == 3)
-            {
-              glColor3dv (col.data ());
-              if (light_mode > 0)
-                {
-                  float buf[4] = { 0, 0, 0, 1 };
-
-                  for (int k = 0; k < 3; k++)
-                    buf[k] = (v->ambient * col(k));
-                  glMaterialfv (LIGHT_MODE, GL_AMBIENT, buf);
-
-                  for (int k = 0; k < 3; k++)
-                    buf[k] = (v->diffuse * col(k));
-                  glMaterialfv (LIGHT_MODE, GL_AMBIENT, buf);
-                }
-            }
-        }
-
-      if (light_mode > 0 && (first || light_mode == 2))
-        glNormal3dv (v->normal.data ());
-
-      glVertex3dv (v->coords.data ());
-
-      first = false;
-    }
-
-  void combine (GLdouble xyz[3], void *data[4], GLfloat w[4],
-                void **out_data)
-    {
-      //printf ("patch_tesselator::combine\n");
-
-      vertex_data::vertex_data_rep *v[4];
-      int vmax = 4;
-
-      for (int i = 0; i < 4; i++)
-        {
-          v[i] = reinterpret_cast<vertex_data::vertex_data_rep *> (data[i]);
-
-          if (vmax == 4 && ! v[i])
-            vmax = i;
-        }
-
-      Matrix vv (1, 3, 0.0);
-      Matrix cc;
-      Matrix nn (1, 3, 0.0);
-      double aa = 0.0;
-
-      vv(0) = xyz[0];
-      vv(1) = xyz[1];
-      vv(2) = xyz[2];
-
-      if (v[0]->color.numel ())
-        {
-          cc.resize (1, 3, 0.0);
-          for (int ic = 0; ic < 3; ic++)
-            for (int iv = 0; iv < vmax; iv++)
-              cc(ic) += (w[iv] * v[iv]->color (ic));
-        }
-
-      if (v[0]->normal.numel () > 0)
-        {
-          for (int in = 0; in < 3; in++)
-            for (int iv = 0; iv < vmax; iv++)
-              nn(in) += (w[iv] * v[iv]->normal (in));
-        }
-
-      for (int iv = 0; iv < vmax; iv++)
-        aa += (w[iv] * v[iv]->alpha);
-
-      vertex_data new_v (vv, cc, nn, aa, v[0]->ambient, v[0]->diffuse,
-                         v[0]->specular, v[0]->specular_exp);
-      tmp_vdata.push_back (new_v);
-
-      *out_data = new_v.get_rep ();
-    }
-
-private:
-
-  // No copying!
-
-  patch_tesselator (const patch_tesselator&);
-
-  patch_tesselator& operator = (const patch_tesselator&);
-
-  opengl_renderer *renderer;
-  int color_mode;       // 0: uni,  1: flat, 2: interp
-  int light_mode;       // 0: none, 1: flat, 2: gouraud
-  int index;
-  bool first;
-  std::list<vertex_data> tmp_vdata;
-};
-
-void
-opengl_renderer::draw (const graphics_object& go, bool toplevel)
-{
-  if (! go.valid_object ())
-    return;
-
-  const base_properties& props = go.get_properties ();
-
-  if (! toolkit)
-    toolkit = props.get_toolkit ();
-
-  if (go.isa ("figure"))
-    draw_figure (dynamic_cast<const figure::properties&> (props));
-  else if (go.isa ("axes"))
-    draw_axes (dynamic_cast<const axes::properties&> (props));
-  else if (go.isa ("line"))
-    draw_line (dynamic_cast<const line::properties&> (props));
-  else if (go.isa ("surface"))
-    draw_surface (dynamic_cast<const surface::properties&> (props));
-  else if (go.isa ("patch"))
-    draw_patch (dynamic_cast<const patch::properties&> (props));
-  else if (go.isa ("hggroup"))
-    draw_hggroup (dynamic_cast<const hggroup::properties&> (props));
-  else if (go.isa ("text"))
-    draw_text (dynamic_cast<const text::properties&> (props));
-  else if (go.isa ("image"))
-    draw_image (dynamic_cast<const image::properties&> (props));
-  else if (go.isa ("uimenu") || go.isa ("uicontrol")
-           || go.isa ("uicontextmenu") || go.isa ("uitoolbar")
-           || go.isa ("uipushtool") || go.isa ("uitoggletool"))
-    /* SKIP */;
-  else if (go.isa ("uipanel"))
-    {
-      if (toplevel)
-        draw_uipanel (dynamic_cast<const uipanel::properties&> (props), go);
-    }
-  else
-    {
-      warning ("opengl_renderer: cannot render object of type `%s'",
-               props.graphics_object_name ().c_str ());
-    }
-}
-
-void
-opengl_renderer::draw_figure (const figure::properties& props)
-{
-  // Initialize OpenGL context
-
-  init_gl_context (props.is___enhanced__ (), props.get_color_rgb ());
-
-  // Draw children
-
-  draw (props.get_all_children (), false);
-}
-
-void
-opengl_renderer::draw_uipanel (const uipanel::properties& props,
-                               const graphics_object& go)
-{
-  graphics_object fig = go.get_ancestor ("figure");
-  const figure::properties& figProps =
-    dynamic_cast<const figure::properties&> (fig.get_properties ());
-
-  // Initialize OpenGL context 
-
-  init_gl_context (figProps.is___enhanced__ (),
-                   props.get_backgroundcolor_rgb ());
-
-  // Draw children
-
-  draw (props.get_all_children (), false);
-}
-
-void
-opengl_renderer::init_gl_context (bool enhanced, const Matrix& c)
-{
-  // Initialize OpenGL context
-
-  glEnable (GL_DEPTH_TEST);
-  glDepthFunc (GL_LEQUAL);
-  glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-  glAlphaFunc (GL_GREATER, 0.0f);
-  glEnable (GL_NORMALIZE);
-
-  if (enhanced)
-    {
-      glEnable (GL_BLEND);
-      glEnable (GL_LINE_SMOOTH);
-    }
-  else
-    {
-      glDisable (GL_BLEND);
-      glDisable (GL_LINE_SMOOTH);
-    }
-
-  // Clear background
-
-  if (c.length () >= 3)
-    {
-      glClearColor (c(0), c(1), c(2), 1);
-      glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-    }
-}
-
-void
-opengl_renderer::render_grid (const std::string& gridstyle,
-                              const Matrix& ticks, double lim1, double lim2,
-                              double p1, double p1N, double p2, double p2N,
-                              int xyz, bool is_3D)
-{
-  set_linestyle (gridstyle, true);
-  glBegin (GL_LINES);
-  for (int i = 0; i < ticks.numel (); i++)
-    {
-      double val = ticks(i);
-      if (lim1 <= val && val <= lim2)
-        {
-          if (xyz == 0) // X
-            {
-              glVertex3d (val, p1N, p2);
-              glVertex3d (val, p1, p2);
-              if (is_3D)
-                {
-                  glVertex3d (val, p1, p2N);
-                  glVertex3d (val, p1, p2);
-                }
-            }
-          else if (xyz == 1) // Y
-            {
-              glVertex3d (p1N, val, p2);
-              glVertex3d (p1, val, p2);
-              if (is_3D)
-                {
-                  glVertex3d (p1, val, p2N);
-                  glVertex3d (p1, val, p2);
-                }
-            }
-          else if (xyz == 2) // Z
-            {
-              glVertex3d (p1N, p2, val);
-              glVertex3d (p1, p2, val);
-              glVertex3d (p1, p2N, val);
-              glVertex3d (p1, p2, val);
-            }
-        }
-    }
-  glEnd ();
-  set_linestyle ("-", true);
-}
-
-void
-opengl_renderer::render_tickmarks (const Matrix& ticks,
-                                   double lim1, double lim2,
-                                   double p1, double p1N,
-                                   double p2, double p2N,
-                                   double dx, double dy, double dz,
-                                   int xyz, bool mirror)
-{
-  glBegin (GL_LINES);
-
-  for (int i = 0; i < ticks.numel (); i++)
-    {
-      double val = ticks(i);
-
-      if (lim1 <= val && val <= lim2)
-        {
-          if (xyz == 0) // X
-            {
-              glVertex3d (val, p1, p2);
-              glVertex3d (val, p1+dy, p2+dz);
-              if (mirror)
-                {
-                  glVertex3d (val, p1N, p2N);
-                  glVertex3d (val, p1N-dy, p2N-dz);
-                }
-            }
-          else if (xyz == 1) // Y
-            {
-              glVertex3d (p1, val, p2);
-              glVertex3d (p1+dx, val, p2+dz);
-              if (mirror)
-                {
-                  glVertex3d (p1N, val, p2N);
-                  glVertex3d (p1N-dx, val, p2N-dz);
-                }
-            }
-          else if (xyz == 2) // Z
-            {
-              glVertex3d (p1, p2, val);
-              glVertex3d (p1+dx, p2+dy, val);
-              if (mirror)
-                {
-                  glVertex3d (p1N, p2N, val);
-                  glVertex3d (p1N-dx, p2N-dy, val);
-                }
-            }
-        }
-    }
-
-  glEnd ();
-}
-
-void
-opengl_renderer::render_ticktexts (const Matrix& ticks,
-                                   const string_vector& ticklabels,
-                                   double lim1, double lim2,
-                                   double p1, double p2,
-                                   int xyz, int ha, int va,
-                                   int& wmax, int& hmax)
-{
-  int n = std::min (ticklabels.numel (), ticks.numel ());
-
-  for (int i = 0; i < n; i++)
-    {
-      double val = ticks(i);
-
-      if (lim1 <= val && val <= lim2)
-        {
-          Matrix b;
-          // FIXME: as tick text is transparent, shouldn't be
-          //        drawn after axes object, for correct rendering?
-          if (xyz == 0) // X
-            {
-              b = render_text (ticklabels(i), val, p1, p2, ha, va);
-            }
-          else if (xyz == 1) // Y
-            {
-              b = render_text (ticklabels(i), p1, val, p2, ha, va);
-            }
-          else if (xyz == 2) // Z
-            {
-              b = render_text (ticklabels(i), p1, p2, val, ha, va);
-            }
-
-          wmax = std::max (wmax, static_cast<int> (b(2)));
-          hmax = std::max (hmax, static_cast<int> (b(3)));
-        }
-    }
-}
-
-void
-opengl_renderer::setup_opengl_transformation (const axes::properties& props)
-{
-  // setup OpenGL transformation
-
-  Matrix x_zlim = props.get_transform_zlim ();
-
-  xZ1 = x_zlim(0)-(x_zlim(1)-x_zlim(0))/2;
-  xZ2 = x_zlim(1)+(x_zlim(1)-x_zlim(0))/2;
-
-  Matrix x_mat1 = props.get_opengl_matrix_1 ();
-  Matrix x_mat2 = props.get_opengl_matrix_2 ();
-
-#if defined (HAVE_FRAMEWORK_OPENGL)
-  GLint vw[4];
-#else
-  int vw[4];
-#endif
-
-  glGetIntegerv (GL_VIEWPORT, vw);
-
-  glMatrixMode (GL_MODELVIEW);
-  glLoadIdentity ();
-  glScaled (1, 1, -1);
-  glMultMatrixd (x_mat1.data ());
-  glMatrixMode (GL_PROJECTION);
-  glLoadIdentity ();
-  glOrtho (0, vw[2], vw[3], 0, xZ1, xZ2);
-  glMultMatrixd (x_mat2.data ());
-  glMatrixMode (GL_MODELVIEW);
-
-  glClear (GL_DEPTH_BUFFER_BIT);
-
-  glDisable (GL_LINE_SMOOTH);
-
-  // store axes transformation data
-
-  xform = props.get_transform ();
-}
-
-void
-opengl_renderer::draw_axes_planes (const axes::properties& props)
-{
-  double xPlane = props.get_xPlane ();
-  double yPlane = props.get_yPlane ();
-  double zPlane = props.get_zPlane ();
-  double xPlaneN = props.get_xPlaneN ();
-  double yPlaneN = props.get_yPlaneN ();
-  double zPlaneN = props.get_zPlaneN ();
-
-  // Axes planes
-  Matrix axe_color = props.get_color_rgb ();
-  if (axe_color.numel () > 0 && props.is_visible ())
-    {
-      set_color (axe_color);
-      set_polygon_offset (true, 2.5);
-
-      glBegin (GL_QUADS);
-
-      // X plane
-      glVertex3d (xPlane, yPlaneN, zPlaneN);
-      glVertex3d (xPlane, yPlane, zPlaneN);
-      glVertex3d (xPlane, yPlane, zPlane);
-      glVertex3d (xPlane, yPlaneN, zPlane);
-
-      // Y plane
-      glVertex3d (xPlaneN, yPlane, zPlaneN);
-      glVertex3d (xPlane, yPlane, zPlaneN);
-      glVertex3d (xPlane, yPlane, zPlane);
-      glVertex3d (xPlaneN, yPlane, zPlane);
-
-      // Z plane
-      glVertex3d (xPlaneN, yPlaneN, zPlane);
-      glVertex3d (xPlane, yPlaneN, zPlane);
-      glVertex3d (xPlane, yPlane, zPlane);
-      glVertex3d (xPlaneN, yPlane, zPlane);
-
-      glEnd ();
-
-      set_polygon_offset (false);
-    }
-}
-
-void
-opengl_renderer::draw_axes_boxes (const axes::properties& props)
-{
-  bool xySym = props.get_xySym ();
-  double xPlane = props.get_xPlane ();
-  double yPlane = props.get_yPlane ();
-  double zPlane = props.get_zPlane ();
-  double xPlaneN = props.get_xPlaneN ();
-  double yPlaneN = props.get_yPlaneN ();
-  double zPlaneN = props.get_zPlaneN ();
-  double xpTick = props.get_xpTick ();
-  double ypTick = props.get_ypTick ();
-  double zpTick = props.get_zpTick ();
-  double xpTickN = props.get_xpTickN ();
-  double ypTickN = props.get_ypTickN ();
-  double zpTickN = props.get_zpTickN ();
-
-  bool plotyy = (props.has_property ("__plotyy_axes__"));
-
-  // Axes box
-
-  set_linestyle ("-", true);
-  set_linewidth (props.get_linewidth ());
-
-  if (props.is_visible ())
-    {
-      glBegin (GL_LINES);
-
-      // X box
-      set_color (props.get_xcolor_rgb ());
-      glVertex3d (xPlaneN, ypTick, zpTick);
-      glVertex3d (xPlane, ypTick, zpTick);
-
-      if (props.is_box ())
-        {
-          glVertex3d (xPlaneN, ypTickN, zpTick);
-          glVertex3d (xPlane, ypTickN, zpTick);
-          glVertex3d (xPlaneN, ypTickN, zpTickN);
-          glVertex3d (xPlane, ypTickN, zpTickN);
-          glVertex3d (xPlaneN, ypTick, zpTickN);
-          glVertex3d (xPlane, ypTick, zpTickN);
-        }
-
-      // Y box
-      set_color (props.get_ycolor_rgb ());
-      glVertex3d (xpTick, yPlaneN, zpTick);
-      glVertex3d (xpTick, yPlane, zpTick);
-
-      if (props.is_box () && ! plotyy)
-        {
-          glVertex3d (xpTickN, yPlaneN, zpTick);
-          glVertex3d (xpTickN, yPlane, zpTick);
-          glVertex3d (xpTickN, yPlaneN, zpTickN);
-          glVertex3d (xpTickN, yPlane, zpTickN);
-          glVertex3d (xpTick, yPlaneN, zpTickN);
-          glVertex3d (xpTick, yPlane, zpTickN);
-        }
-
-      // Z box
-      set_color (props.get_zcolor_rgb ());
-
-      if (xySym)
-        {
-          glVertex3d (xPlaneN, yPlane, zPlaneN);
-          glVertex3d (xPlaneN, yPlane, zPlane);
-        }
-      else
-        {
-          glVertex3d (xPlane, yPlaneN, zPlaneN);
-          glVertex3d (xPlane, yPlaneN, zPlane);
-        }
-
-      if (props.is_box ())
-        {
-          glVertex3d (xPlane, yPlane, zPlaneN);
-          glVertex3d (xPlane, yPlane, zPlane);
-
-          if (xySym)
-            {
-              glVertex3d (xPlane, yPlaneN, zPlaneN);
-              glVertex3d (xPlane, yPlaneN, zPlane);
-            }
-          else
-            {
-              glVertex3d (xPlaneN, yPlane, zPlaneN);
-              glVertex3d (xPlaneN, yPlane, zPlane);
-            }
-
-          glVertex3d (xPlaneN, yPlaneN, zPlaneN);
-          glVertex3d (xPlaneN, yPlaneN, zPlane);
-        }
-
-      glEnd ();
-    }
-}
-
-void
-opengl_renderer::draw_axes_x_grid (const axes::properties& props)
-{
-  int xstate = props.get_xstate ();
-  int zstate = props.get_zstate ();
-  bool x2Dtop = props.get_x2Dtop ();
-  bool layer2Dtop = props.get_layer2Dtop ();
-  bool xyzSym = props.get_xyzSym ();
-  bool nearhoriz = props.get_nearhoriz ();
-  double xticklen = props.get_xticklen ();
-  double xtickoffset = props.get_xtickoffset ();
-  double fy = props.get_fy ();
-  double fz = props.get_fz ();
-  double x_min = props.get_x_min ();
-  double x_max = props.get_x_max ();
-  double yPlane = props.get_yPlane ();
-  double yPlaneN = props.get_yPlaneN ();
-  double ypTick = props.get_ypTick ();
-  double ypTickN = props.get_ypTickN ();
-  double zPlane = props.get_zPlane ();
-  double zPlaneN = props.get_zPlaneN ();
-  double zpTick = props.get_zpTick ();
-  double zpTickN = props.get_zpTickN ();
-
-  // X grid
-
-  if (props.is_visible () && xstate != AXE_DEPTH_DIR)
-    {
-      std::string gridstyle = props.get_gridlinestyle ();
-      std::string minorgridstyle = props.get_minorgridlinestyle ();
-      bool do_xgrid = (props.is_xgrid () && (gridstyle != "none"));
-      bool do_xminorgrid = (props.is_xminorgrid () && (minorgridstyle != "none"));
-      bool do_xminortick = props.is_xminortick ();
-      Matrix xticks = xform.xscale (props.get_xtick ().matrix_value ());
-      Matrix xmticks = xform.xscale (props.get_xmtick ().matrix_value ());
-      string_vector xticklabels = props.get_xticklabel ().all_strings ();
-      int wmax = 0, hmax = 0;
-      bool tick_along_z = nearhoriz || xisinf (fy);
-      bool mirror = props.is_box () && xstate != AXE_ANY_DIR;
-
-      set_color (props.get_xcolor_rgb ());
-
-      // grid lines
-      if (do_xgrid)
-        render_grid (gridstyle, xticks, x_min, x_max,
-                     yPlane, yPlaneN, layer2Dtop ? zPlaneN : zPlane,
-                     zPlaneN, 0, (zstate != AXE_DEPTH_DIR));
-
-      // tick marks
-      if (tick_along_z)
-        {
-          render_tickmarks (xticks, x_min, x_max, ypTick, ypTick,
-                            zpTick, zpTickN, 0., 0.,
-                            signum (zpTick-zpTickN)*fz*xticklen,
-                            0, mirror);
-        }
-      else
-        {
-          render_tickmarks (xticks, x_min, x_max, ypTick, ypTickN,
-                            zpTick, zpTick, 0.,
-                            signum (ypTick-ypTickN)*fy*xticklen,
-                            0., 0, mirror);
-        }
-
-      // tick texts
-      if (xticklabels.numel () > 0)
-        {
-          int halign = (xstate == AXE_HORZ_DIR ? 1 : (xyzSym ? 0 : 2));
-          int valign = (xstate == AXE_VERT_DIR ? 1 : (x2Dtop ? 0 : 2));
-
-          if (tick_along_z)
-            render_ticktexts (xticks, xticklabels, x_min, x_max, ypTick,
-                              zpTick+signum (zpTick-zpTickN)*fz*xtickoffset,
-                              0, halign, valign, wmax, hmax);
-          else
-            render_ticktexts (xticks, xticklabels, x_min, x_max,
-                              ypTick+signum (ypTick-ypTickN)*fy*xtickoffset,
-                              zpTick, 0, halign, valign, wmax, hmax);
-        }
-
-      // minor grid lines
-      if (do_xminorgrid)
-        render_grid (minorgridstyle, xmticks, x_min, x_max,
-                     yPlane, yPlaneN, layer2Dtop ? zPlaneN : zPlane,
-                     zPlaneN, 0, (zstate != AXE_DEPTH_DIR));
-
-      // minor tick marks
-      if (do_xminortick)
-        {
-          if (tick_along_z)
-            render_tickmarks (xmticks, x_min, x_max, ypTick, ypTick,
-                              zpTick, zpTickN, 0., 0.,
-                              signum (zpTick-zpTickN)*fz*xticklen/2,
-                              0, mirror);
-          else
-            render_tickmarks (xmticks, x_min, x_max, ypTick, ypTickN,
-                              zpTick, zpTick, 0.,
-                              signum (ypTick-ypTickN)*fy*xticklen/2,
-                              0., 0, mirror);
-        }
-
-      gh_manager::get_object (props.get_xlabel ()).set ("visible", "on");
-    }
-  else
-    gh_manager::get_object (props.get_xlabel ()).set ("visible", "off");
-}
-
-void
-opengl_renderer::draw_axes_y_grid (const axes::properties& props)
-{
-  int ystate = props.get_ystate ();
-  int zstate = props.get_zstate ();
-  bool y2Dright = props.get_y2Dright ();
-  bool layer2Dtop = props.get_layer2Dtop ();
-  bool xyzSym = props.get_xyzSym ();
-  bool nearhoriz = props.get_nearhoriz ();
-  double yticklen = props.get_yticklen ();
-  double ytickoffset = props.get_ytickoffset ();
-  double fx = props.get_fx ();
-  double fz = props.get_fz ();
-  double xPlane = props.get_xPlane ();
-  double xPlaneN = props.get_xPlaneN ();
-  double xpTick = props.get_xpTick ();
-  double xpTickN = props.get_xpTickN ();
-  double y_min = props.get_y_min ();
-  double y_max = props.get_y_max ();
-  double zPlane = props.get_zPlane ();
-  double zPlaneN = props.get_zPlaneN ();
-  double zpTick = props.get_zpTick ();
-  double zpTickN = props.get_zpTickN ();
-
-  // Y grid
-
-  if (ystate != AXE_DEPTH_DIR && props.is_visible ())
-    {
-      std::string gridstyle = props.get_gridlinestyle ();
-      std::string minorgridstyle = props.get_minorgridlinestyle ();
-      bool do_ygrid = (props.is_ygrid () && (gridstyle != "none"));
-      bool do_yminorgrid = (props.is_yminorgrid () && (minorgridstyle != "none"));
-      bool do_yminortick = props.is_yminortick ();
-      Matrix yticks = xform.yscale (props.get_ytick ().matrix_value ());
-      Matrix ymticks = xform.yscale (props.get_ymtick ().matrix_value ());
-      string_vector yticklabels = props.get_yticklabel ().all_strings ();
-      int wmax = 0, hmax = 0;
-      bool tick_along_z = nearhoriz || xisinf (fx);
-      bool mirror = props.is_box () && ystate != AXE_ANY_DIR
-                    && (! props.has_property ("__plotyy_axes__"));
-
-      set_color (props.get_ycolor_rgb ());
-
-      // grid lines
-      if (do_ygrid)
-        render_grid (gridstyle, yticks, y_min, y_max,
-                     xPlane, xPlaneN, layer2Dtop ? zPlaneN : zPlane,
-                     zPlaneN, 1, (zstate != AXE_DEPTH_DIR));
-
-      // tick marks
-      if (tick_along_z)
-        render_tickmarks (yticks, y_min, y_max, xpTick, xpTick,
-                          zpTick, zpTickN, 0., 0.,
-                          signum (zpTick-zpTickN)*fz*yticklen,
-                          1, mirror);
-      else
-        render_tickmarks (yticks, y_min, y_max, xpTick, xpTickN,
-                          zpTick, zpTick,
-                          signum (xPlaneN-xPlane)*fx*yticklen,
-                          0., 0., 1, mirror);
-
-      // tick texts
-      if (yticklabels.numel () > 0)
-        {
-          int halign = (ystate == AXE_HORZ_DIR
-                        ? 1 : (!xyzSym || y2Dright ? 0 : 2));
-          int valign = (ystate == AXE_VERT_DIR ? 1 : 2);
-
-          if (tick_along_z)
-            render_ticktexts (yticks, yticklabels, y_min, y_max, xpTick,
-                              zpTick+signum (zpTick-zpTickN)*fz*ytickoffset,
-                              1, halign, valign, wmax, hmax);
-          else
-            render_ticktexts (yticks, yticklabels, y_min, y_max,
-                              xpTick+signum (xpTick-xpTickN)*fx*ytickoffset,
-                              zpTick, 1, halign, valign, wmax, hmax);
-        }
-
-      // minor grid lines
-      if (do_yminorgrid)
-        render_grid (minorgridstyle, ymticks, y_min, y_max,
-                     xPlane, xPlaneN, layer2Dtop ? zPlaneN : zPlane,
-                     zPlaneN, 1, (zstate != AXE_DEPTH_DIR));
-
-      // minor tick marks
-      if (do_yminortick)
-        {
-          if (tick_along_z)
-            render_tickmarks (ymticks, y_min, y_max, xpTick, xpTick,
-                              zpTick, zpTickN, 0., 0.,
-                              signum (zpTick-zpTickN)*fz*yticklen/2,
-                              1, mirror);
-          else
-            render_tickmarks (ymticks, y_min, y_max, xpTick, xpTickN,
-                              zpTick, zpTick,
-                              signum (xpTick-xpTickN)*fx*yticklen/2,
-                              0., 0., 1, mirror);
-        }
-
-      gh_manager::get_object (props.get_ylabel ()).set ("visible", "on");
-    }
-  else
-    gh_manager::get_object (props.get_ylabel ()).set ("visible", "off");
-}
-
-void
-opengl_renderer::draw_axes_z_grid (const axes::properties& props)
-{
-  int zstate = props.get_zstate ();
-  bool xySym = props.get_xySym ();
-  bool zSign = props.get_zSign ();
-  double zticklen = props.get_zticklen ();
-  double ztickoffset = props.get_ztickoffset ();
-  double fx = props.get_fx ();
-  double fy = props.get_fy ();
-  double xPlane = props.get_xPlane ();
-  double xPlaneN = props.get_xPlaneN ();
-  double yPlane = props.get_yPlane ();
-  double yPlaneN = props.get_yPlaneN ();
-  double z_min = props.get_z_min ();
-  double z_max = props.get_z_max ();
-
-  // Z Grid
-
-  if (zstate != AXE_DEPTH_DIR && props.is_visible ())
-    {
-      std::string gridstyle = props.get_gridlinestyle ();
-      std::string minorgridstyle = props.get_minorgridlinestyle ();
-      bool do_zgrid = (props.is_zgrid () && (gridstyle != "none"));
-      bool do_zminorgrid = (props.is_zminorgrid () && (minorgridstyle != "none"));
-      bool do_zminortick = props.is_zminortick ();
-      Matrix zticks = xform.zscale (props.get_ztick ().matrix_value ());
-      Matrix zmticks = xform.zscale (props.get_zmtick ().matrix_value ());
-      string_vector zticklabels = props.get_zticklabel ().all_strings ();
-      int wmax = 0, hmax = 0;
-      bool mirror = props.is_box () && zstate != AXE_ANY_DIR;
-
-      set_color (props.get_zcolor_rgb ());
-
-      // grid lines
-      if (do_zgrid)
-        render_grid (gridstyle, zticks, z_min, z_max,
-                     xPlane, xPlaneN, yPlane, yPlaneN, 2, true);
-
-      // tick marks
-      if (xySym)
-        {
-          if (xisinf (fy))
-            render_tickmarks (zticks, z_min, z_max, xPlaneN, xPlane,
-                              yPlane, yPlane,
-                              signum (xPlaneN-xPlane)*fx*zticklen,
-                              0., 0., 2, mirror);
-          else
-            render_tickmarks (zticks, z_min, z_max, xPlaneN, xPlaneN,
-                              yPlane, yPlane, 0.,
-                              signum (yPlane-yPlaneN)*fy*zticklen,
-                              0., 2, false);
-        }
-      else
-        {
-          if (xisinf (fx))
-            render_tickmarks (zticks, z_min, z_max, xPlaneN, xPlane,
-                              yPlaneN, yPlane, 0.,
-                              signum (yPlaneN-yPlane)*fy*zticklen,
-                              0., 2, mirror);
-          else
-            render_tickmarks (zticks, z_min, z_max, xPlane, xPlane,
-                              yPlaneN, yPlane,
-                              signum (xPlane-xPlaneN)*fx*zticklen,
-                              0., 0., 2, false);
-        }
-
-      // FIXME: tick texts
-      if (zticklabels.numel () > 0)
-        {
-          int halign = 2;
-          int valign = (zstate == AXE_VERT_DIR ? 1 : (zSign ? 3 : 2));
-
-          if (xySym)
-            {
-              if (xisinf (fy))
-                render_ticktexts (zticks, zticklabels, z_min, z_max,
-                                  xPlaneN+signum (xPlaneN-xPlane)*fx*ztickoffset,
-                                  yPlane, 2, halign, valign, wmax, hmax);
-              else
-                render_ticktexts (zticks, zticklabels, z_min, z_max, xPlaneN,
-                                  yPlane+signum (yPlane-yPlaneN)*fy*ztickoffset,
-                                  2, halign, valign, wmax, hmax);
-            }
-          else
-            {
-              if (xisinf (fx))
-                render_ticktexts (zticks, zticklabels, z_min, z_max, xPlane,
-                                  yPlaneN+signum (yPlaneN-yPlane)*fy*ztickoffset,
-                                  2, halign, valign, wmax, hmax);
-              else
-                render_ticktexts (zticks, zticklabels, z_min, z_max,
-                                  xPlane+signum (xPlane-xPlaneN)*fx*ztickoffset,
-                                  yPlaneN, 2, halign, valign, wmax, hmax);
-            }
-        }
-
-      // minor grid lines
-      if (do_zminorgrid)
-        render_grid (minorgridstyle, zmticks, z_min, z_max,
-                     xPlane, xPlaneN, yPlane, yPlaneN, 2, true);
-
-      // minor tick marks
-      if (do_zminortick)
-        {
-          if (xySym)
-            {
-              if (xisinf (fy))
-                render_tickmarks (zmticks, z_min, z_max, xPlaneN, xPlane,
-                                  yPlane, yPlane,
-                                  signum (xPlaneN-xPlane)*fx*zticklen/2,
-                                  0., 0., 2, mirror);
-              else
-                render_tickmarks (zmticks, z_min, z_max, xPlaneN, xPlaneN,
-                                  yPlane, yPlane, 0.,
-                                  signum (yPlane-yPlaneN)*fy*zticklen/2,
-                                  0., 2, false);
-            }
-          else
-            {
-              if (xisinf (fx))
-                render_tickmarks (zmticks, z_min, z_max, xPlane, xPlane,
-                                  yPlaneN, yPlane, 0.,
-                                  signum (yPlaneN-yPlane)*fy*zticklen/2,
-                                  0., 2, mirror);
-              else
-                render_tickmarks (zmticks, z_min, z_max, xPlane, xPlane,
-                                  yPlaneN, yPlaneN,
-                                  signum (xPlane-xPlaneN)*fx*zticklen/2,
-                                  0., 0., 2, false);
-            }
-        }
-
-      gh_manager::get_object (props.get_zlabel ()).set ("visible", "on");
-    }
-  else
-    gh_manager::get_object (props.get_zlabel ()).set ("visible", "off");
-}
-
-void
-opengl_renderer::draw_axes_children (const axes::properties& props)
-{
-  // Children
-
-  GLboolean antialias;
-  glGetBooleanv (GL_LINE_SMOOTH, &antialias);
-
-  if (antialias == GL_TRUE)
-    glEnable (GL_LINE_SMOOTH);
-
-  Matrix children = props.get_all_children ();
-  std::list<graphics_object> obj_list;
-  std::list<graphics_object>::iterator it;
-
-  // 1st pass: draw light objects
-
-  // Start with the last element of the array of child objects to
-  // display them in the oder they were added to the array.
-
-  for (octave_idx_type i = children.numel () - 1; i >= 0; i--)
-    {
-      graphics_object go = gh_manager::get_object (children (i));
-
-      if (go.get_properties ().is_visible ())
-        {
-          if (go.isa ("light"))
-            draw (go);
-          else
-            obj_list.push_back (go);
-        }
-    }
-
-  // 2nd pass: draw other objects (with units set to "data")
-
-  it = obj_list.begin ();
-  while (it != obj_list.end ())
-    {
-      graphics_object go = (*it);
-
-      // FIXME: check whether object has "units" property and it is set
-      // to "data"
-      if (! go.isa ("text") || go.get ("units").string_value () == "data")
-        {
-          set_clipping (go.get_properties ().is_clipping ());
-          draw (go);
-
-          it = obj_list.erase (it);
-        }
-      else
-        it++;
-    }
-
-  // 3rd pass: draw remaining objects
-
-  glDisable (GL_DEPTH_TEST);
-
-  for (it = obj_list.begin (); it != obj_list.end (); it++)
-    {
-      graphics_object go = (*it);
-
-      set_clipping (go.get_properties ().is_clipping ());
-      draw (go);
-    }
-
-  glEnable (GL_DEPTH_TEST);
-
-  set_clipping (false);
-
-  // FIXME: finalize rendering (transparency processing)
-  // FIXME: draw zoom box, if needed
-}
-
-void
-opengl_renderer::draw_axes (const axes::properties& props)
-{
-  double x_min = props.get_x_min ();
-  double x_max = props.get_x_max ();
-  double y_min = props.get_y_min ();
-  double y_max = props.get_y_max ();
-  double z_min = props.get_z_min ();
-  double z_max = props.get_z_max ();
-
-  setup_opengl_transformation (props);
-
-  // draw axes object
-
-  draw_axes_planes (props);
-  draw_axes_boxes (props);
-
-  set_font (props);
-
-  draw_axes_x_grid (props);
-  draw_axes_y_grid (props);
-  draw_axes_z_grid (props);
-
-  set_linestyle ("-");
-
-  set_clipbox (x_min, x_max, y_min, y_max, z_min, z_max);
-
-  draw_axes_children (props);
-}
-
-void
-opengl_renderer::draw_line (const line::properties& props)
-{
-  Matrix x = xform.xscale (props.get_xdata ().matrix_value ());
-  Matrix y = xform.yscale (props.get_ydata ().matrix_value ());
-  Matrix z = xform.zscale (props.get_zdata ().matrix_value ());
-
-  bool has_z = (z.numel () > 0);
-  int n = static_cast<int> (::xmin (::xmin (x.numel (), y.numel ()), (has_z ? z.numel () : INT_MAX)));
-  octave_uint8 clip_mask = (props.is_clipping () ? 0x7F : 0x40), clip_ok (0x40);
-
-  std::vector<octave_uint8> clip (n);
-
-  if (has_z)
-    for (int i = 0; i < n; i++)
-      clip[i] = (clip_code (x(i), y(i), z(i)) & clip_mask);
-  else
-    {
-      double z_mid = (zmin+zmax)/2;
-
-      for (int i = 0; i < n; i++)
-        clip[i] = (clip_code (x(i), y(i), z_mid) & clip_mask);
-    }
-
-  if (! props.linestyle_is ("none"))
-    {
-      set_color (props.get_color_rgb ());
-      set_linestyle (props.get_linestyle (), false);
-      set_linewidth (props.get_linewidth ());
-
-      if (has_z)
-        {
-          bool flag = false;
-
-          for (int i = 1; i < n; i++)
-            {
-              if ((clip[i-1] & clip[i]) == clip_ok)
-                {
-                  if (! flag)
-                    {
-                      flag = true;
-                      glBegin (GL_LINE_STRIP);
-                      glVertex3d (x(i-1), y(i-1), z(i-1));
-                    }
-                  glVertex3d (x(i), y(i), z(i));
-                }
-              else if (flag)
-                {
-                  flag = false;
-                  glEnd ();
-                }
-            }
-
-          if (flag)
-            glEnd ();
-        }
-      else
-        {
-          bool flag = false;
-
-          for (int i = 1; i < n; i++)
-            {
-              if ((clip[i-1] & clip[i]) == clip_ok)
-                {
-                  if (! flag)
-                    {
-                      flag = true;
-                      glBegin (GL_LINE_STRIP);
-                      glVertex2d (x(i-1), y(i-1));
-                    }
-                  glVertex2d (x(i), y(i));
-                }
-              else if (flag)
-                {
-                  flag = false;
-                  glEnd ();
-                }
-            }
-
-          if (flag)
-            glEnd ();
-        }
-
-      set_linewidth (0.5);
-      set_linestyle ("-");
-    }
-
-  set_clipping (false);
-
-  if (! props.marker_is ("none") &&
-      ! (props.markeredgecolor_is ("none")
-         && props.markerfacecolor_is ("none")))
-    {
-      Matrix lc, fc;
-
-      if (props.markeredgecolor_is ("auto"))
-        lc = props.get_color_rgb ();
-      else if (! props.markeredgecolor_is ("none"))
-        lc = props.get_markeredgecolor_rgb ();
-
-      if (props.markerfacecolor_is ("auto"))
-        fc = props.get_color_rgb ();
-      else if (! props.markerfacecolor_is ("none"))
-        fc = props.get_markerfacecolor_rgb ();
-
-      init_marker (props.get_marker (), props.get_markersize (),
-                   props.get_linewidth ());
-
-      for (int i = 0; i < n; i++)
-        {
-          if (clip[i] == clip_ok)
-            draw_marker (x(i), y(i),
-                         has_z ? z(i) : static_cast<double> (i) / n,
-                         lc, fc);
-        }
-
-      end_marker ();
-    }
-
-  set_clipping (props.is_clipping ());
-}
-
-void
-opengl_renderer::draw_surface (const surface::properties& props)
-{
-  const Matrix x = xform.xscale (props.get_xdata ().matrix_value ());
-  const Matrix y = xform.yscale (props.get_ydata ().matrix_value ());
-  const Matrix z = xform.zscale (props.get_zdata ().matrix_value ());
-
-  int zr = z.rows (), zc = z.columns ();
-
-  NDArray c;
-  const NDArray n = props.get_vertexnormals ().array_value ();
-
-  // FIXME: handle transparency
-  Matrix a;
-
-  if (props.facelighting_is ("phong") || props.edgelighting_is ("phong"))
-    warning ("opengl_renderer::draw: phong light model not supported");
-
-  int fc_mode = (props.facecolor_is_rgb () ? 0 :
-                 (props.facecolor_is ("flat") ? 1 :
-                  (props.facecolor_is ("interp") ? 2 :
-                   (props.facecolor_is ("texturemap") ? 3 : -1))));
-  int fl_mode = (props.facelighting_is ("none") ? 0 :
-                 (props.facelighting_is ("flat") ? 1 : 2));
-  int fa_mode = (props.facealpha_is_double () ? 0 :
-                 (props.facealpha_is ("flat") ? 1 : 2));
-  int ec_mode = (props.edgecolor_is_rgb () ? 0 :
-                 (props.edgecolor_is ("flat") ? 1 :
-                  (props.edgecolor_is ("interp") ? 2 : -1)));
-  int el_mode = (props.edgelighting_is ("none") ? 0 :
-                 (props.edgelighting_is ("flat") ? 1 : 2));
-  int ea_mode = (props.edgealpha_is_double () ? 0 :
-                 (props.edgealpha_is ("flat") ? 1 : 2));
-
-  Matrix fcolor = (fc_mode == 3 ? Matrix (1, 3, 1.0) : props.get_facecolor_rgb ());
-  Matrix ecolor = props.get_edgecolor_rgb ();
-
-  float as = props.get_ambientstrength ();
-  float ds = props.get_diffusestrength ();
-  float ss = props.get_specularstrength ();
-  float se = props.get_specularexponent ();
-  float cb[4] = { 0.0, 0.0, 0.0, 1.0 };
-  double d = 1.0;
-
-  opengl_texture tex;
-
-  int i1, i2, j1, j2;
-  bool x_mat = (x.rows () == z.rows ());
-  bool y_mat = (y.columns () == z.columns ());
-
-  i1 = i2 = j1 = j2 = 0;
-
-  boolMatrix clip (z.dims (), false);
-
-  for (int i = 0; i < zr; i++)
-    {
-      if (x_mat)
-        i1 = i;
-
-      for (int j = 0; j < zc; j++)
-        {
-          if (y_mat)
-            j1 = j;
-
-          clip(i,j) = is_nan_or_inf (x(i1,j), y(i,j1), z(i,j));
-        }
-    }
-
-  if ((fc_mode > 0 && fc_mode < 3) || ec_mode > 0)
-    c = props.get_color_data ().array_value ();
-
-  if (fa_mode > 0 || ea_mode > 0)
-    {
-      // FIXME: implement alphadata conversion
-      //a = props.get_alpha_data ();
-    }
-
-  if (fl_mode > 0 || el_mode > 0)
-    {
-      float buf[4] = { ss, ss, ss, 1 };
-
-      glMaterialfv (LIGHT_MODE, GL_SPECULAR, buf);
-      glMaterialf (LIGHT_MODE, GL_SHININESS, se);
-    }
-
-  // FIXME: good candidate for caching, transfering pixel
-  // data to OpenGL is time consuming.
-  if (fc_mode == 3)
-    tex = opengl_texture::create (props.get_color_data ());
-
-  if (! props.facecolor_is ("none"))
-    {
-      if (props.get_facealpha_double () == 1)
-        {
-          if (fc_mode == 0 || fc_mode == 3)
-            {
-              glColor3dv (fcolor.data ());
-              if (fl_mode > 0)
-                {
-                  for (int i = 0; i < 3; i++)
-                    cb[i] = as * fcolor(i);
-                  glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
-
-                  for (int i = 0; i < 3; i++)
-                    cb[i] = ds * fcolor(i);
-                  glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
-                }
-            }
-
-          if (fl_mode > 0)
-            glEnable (GL_LIGHTING);
-          glShadeModel ((fc_mode == 2 || fl_mode == 2) ? GL_SMOOTH : GL_FLAT);
-          set_polygon_offset (true, 1);
-          if (fc_mode == 3)
-            glEnable (GL_TEXTURE_2D);
-
-          for (int i = 1; i < zc; i++)
-            {
-              if (y_mat)
-                {
-                  i1 = i-1;
-                  i2 = i;
-                }
-
-              for (int j = 1; j < zr; j++)
-                {
-                  if (clip(j-1, i-1) || clip (j, i-1)
-                      || clip (j-1, i) || clip (j, i))
-                    continue;
-
-                  if (x_mat)
-                    {
-                      j1 = j-1;
-                      j2 = j;
-                    }
-
-                  glBegin (GL_QUADS);
-
-                  // Vertex 1
-                  if (fc_mode == 3)
-                    tex.tex_coord (double (i-1) / (zc-1), double (j-1) / (zr-1));
-                  else if (fc_mode > 0)
-                    {
-                      // FIXME: is there a smarter way to do this?
-                      for (int k = 0; k < 3; k++)
-                        cb[k] = c(j-1, i-1, k);
-                      glColor3fv (cb);
-
-                      if (fl_mode > 0)
-                        {
-                          for (int k = 0; k < 3; k++)
-                            cb[k] *= as;
-                          glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
-
-                          for (int k = 0; k < 3; k++)
-                            cb[k] = ds * c(j-1, i-1, k);
-                          glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
-                        }
-                    }
-                  if (fl_mode > 0)
-                    {
-                      d = sqrt (n(j-1,i-1,0) * n(j-1,i-1,0)
-                                + n(j-1,i-1,1) * n(j-1,i-1,1)
-                                + n(j-1,i-1,2) * n(j-1,i-1,2));
-                      glNormal3d (n(j-1,i-1,0)/d, n(j-1,i-1,1)/d, n(j-1,i-1,2)/d);
-                    }
-                  glVertex3d (x(j1,i-1), y(j-1,i1), z(j-1,i-1));
-
-                  // Vertex 2
-                  if (fc_mode == 3)
-                    tex.tex_coord (double (i) / (zc-1), double (j-1) / (zr-1));
-                  else if (fc_mode == 2)
-                    {
-                      for (int k = 0; k < 3; k++)
-                        cb[k] = c(j-1, i, k);
-                      glColor3fv (cb);
-
-                      if (fl_mode > 0)
-                        {
-                          for (int k = 0; k < 3; k++)
-                            cb[k] *= as;
-                          glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
-
-                          for (int k = 0; k < 3; k++)
-                            cb[k] = ds * c(j-1, i, k);
-                          glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
-                        }
-                    }
-
-                  if (fl_mode == 2)
-                    {
-                      d = sqrt (n(j-1,i,0) * n(j-1,i,0)
-                                + n(j-1,i,1) * n(j-1,i,1)
-                                + n(j-1,i,2) * n(j-1,i,2));
-                      glNormal3d (n(j-1,i,0)/d, n(j-1,i,1)/d, n(j-1,i,2)/d);
-                    }
-
-                  glVertex3d (x(j1,i), y(j-1,i2), z(j-1,i));
-
-                  // Vertex 3
-                  if (fc_mode == 3)
-                    tex.tex_coord (double (i) / (zc-1), double (j) / (zr-1));
-                  else if (fc_mode == 2)
-                    {
-                      for (int k = 0; k < 3; k++)
-                        cb[k] = c(j, i, k);
-                      glColor3fv (cb);
-
-                      if (fl_mode > 0)
-                        {
-                          for (int k = 0; k < 3; k++)
-                            cb[k] *= as;
-                          glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
-
-                          for (int k = 0; k < 3; k++)
-                            cb[k] = ds * c(j, i, k);
-                          glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
-                        }
-                    }
-                  if (fl_mode == 2)
-                    {
-                      d = sqrt (n(j,i,0) * n(j,i,0)
-                                + n(j,i,1) * n(j,i,1)
-                                + n(j,i,2) * n(j,i,2));
-                      glNormal3d (n(j,i,0)/d, n(j,i,1)/d, n(j,i,2)/d);
-                    }
-                  glVertex3d (x(j2,i), y(j,i2), z(j,i));
-
-                  // Vertex 4
-                  if (fc_mode == 3)
-                    tex.tex_coord (double (i-1) / (zc-1), double (j) / (zr-1));
-                  else if (fc_mode == 2)
-                    {
-                      for (int k = 0; k < 3; k++)
-                        cb[k] = c(j, i-1, k);
-                      glColor3fv (cb);
-
-                      if (fl_mode > 0)
-                        {
-                          for (int k = 0; k < 3; k++)
-                            cb[k] *= as;
-                          glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
-
-                          for (int k = 0; k < 3; k++)
-                            cb[k] = ds * c(j, i-1, k);
-                          glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
-                        }
-                    }
-                  if (fl_mode == 2)
-                    {
-                      d = sqrt (n(j,i-1,0) * n(j,i-1,0)
-                                + n(j,i-1,1) * n(j,i-1,1)
-                                + n(j,i-1,2) * n(j,i-1,2));
-                      glNormal3d (n(j,i-1,0)/d, n(j,i-1,1)/d, n(j,i-1,2)/d);
-                    }
-                  glVertex3d (x(j2,i-1), y(j,i1), z(j,i-1));
-
-                  glEnd ();
-                }
-            }
-
-          set_polygon_offset (false);
-          if (fc_mode == 3)
-            glDisable (GL_TEXTURE_2D);
-
-          if (fl_mode > 0)
-            glDisable (GL_LIGHTING);
-        }
-      else
-        {
-          // FIXME: implement transparency
-        }
-    }
-
-  if (! props.edgecolor_is ("none"))
-    {
-      if (props.get_edgealpha_double () == 1)
-        {
-          if (ec_mode == 0)
-            {
-              glColor3dv (ecolor.data ());
-              if (fl_mode > 0)
-                {
-                  for (int i = 0; i < 3; i++)
-                    cb[i] = as * ecolor(i);
-                  glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
-
-                  for (int i = 0; i < 3; i++)
-                    cb[i] = ds * ecolor(i);
-                  glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
-                }
-            }
-
-          if (el_mode > 0)
-            glEnable (GL_LIGHTING);
-          glShadeModel ((ec_mode == 2 || el_mode == 2) ? GL_SMOOTH : GL_FLAT);
-
-          set_linestyle (props.get_linestyle (), false);
-          set_linewidth (props.get_linewidth ());
-
-          // Mesh along Y-axis
-
-          if (props.meshstyle_is ("both") || props.meshstyle_is ("column"))
-            {
-              for (int i = 0; i < zc; i++)
-                {
-                  if (y_mat)
-                    {
-                      i1 = i-1;
-                      i2 = i;
-                    }
-
-                  for (int j = 1; j < zr; j++)
-                    {
-                      if (clip(j-1,i) || clip(j,i))
-                        continue;
-
-                      if (x_mat)
-                        {
-                          j1 = j-1;
-                          j2 = j;
-                        }
-
-                      glBegin (GL_LINES);
-
-                      // Vertex 1
-                      if (ec_mode > 0)
-                        {
-                          for (int k = 0; k < 3; k++)
-                            cb[k] = c(j-1, i, k);
-                          glColor3fv (cb);
-
-                          if (fl_mode > 0)
-                            {
-                              for (int k = 0; k < 3; k++)
-                                cb[k] *= as;
-                              glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
-
-                              for (int k = 0; k < 3; k++)
-                                cb[k] = ds * c(j-1, i, k);
-                              glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
-                            }
-                        }
-                      if (el_mode > 0)
-                        {
-                          d = sqrt (n(j-1,i,0) * n(j-1,i,0)
-                                    + n(j-1,i,1) * n(j-1,i,1)
-                                    + n(j-1,i,2) * n(j-1,i,2));
-                          glNormal3d (n(j-1,i,0)/d, n(j-1,i,1)/d, n(j-1,i,2)/d);
-                        }
-                      glVertex3d (x(j1,i), y(j-1,i2), z(j-1,i));
-
-                      // Vertex 2
-                      if (ec_mode == 2)
-                        {
-                          for (int k = 0; k < 3; k++)
-                            cb[k] = c(j, i, k);
-                          glColor3fv (cb);
-
-                          if (fl_mode > 0)
-                            {
-                              for (int k = 0; k < 3; k++)
-                                cb[k] *= as;
-                              glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
-
-                              for (int k = 0; k < 3; k++)
-                                cb[k] = ds * c(j, i, k);
-                              glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
-                            }
-                        }
-                      if (el_mode == 2)
-                        {
-                          d = sqrt (n(j,i,0) * n(j,i,0)
-                                    + n(j,i,1) * n(j,i,1)
-                                    + n(j,i,2) * n(j,i,2));
-                          glNormal3d (n(j,i,0)/d, n(j,i,1)/d, n(j,i,2)/d);
-                        }
-                      glVertex3d (x(j2,i), y(j,i2), z(j,i));
-
-                      glEnd ();
-                    }
-                }
-            }
-
-          // Mesh along X-axis
-
-          if (props.meshstyle_is ("both") || props.meshstyle_is ("row"))
-            {
-              for (int j = 0; j < zr; j++)
-                {
-                  if (x_mat)
-                    {
-                      j1 = j-1;
-                      j2 = j;
-                    }
-
-                  for (int i = 1; i < zc; i++)
-                    {
-                      if (clip(j,i-1) || clip(j,i))
-                        continue;
-
-                      if (y_mat)
-                        {
-                          i1 = i-1;
-                          i2 = i;
-                        }
-
-                      glBegin (GL_LINES);
-
-                      // Vertex 1
-                      if (ec_mode > 0)
-                        {
-                          for (int k = 0; k < 3; k++)
-                            cb[k] = c(j, i-1, k);
-                          glColor3fv (cb);
-
-                          if (fl_mode > 0)
-                            {
-                              for (int k = 0; k < 3; k++)
-                                cb[k] *= as;
-                              glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
-
-                              for (int k = 0; k < 3; k++)
-                                cb[k] = ds * c(j, i-1, k);
-                              glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
-                            }
-                        }
-                      if (el_mode > 0)
-                        {
-                          d = sqrt (n(j,i-1,0) * n(j,i-1,0)
-                                    + n(j,i-1,1) * n(j,i-1,1)
-                                    + n(j,i-1,2) * n(j,i-1,2));
-                          glNormal3d (n(j,i-1,0)/d, n(j,i-1,1)/d, n(j,i-1,2)/d);
-                        }
-                      glVertex3d (x(j2,i-1), y(j,i1), z(j,i-1));
-
-                      // Vertex 2
-                      if (ec_mode == 2)
-                        {
-                          for (int k = 0; k < 3; k++)
-                            cb[k] = c(j, i, k);
-                          glColor3fv (cb);
-
-                          if (fl_mode > 0)
-                            {
-                              for (int k = 0; k < 3; k++)
-                                cb[k] *= as;
-                              glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
-
-                              for (int k = 0; k < 3; k++)
-                                cb[k] = ds * c(j, i, k);
-                              glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
-                            }
-                        }
-                      if (el_mode == 2)
-                        {
-                          d = sqrt (n(j,i,0) * n(j,i,0)
-                                    + n(j,i,1) * n(j,i,1)
-                                    + n(j,i,2) * n(j,i,2));
-                          glNormal3d (n(j,i,0)/d, n(j,i,1)/d, n(j,i,2)/d);
-                        }
-                      glVertex3d (x(j2,i), y(j,i2), z(j,i));
-
-                      glEnd ();
-                    }
-                }
-            }
-
-          set_linestyle ("-");
-          set_linewidth (0.5);
-
-          if (el_mode > 0)
-            glDisable (GL_LIGHTING);
-        }
-      else
-        {
-          // FIXME: implement transparency
-        }
-    }
-
-  if (! props.marker_is ("none") &&
-      ! (props.markeredgecolor_is ("none")
-         && props.markerfacecolor_is ("none")))
-    {
-      // FIXME: check how transparency should be handled in markers
-      // FIXME: check what to do with marker facecolor set to auto
-      //        and facecolor set to none.
-
-      bool do_edge = ! props.markeredgecolor_is ("none");
-      bool do_face = ! props.markerfacecolor_is ("none");
-
-      Matrix mecolor = props.get_markeredgecolor_rgb ();
-      Matrix mfcolor = props.get_markerfacecolor_rgb ();
-      Matrix cc (1, 3, 0.0);
-
-      if (mecolor.numel () == 0 && props.markeredgecolor_is ("auto"))
-        {
-          mecolor = props.get_edgecolor_rgb ();
-          do_edge = ! props.edgecolor_is ("none");
-        }
-
-      if (mfcolor.numel () == 0 && props.markerfacecolor_is ("auto"))
-        {
-          mfcolor = props.get_facecolor_rgb ();
-          do_face = ! props.facecolor_is ("none");
-        }
-
-      if ((mecolor.numel () == 0 || mfcolor.numel () == 0)
-          && c.numel () == 0)
-        c = props.get_color_data ().array_value ();
-
-      init_marker (props.get_marker (), props.get_markersize (),
-                   props.get_linewidth ());
-
-      for (int i = 0; i < zc; i++)
-        {
-          if (y_mat)
-            i1 = i;
-
-          for (int j = 0; j < zr; j++)
-            {
-              if (clip(j,i))
-                continue;
-
-              if (x_mat)
-                j1 = j;
-
-              if ((do_edge && mecolor.numel () == 0)
-                  || (do_face && mfcolor.numel () == 0))
-                {
-                  for (int k = 0; k < 3; k++)
-                    cc(k) = c(j,i,k);
-                }
-
-              Matrix lc = (do_edge ? (mecolor.numel () == 0 ? cc : mecolor) : Matrix ());
-              Matrix fc = (do_face ? (mfcolor.numel () == 0 ? cc : mfcolor) : Matrix ());
-
-              draw_marker (x(j1,i), y(j,i1), z(j,i), lc, fc);
-            }
-        }
-
-      end_marker ();
-    }
-}
-
-// FIXME: global optimization (rendering, data structures...), there
-// is probably a smarter/faster/less-memory-consuming way to do this.
-void
-opengl_renderer::draw_patch (const patch::properties &props)
-{
-  const Matrix f = props.get_faces ().matrix_value ();
-  const Matrix v = xform.scale (props.get_vertices ().matrix_value ());
-  Matrix c;
-  const Matrix n = props.get_vertexnormals ().matrix_value ();
-  Matrix a;
-
-  int nv = v.rows ();
-  // int vmax = v.columns ();
-  int nf = f.rows ();
-  int fcmax = f.columns ();
-
-  bool has_z = (v.columns () > 2);
-  bool has_facecolor = false;
-  bool has_facealpha = false;
-
-  int fc_mode = ((props.facecolor_is ("none")
-                  || props.facecolor_is_rgb ()) ? 0 :
-                 (props.facecolor_is ("flat") ? 1 : 2));
-  int fl_mode = (props.facelighting_is ("none") ? 0 :
-                 (props.facelighting_is ("flat") ? 1 : 2));
-  int fa_mode = (props.facealpha_is_double () ? 0 :
-                 (props.facealpha_is ("flat") ? 1 : 2));
-  int ec_mode = ((props.edgecolor_is ("none")
-                  || props.edgecolor_is_rgb ()) ? 0 :
-                 (props.edgecolor_is ("flat") ? 1 : 2));
-  int el_mode = (props.edgelighting_is ("none") ? 0 :
-                 (props.edgelighting_is ("flat") ? 1 : 2));
-  int ea_mode = (props.edgealpha_is_double () ? 0 :
-                 (props.edgealpha_is ("flat") ? 1 : 2));
-
-  Matrix fcolor = props.get_facecolor_rgb ();
-  Matrix ecolor = props.get_edgecolor_rgb ();
-
-  float as = props.get_ambientstrength ();
-  float ds = props.get_diffusestrength ();
-  float ss = props.get_specularstrength ();
-  float se = props.get_specularexponent ();
-
-  boolMatrix clip (1, nv, false);
-
-  if (has_z)
-    for (int i = 0; i < nv; i++)
-      clip(i) = is_nan_or_inf (v(i,0), v(i,1), v(i,2));
-  else
-    for (int i = 0; i < nv; i++)
-      clip(i) = is_nan_or_inf (v(i,0), v(i,1), 0);
-
-  boolMatrix clip_f (1, nf, false);
-  Array<int> count_f (dim_vector (nf, 1), 0);
-
-  for (int i = 0; i < nf; i++)
-    {
-      bool fclip = false;
-      int count = 0;
-
-      for (int j = 0; j < fcmax && ! xisnan (f(i,j)); j++, count++)
-        fclip = (fclip || clip(int (f(i,j) - 1)));
-
-      clip_f(i) = fclip;
-      count_f(i) = count;
-    }
-
-  if (fc_mode > 0 || ec_mode > 0)
-    {
-      c = props.get_color_data ().matrix_value ();
-
-      if (c.rows () == 1)
-        {
-          // Single color specifications, we can simplify a little bit
-
-          if (fc_mode > 0)
-            {
-              fcolor = c;
-              fc_mode = 0;
-            }
-
-          if (ec_mode > 0)
-            {
-              ecolor = c;
-              ec_mode = 0;
-            }
-
-          c = Matrix ();
-        }
-      else
-        has_facecolor = ((c.numel () > 0) && (c.rows () == f.rows ()));
-    }
-
-  if (fa_mode > 0 || ea_mode > 0)
-    {
-      // FIXME: retrieve alpha data from patch object
-      //a = props.get_alpha_data ();
-      has_facealpha = ((a.numel () > 0) && (a.rows () == f.rows ()));
-    }
-
-  octave_idx_type fr = f.rows ();
-  std::vector<vertex_data> vdata (f.numel ());
-
-  for (int i = 0; i < nf; i++)
-    for (int j = 0; j < count_f(i); j++)
-      {
-        int idx = int (f(i,j) - 1);
-
-        Matrix vv (1, 3, 0.0);
-        Matrix cc;
-        Matrix nn(1, 3, 0.0);
-        double aa = 1.0;
-
-        vv(0) = v(idx,0); vv(1) = v(idx,1);
-        if (has_z)
-          vv(2) = v(idx,2);
-        // FIXME: uncomment when patch object has normal computation
-        //nn(0) = n(idx,0); nn(1) = n(idx,1); nn(2) = n(idx,2);
-        if (c.numel () > 0)
-          {
-            cc.resize (1, 3);
-            if (has_facecolor)
-              cc(0) = c(i,0), cc(1) = c(i,1), cc(2) = c(i,2);
-            else
-              cc(0) = c(idx,0), cc(1) = c(idx,1), cc(2) = c(idx,2);
-          }
-        if (a.numel () > 0)
-          {
-            if (has_facealpha)
-              aa = a(i);
-            else
-              aa = a(idx);
-          }
-
-        vdata[i+j*fr] =
-            vertex_data (vv, cc, nn, aa, as, ds, ss, se);
-      }
-
-  if (fl_mode > 0 || el_mode > 0)
-    {
-      float buf[4] = { ss, ss, ss, 1 };
-
-      glMaterialfv (LIGHT_MODE, GL_SPECULAR, buf);
-      glMaterialf (LIGHT_MODE, GL_SHININESS, se);
-    }
-
-  if (! props.facecolor_is ("none"))
-    {
-      // FIXME: adapt to double-radio property
-      if (props.get_facealpha_double () == 1)
-        {
-          if (fc_mode == 0)
-            {
-              glColor3dv (fcolor.data ());
-              if (fl_mode > 0)
-                {
-                  float cb[4] = { 0, 0, 0, 1 };
-
-                  for (int i = 0; i < 3; i++)
-                    cb[i] = (as * fcolor(i));
-                  glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
-
-                  for (int i = 0; i < 3; i++)
-                    cb[i] = ds * fcolor(i);
-                  glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
-                }
-            }
-
-          if (fl_mode > 0)
-            glEnable (GL_LIGHTING);
-
-          // FIXME: use __index__ property from patch object
-          patch_tesselator tess (this, fc_mode, fl_mode, 0);
-
-          for (int i = 0; i < nf; i++)
-            {
-              if (clip_f(i))
-                continue;
-
-              tess.begin_polygon (true);
-              tess.begin_contour ();
-
-              for (int j = 0; j < count_f(i); j++)
-                {
-                  vertex_data::vertex_data_rep *vv = vdata[i+j*fr].get_rep ();
-
-                  tess.add_vertex (vv->coords.fortran_vec (), vv);
-                }
-
-              tess.end_contour ();
-              tess.end_polygon ();
-            }
-
-          if (fl_mode > 0)
-            glDisable (GL_LIGHTING);
-        }
-      else
-        {
-          // FIXME: implement transparency
-        }
-    }
-
-  if (! props.edgecolor_is ("none"))
-    {
-      // FIXME: adapt to double-radio property
-      if (props.get_edgealpha_double () == 1)
-        {
-          if (ec_mode == 0)
-            {
-              glColor3dv (ecolor.data ());
-              if (el_mode > 0)
-                {
-                  float cb[4] = { 0, 0, 0, 1 };
-
-                  for (int i = 0; i < 3; i++)
-                    cb[i] = (as * ecolor(i));
-                  glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
-
-                  for (int i = 0; i < 3; i++)
-                    cb[i] = ds * ecolor(i);
-                  glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
-                }
-            }
-
-          if (el_mode > 0)
-            glEnable (GL_LIGHTING);
-
-          set_linestyle (props.get_linestyle (), false);
-          set_linewidth (props.get_linewidth ());
-
-
-          // FIXME: use __index__ property from patch object; should we
-          // offset patch contour as well?
-          patch_tesselator tess (this, ec_mode, el_mode);
-
-          for (int i = 0; i < nf; i++)
-            {
-              if (clip_f(i))
-                {
-                  // This is an unclosed contour. Draw it as a line
-                  bool flag = false;
-
-                  for (int j = 0; j < count_f(i); j++)
-                    {
-                      if (! clip(int (f(i,j) - 1)))
-                        {
-                          vertex_data::vertex_data_rep *vv = vdata[i+j*fr].get_rep ();
-                          const Matrix m = vv->coords;
-                          if (! flag)
-                            {
-                              flag = true;
-                              glBegin (GL_LINE_STRIP);
-                            }
-                          glVertex3d (m(0), m(1), m(2));
-                        }
-                      else if (flag)
-                        {
-                          flag = false;
-                          glEnd ();
-                        }
-                    }
-
-                  if (flag)
-                    glEnd ();
-                }
-              else
-                {
-                  tess.begin_polygon (false);
-                  tess.begin_contour ();
-
-                  for (int j = 0; j < count_f(i); j++)
-                    {
-                      vertex_data::vertex_data_rep *vv = vdata[i+j*fr].get_rep ();
-                      tess.add_vertex (vv->coords.fortran_vec (), vv);
-                    }
-
-                  tess.end_contour ();
-                  tess.end_polygon ();
-                }
-            }
-
-          set_linestyle ("-");
-          set_linewidth (0.5);
-
-          if (el_mode > 0)
-            glDisable (GL_LIGHTING);
-        }
-      else
-        {
-          // FIXME: implement transparency
-        }
-    }
-
-  if (! props.marker_is ("none") &&
-      ! (props.markeredgecolor_is ("none") && props.markerfacecolor_is ("none")))
-    {
-      bool do_edge = ! props.markeredgecolor_is ("none");
-      bool do_face = ! props.markerfacecolor_is ("none");
-
-      Matrix mecolor = props.get_markeredgecolor_rgb ();
-      Matrix mfcolor = props.get_markerfacecolor_rgb ();
-
-      bool has_markerfacecolor = false;
-
-      if ((mecolor.numel () == 0 && ! props.markeredgecolor_is ("none"))
-          || (mfcolor.numel () == 0 && ! props.markerfacecolor_is ("none")))
-        {
-          Matrix mc = props.get_color_data ().matrix_value ();
-
-          if (mc.rows () == 1)
-            {
-              // Single color specifications, we can simplify a little bit
-
-              if (mfcolor.numel () == 0
-                   && ! props.markerfacecolor_is ("none"))
-                mfcolor = mc;
-
-              if (mecolor.numel () == 0
-                   && ! props.markeredgecolor_is ("none"))
-                mecolor = mc;
-            }
-          else
-            {
-              if (c.numel () == 0)
-                c = props.get_color_data ().matrix_value ();
-              has_markerfacecolor = ((c.numel () > 0)
-                                    && (c.rows () == f.rows ()));
-            }
-        }
-
-
-      init_marker (props.get_marker (), props.get_markersize (),
-                   props.get_linewidth ());
-
-      for (int i = 0; i < nf; i++)
-        for (int j = 0; j < count_f(i); j++)
-          {
-            int idx = int (f(i,j) - 1);
-
-            if (clip(idx))
-              continue;
-
-            Matrix cc;
-            if (c.numel () > 0)
-              {
-                cc.resize (1, 3);
-                if (has_markerfacecolor)
-                  cc(0) = c(i,0), cc(1) = c(i,1), cc(2) = c(i,2);
-                else
-                  cc(0) = c(idx,0), cc(1) = c(idx,1), cc(2) = c(idx,2);
-              }
-
-            Matrix lc = (do_edge ? (mecolor.numel () == 0 ? cc : mecolor)
-                         : Matrix ());
-            Matrix fc = (do_face ? (mfcolor.numel () == 0 ? cc : mfcolor)
-                         : Matrix ());
-
-            draw_marker (v(idx,0), v(idx,1), (has_z ? v(idx,2) : 0), lc, fc);
-          }
-
-      end_marker ();
-    }
-}
-
-void
-opengl_renderer::draw_hggroup (const hggroup::properties &props)
-{
-  draw (props.get_children ());
-}
-
-void
-opengl_renderer::draw_text (const text::properties& props)
-{
-  if (props.get_string ().is_empty ())
-    return;
-
-  Matrix pos = xform.scale (props.get_data_position ());
-  const Matrix bbox = props.get_extent_matrix ();
-
-  // FIXME: handle margin and surrounding box
-  bool blend = glIsEnabled (GL_BLEND);
-
-  glEnable (GL_BLEND);
-  glEnable (GL_ALPHA_TEST);
-  glRasterPos3d (pos(0), pos(1), pos.numel () > 2 ? pos(2) : 0.0);
-  glBitmap (0, 0, 0, 0, bbox(0), bbox(1), 0);
-  glDrawPixels (bbox(2), bbox(3),
-                GL_RGBA, GL_UNSIGNED_BYTE, props.get_pixels ().data ());
-  glDisable (GL_ALPHA_TEST);
-  if (! blend)
-    glDisable (GL_BLEND);
-
-}
-
-void
-opengl_renderer::draw_image (const image::properties& props)
-{
-  octave_value cdata = props.get_color_data ();
-  dim_vector dv (cdata.dims ());
-  int h = dv(0), w = dv(1);
-
-  Matrix x = props.get_xdata ().matrix_value ();
-  Matrix y = props.get_ydata ().matrix_value ();
-
-  // Someone wants us to draw an empty image? No way.
-  if (x.is_empty () || y.is_empty ())
-    return;
-
-  if (w > 1 && x(1) == x(0))
-    x(1) = x(1) + (w-1);
-
-  if (h > 1 && y(1) == y(0))
-    y(1) = y(1) + (h-1);
-
-  const ColumnVector p0 = xform.transform (x(0), y(0), 0);
-  const ColumnVector p1 = xform.transform (x(1), y(1), 0);
-
-  // image pixel size in screen pixel units
-  float pix_dx, pix_dy;
-  // image pixel size in normalized units
-  float nor_dx, nor_dy;
-
-  if (w > 1)
-    {
-      pix_dx = (p1(0) - p0(0))/(w-1);
-      nor_dx = (x(1) - x(0))/(w-1);
-    }
-  else
-    {
-      const ColumnVector p1w = xform.transform (x(1) + 1, y(1), 0);
-      pix_dx = p1w(0) - p0(0);
-      nor_dx = 1;
-    }
-
-  if (h > 1)
-    {
-      pix_dy = (p1(1) - p0(1))/(h-1);
-      nor_dy = (y(1) - y(0))/(h-1);
-    }
-  else
-    {
-      const ColumnVector p1h = xform.transform (x(1), y(1) + 1, 0);
-      pix_dy = p1h(1) - p0(1);
-      nor_dy = 1;
-    }
-
-
-  // OpenGL won't draw the image if it's origin is outside the
-  // viewport/clipping plane so we must do the clipping
-  // ourselfes - only draw part of the image
-
-  int j0 = 0, j1 = w;
-  int i0 = 0, i1 = h;
-
-  float im_xmin = x(0) - nor_dx/2;
-  float im_xmax = x(1) + nor_dx/2;
-  float im_ymin = y(0) - nor_dy/2;
-  float im_ymax = y(1) + nor_dy/2;
-  if (props.is_clipping ()) // clip to axes
-    {
-      if (im_xmin < xmin)
-        j0 += (xmin - im_xmin)/nor_dx + 1;
-      if (im_xmax > xmax)
-        j1 -= (im_xmax - xmax)/nor_dx ;
-
-      if (im_ymin < ymin)
-        i0 += (ymin - im_ymin)/nor_dy + 1;
-      if (im_ymax > ymax)
-        i1 -= (im_ymax - ymax)/nor_dy;
-    }
-  else // clip to viewport
-    {
-      GLfloat vp[4];
-      glGetFloatv (GL_VIEWPORT, vp);
-      // FIXME -- actually add the code to do it!
-
-    }
-
-  if (i0 >= i1 || j0 >= j1)
-    return;
-
-  glPixelZoom (pix_dx, -pix_dy);
-  glRasterPos3d (im_xmin + nor_dx*j0, im_ymin + nor_dy*i0, 0);
-
-  // by default this is 4
-  glPixelStorei (GL_UNPACK_ALIGNMENT,1);
-
-  // Expect RGB data
-  if (dv.length () == 3 && dv(2) == 3)
-    {
-      if (cdata.is_double_type ())
-        {
-          const NDArray xcdata = cdata.array_value ();
-
-          OCTAVE_LOCAL_BUFFER (GLfloat, a, 3*(j1-j0)*(i1-i0));
-
-          for (int i = i0; i < i1; i++)
-            {
-              for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3)
-                {
-                  a[idx]   = xcdata(i,j,0);
-                  a[idx+1] = xcdata(i,j,1);
-                  a[idx+2] = xcdata(i,j,2);
-                }
-            }
-
-          draw_pixels (j1-j0, i1-i0, GL_RGB, GL_FLOAT, a);
-
-        }
-      else if (cdata.is_uint16_type ())
-        {
-          const uint16NDArray xcdata = cdata.uint16_array_value ();
-
-          OCTAVE_LOCAL_BUFFER (GLushort, a, 3*(j1-j0)*(i1-i0));
-
-          for (int i = i0; i < i1; i++)
-            {
-              for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3)
-                {
-                  a[idx]   = xcdata(i,j,0);
-                  a[idx+1] = xcdata(i,j,1);
-                  a[idx+2] = xcdata(i,j,2);
-                }
-            }
-
-          draw_pixels (j1-j0, i1-i0, GL_RGB, GL_UNSIGNED_SHORT, a);
-
-        }
-      else if (cdata.is_uint8_type ())
-        {
-          const uint8NDArray xcdata = cdata.uint8_array_value ();
-
-          OCTAVE_LOCAL_BUFFER (GLubyte, a, 3*(j1-j0)*(i1-i0));
-
-          for (int i = i0; i < i1; i++)
-            {
-              for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3)
-                {
-                  a[idx]   = xcdata(i,j,0);
-                  a[idx+1] = xcdata(i,j,1);
-                  a[idx+2] = xcdata(i,j,2);
-                }
-            }
-
-          draw_pixels (j1-j0, i1-i0, GL_RGB, GL_UNSIGNED_BYTE, a);
-        }
-      else
-        warning ("opengl_texture::draw: invalid image data type (expected double, uint16, or uint8)");
-    }
-  else
-    warning ("opengl_texture::draw: invalid image size (expected n*m*3 or n*m)");
-
-  glPixelZoom (1, 1);
-}
-
-void
-opengl_renderer::set_viewport (int w, int h)
-{
-  glViewport (0, 0, w, h);
-}
-
-void
-opengl_renderer::draw_pixels (GLsizei width, GLsizei height, GLenum format,
-                              GLenum type, const GLvoid *data)
-{
-  glDrawPixels (width, height, format, type, data);
-}
-
-void
-opengl_renderer::set_color (const Matrix& c)
-{
-  glColor3dv (c.data ());
-#if HAVE_FREETYPE
-  text_renderer.set_color (c);
-#endif
-}
-
-void
-opengl_renderer::set_font (const base_properties& props)
-{
-#if HAVE_FREETYPE
-  text_renderer.set_font (props.get ("fontname").string_value (),
-                          props.get ("fontweight").string_value (),
-                          props.get ("fontangle").string_value (),
-                          props.get ("fontsize").double_value ());
-#endif
-}
-
-void
-opengl_renderer::set_polygon_offset (bool on, double offset)
-{
-  if (on)
-    {
-      glPolygonOffset (offset, offset);
-      glEnable (GL_POLYGON_OFFSET_FILL);
-      glEnable (GL_POLYGON_OFFSET_LINE);
-    }
-  else
-    {
-      glDisable (GL_POLYGON_OFFSET_FILL);
-      glDisable (GL_POLYGON_OFFSET_LINE);
-    }
-}
-
-void
-opengl_renderer::set_linewidth (float w)
-{
-  glLineWidth (w);
-}
-
-void
-opengl_renderer::set_linestyle (const std::string& s, bool use_stipple)
-{
-  bool solid = false;
-
-  if (s == "-")
-    {
-      glLineStipple (1, static_cast<unsigned short> (0xFFFF));
-      solid = true;
-    }
-  else if (s == ":")
-    glLineStipple (1, static_cast<unsigned short> (0x8888));
-  else if (s == "--")
-    glLineStipple (1, static_cast<unsigned short> (0x0FFF));
-  else if (s == "-.")
-    glLineStipple (1, static_cast<unsigned short> (0x020F));
-  else
-    glLineStipple (1, static_cast<unsigned short> (0x0000));
-
-  if (solid && ! use_stipple)
-    glDisable (GL_LINE_STIPPLE);
-  else
-    glEnable (GL_LINE_STIPPLE);
-}
-
-void
-opengl_renderer::set_clipbox (double x1, double x2, double y1, double y2,
-                              double z1, double z2)
-{
-  double dx = (x2-x1);
-  double dy = (y2-y1);
-  double dz = (z2-z1);
-
-  x1 -= 0.001*dx; x2 += 0.001*dx;
-  y1 -= 0.001*dy; y2 += 0.001*dy;
-  z1 -= 0.001*dz; z2 += 0.001*dz;
-
-  ColumnVector p (4, 0.0);
-
-  p(0) = -1; p(3) = x2;
-  glClipPlane (GL_CLIP_PLANE0, p.data ());
-  p(0) = 1; p(3) = -x1;
-  glClipPlane (GL_CLIP_PLANE1, p.data ());
-  p(0) = 0; p(1) = -1; p(3) = y2;
-  glClipPlane (GL_CLIP_PLANE2, p.data ());
-  p(1) = 1; p(3) = -y1;
-  glClipPlane (GL_CLIP_PLANE3, p.data ());
-  p(1) = 0; p(2) = -1; p(3) = z2;
-  glClipPlane (GL_CLIP_PLANE4, p.data ());
-  p(2) = 1; p(3) = -z1;
-  glClipPlane (GL_CLIP_PLANE5, p.data ());
-
-  xmin = x1; xmax = x2;
-  ymin = y1; ymax = y2;
-  zmin = z1; zmax = z2;
-}
-
-void
-opengl_renderer::set_clipping (bool enable)
-{
-  bool has_clipping = (glIsEnabled (GL_CLIP_PLANE0) == GL_TRUE);
-
-  if (enable != has_clipping)
-    {
-      if (enable)
-        for (int i = 0; i < 6; i++)
-          glEnable (GL_CLIP_PLANE0+i);
-      else
-        for (int i = 0; i < 6; i++)
-          glDisable (GL_CLIP_PLANE0+i);
-    }
-}
-
-void
-opengl_renderer::init_marker (const std::string& m, double size, float width)
-{
-#if defined (HAVE_FRAMEWORK_OPENGL)
-  GLint vw[4];
-#else
-  int vw[4];
-#endif
-
-  glGetIntegerv (GL_VIEWPORT, vw);
-
-  glMatrixMode (GL_PROJECTION);
-  glPushMatrix ();
-  glLoadIdentity ();
-  glOrtho (0, vw[2], vw[3], 0, xZ1, xZ2);
-  glMatrixMode (GL_MODELVIEW);
-  glPushMatrix ();
-
-  set_clipping (false);
-  set_linewidth (width);
-
-  marker_id = make_marker_list (m, size, false);
-  filled_marker_id = make_marker_list (m, size, true);
-}
-
-void
-opengl_renderer::end_marker (void)
-{
-  glDeleteLists (marker_id, 1);
-  glDeleteLists (filled_marker_id, 1);
-
-  glMatrixMode (GL_MODELVIEW);
-  glPopMatrix ();
-  glMatrixMode (GL_PROJECTION);
-  glPopMatrix ();
-  set_linewidth (0.5f);
-}
-
-void
-opengl_renderer::draw_marker (double x, double y, double z,
-                              const Matrix& lc, const Matrix& fc)
-{
-  ColumnVector tmp = xform.transform (x, y, z, false);
-
-  glLoadIdentity ();
-  glTranslated (tmp(0), tmp(1), -tmp(2));
-
-  if (filled_marker_id > 0 && fc.numel () > 0)
-    {
-      glColor3dv (fc.data ());
-      set_polygon_offset (true, -1.0);
-      glCallList (filled_marker_id);
-      if (lc.numel () > 0)
-        {
-          glColor3dv (lc.data ());
-          glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
-          glEdgeFlag (GL_TRUE);
-          set_polygon_offset (true, -2.0);
-          glCallList (filled_marker_id);
-          glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
-        }
-      set_polygon_offset (false);
-    }
-  else if (marker_id > 0 && lc.numel () > 0)
-    {
-      glColor3dv (lc.data ());
-      glCallList (marker_id);
-    }
-}
-
-unsigned int
-opengl_renderer::make_marker_list (const std::string& marker, double size,
-                                   bool filled) const
-{
-  char c = marker[0];
-
-  if (filled && (c == '+' || c == 'x' || c == '*' || c == '.'))
-    return 0;
-
-  unsigned int ID = glGenLists (1);
-  double sz = size * toolkit.get_screen_resolution () / 72.0;
-
-  // constants for the * marker
-  const double sqrt2d4 = 0.35355339059327;
-  double tt = sz*sqrt2d4;
-
-  glNewList (ID, GL_COMPILE);
-
-  switch (marker[0])
-    {
-    case '+':
-      glBegin (GL_LINES);
-      glVertex2f (-sz/2, 0);
-      glVertex2f (sz/2, 0);
-      glVertex2f (0, -sz/2);
-      glVertex2f (0, sz/2);
-      glEnd ();
-      break;
-    case 'x':
-      glBegin (GL_LINES);
-      glVertex2f (-sz/2, -sz/2);
-      glVertex2f (sz/2, sz/2);
-      glVertex2f (-sz/2, sz/2);
-      glVertex2f (sz/2, -sz/2);
-      glEnd ();
-      break;
-    case '*':
-      glBegin (GL_LINES);
-      glVertex2f (-sz/2, 0);
-      glVertex2f (sz/2, 0);
-      glVertex2f (0, -sz/2);
-      glVertex2f (0, sz/2);
-      glVertex2f (-tt, -tt);
-      glVertex2f (+tt, +tt);
-      glVertex2f (-tt, +tt);
-      glVertex2f (+tt, -tt);
-      glEnd ();
-      break;
-    case '.':
-      {
-        double ang_step = M_PI / 5;
-
-        glBegin (GL_POLYGON);
-        for (double ang = 0; ang < (2*M_PI); ang += ang_step)
-          glVertex2d (sz*cos (ang)/3, sz*sin (ang)/3);
-        glEnd ();
-      }
-      break;
-    case 's':
-      glBegin ((filled ? GL_POLYGON : GL_LINE_LOOP));
-      glVertex2d (-sz/2, -sz/2);
-      glVertex2d (-sz/2, sz/2);
-      glVertex2d (sz/2, sz/2);
-      glVertex2d (sz/2, -sz/2);
-      glEnd ();
-      break;
-    case 'o':
-      {
-        double ang_step = M_PI / 5;
-
-        glBegin ((filled ? GL_POLYGON : GL_LINE_LOOP));
-        for (double ang = 0; ang < (2*M_PI); ang += ang_step)
-          glVertex2d (sz*cos (ang)/2, sz*sin (ang)/2);
-        glEnd ();
-      }
-      break;
-    case 'd':
-      glBegin ((filled ? GL_POLYGON : GL_LINE_LOOP));
-      glVertex2d (0, -sz/2);
-      glVertex2d (sz/2, 0);
-      glVertex2d (0, sz/2);
-      glVertex2d (-sz/2, 0);
-      glEnd ();
-      break;
-    case 'v':
-      glBegin ((filled ? GL_POLYGON : GL_LINE_LOOP));
-      glVertex2f (0, sz/2);
-      glVertex2f (sz/2, -sz/2);
-      glVertex2f (-sz/2, -sz/2);
-      glEnd ();
-      break;
-    case '^':
-      glBegin ((filled ? GL_POLYGON : GL_LINE_LOOP));
-      glVertex2f (0, -sz/2);
-      glVertex2f (-sz/2, sz/2);
-      glVertex2f (sz/2, sz/2);
-      glEnd ();
-      break;
-    case '>':
-      glBegin ((filled ? GL_POLYGON : GL_LINE_LOOP));
-      glVertex2f (sz/2, 0);
-      glVertex2f (-sz/2, sz/2);
-      glVertex2f (-sz/2, -sz/2);
-      glEnd ();
-      break;
-    case '<':
-      glBegin ((filled ? GL_POLYGON : GL_LINE_LOOP));
-      glVertex2f (-sz/2, 0);
-      glVertex2f (sz/2, -sz/2);
-      glVertex2f (sz/2, sz/2);
-      glEnd ();
-      break;
-    case 'p':
-      {
-        double ang;
-        double r;
-        double dr = 1.0 - sin (M_PI/10)/sin (3*M_PI/10)*1.02;
-
-        glBegin ((filled ? GL_POLYGON : GL_LINE_LOOP));
-        for (int i = 0; i < 2*5; i++)
-          {
-            ang = (-0.5 + double(i+1)/5) * M_PI;
-            r = 1.0 - (dr * fmod (double(i+1), 2.0));
-            glVertex2d (sz*r*cos (ang)/2, sz*r*sin (ang)/2);
-          }
-        glEnd ();
-      }
-      break;
-    case 'h':
-      {
-        double ang;
-        double r;
-        double dr = 1.0 - 0.5/sin (M_PI/3)*1.02;
-
-        glBegin ((filled ? GL_POLYGON : GL_LINE_LOOP));
-        for (int i = 0; i < 2*6; i++)
-          {
-            ang = (0.5 + double(i+1)/6.0) * M_PI;
-            r = 1.0 - (dr * fmod (double(i+1), 2.0));
-            glVertex2d (sz*r*cos (ang)/2, sz*r*sin (ang)/2);
-          }
-        glEnd ();
-      }
-      break;
-    default:
-      warning ("opengl_renderer: unsupported marker `%s'",
-               marker.c_str ());
-      break;
-    }
-
-  glEndList ();
-
-  return ID;
-}
-
-void
-opengl_renderer::text_to_pixels (const std::string& txt,
-                                 uint8NDArray& pixels,
-                                 Matrix& bbox,
-                                 int halign, int valign, double rotation)
-{
-#if HAVE_FREETYPE
-  text_renderer.text_to_pixels (txt, pixels, bbox,
-                                halign, valign, rotation);
-#endif
-}
-
-Matrix
-opengl_renderer::render_text (const std::string& txt,
-                            double x, double y, double z,
-                            int halign, int valign, double rotation)
-{
-#if HAVE_FREETYPE
-  if (txt.empty ())
-    return Matrix (1, 4, 0.0);
-
-  uint8NDArray pixels;
-  Matrix bbox;
-  text_to_pixels (txt, pixels, bbox, halign, valign, rotation);
-
-  bool blend = glIsEnabled (GL_BLEND);
-
-  glEnable (GL_BLEND);
-  glEnable (GL_ALPHA_TEST);
-  glRasterPos3d (x, y, z);
-  glBitmap(0, 0, 0, 0, bbox(0), bbox(1), 0);
-  glDrawPixels (bbox(2), bbox(3),
-                GL_RGBA, GL_UNSIGNED_BYTE, pixels.data ());
-  glDisable (GL_ALPHA_TEST);
-  if (! blend)
-    glDisable (GL_BLEND);
-
-  return bbox;
-#else
-  ::warning ("render_text: cannot render text, Freetype library not available");
-  return Matrix (1, 4, 0.0);
-#endif
-}
-
-#endif
--- a/src/gl-render.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,211 +0,0 @@
-/*
-
-Copyright (C) 2008-2012 Michael Goffioul
-
-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/>.
-
-*/
-
-#if !defined (gl_render_h)
-#define gl_render_h 1
-
-#ifdef HAVE_WINDOWS_H
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#endif
-
-#ifdef HAVE_GL_GL_H
-#include <GL/gl.h>
-#elif defined HAVE_OPENGL_GL_H || defined HAVE_FRAMEWORK_OPENGL
-#include <OpenGL/gl.h>
-#endif
-
-#ifdef HAVE_GL_GLU_H
-#include <GL/glu.h>
-#elif defined HAVE_OPENGL_GLU_H || defined HAVE_FRAMEWORK_OPENGL
-#include <OpenGL/glu.h>
-#endif
-
-#include "graphics.h"
-#include "txt-eng-ft.h"
-
-class
-OCTINTERP_API
-opengl_renderer
-{
-public:
-  opengl_renderer (void)
-    : toolkit (), xform (), xmin (), xmax (), ymin (), ymax (),
-    zmin (), zmax (), xZ1 (), xZ2 (), marker_id (), filled_marker_id (),
-    camera_pos (), camera_dir ()
-#if HAVE_FREETYPE
-    , text_renderer ()
-#endif
-  { }
-
-  virtual ~opengl_renderer (void) { }
-
-  virtual void draw (const graphics_object& go, bool toplevel = true);
-
-  virtual void draw (const Matrix& hlist, bool toplevel = false)
-    {
-      int len = hlist.length ();
-
-      for (int i = len-1; i >= 0; i--)
-        {
-          graphics_object obj = gh_manager::get_object (hlist(i));
-
-          if (obj)
-            draw (obj, toplevel);
-        }
-    }
-
-  virtual void set_viewport (int w, int h);
-  virtual graphics_xform get_transform (void) const { return xform; }
-
-protected:
-  virtual void draw_figure (const figure::properties& props);
-  virtual void draw_axes (const axes::properties& props);
-  virtual void draw_line (const line::properties& props);
-  virtual void draw_surface (const surface::properties& props);
-  virtual void draw_patch (const patch::properties& props);
-  virtual void draw_hggroup (const hggroup::properties& props);
-  virtual void draw_text (const text::properties& props);
-  virtual void draw_image (const image::properties& props);
-  virtual void draw_uipanel (const uipanel::properties& props,
-                             const graphics_object& go);
-
-  virtual void init_gl_context (bool enhanced, const Matrix& backgroundColor);
-  virtual void setup_opengl_transformation (const axes::properties& props);
-
-  virtual void set_color (const Matrix& c);
-  virtual void set_polygon_offset (bool on, double offset = 0.0);
-  virtual void set_linewidth (float w);
-  virtual void set_linestyle (const std::string& s, bool stipple = false);
-  virtual void set_clipbox (double x1, double x2, double y1, double y2,
-                            double z1, double z2);
-  virtual void set_clipping (bool on);
-  virtual void set_font (const base_properties& props);
-
-  virtual void init_marker (const std::string& m, double size, float width);
-  virtual void end_marker (void);
-  virtual void draw_marker (double x, double y, double z,
-                            const Matrix& lc, const Matrix& fc);
-
-  virtual void text_to_pixels (const std::string& txt,
-                               uint8NDArray& pixels,
-                               Matrix& bbox,
-                               int halign = 0, int valign = 0,
-                               double rotation = 0.0);
-
-  virtual Matrix render_text (const std::string& txt,
-                              double x, double y, double z,
-                              int halign, int valign, double rotation = 0.0);
-
-  virtual void draw_pixels (GLsizei w, GLsizei h, GLenum format,
-                            GLenum type, const GLvoid *data);
-
-  virtual void render_grid (const std::string& gridstyle, const Matrix& ticks,
-                            double lim1, double lim2,
-                            double p1, double p1N, double p2, double p2N,
-                            int xyz, bool is_3D);
-
-  virtual void render_tickmarks (const Matrix& ticks, double lim1, double lim2,
-                                 double p1, double p1N, double p2, double p2N,
-                                 double dx, double dy, double dz,
-                                 int xyz, bool doubleside);
-
-  virtual void render_ticktexts (const Matrix& ticks,
-                                 const string_vector& ticklabels,
-                                 double lim1, double lim2,
-                                 double p1, double p2,
-                                 int xyz, int ha, int va,
-                                 int& wmax, int& hmax);
-
-private:
-  opengl_renderer (const opengl_renderer&)
-    : toolkit (), xform (), xmin (), xmax (), ymin (), ymax (),
-    zmin (), zmax (), xZ1 (), xZ2 (), marker_id (), filled_marker_id (),
-    camera_pos (), camera_dir ()
-#if HAVE_FREETYPE
-    , text_renderer ()
-#endif
-    { }
-
-  opengl_renderer& operator = (const opengl_renderer&)
-    { return *this; }
-
-  bool is_nan_or_inf (double x, double y, double z) const
-    {
-      return (xisnan (x) || xisnan (y) || xisnan (z)
-              || xisinf (x) || xisinf (y) || xisinf (z));
-    }
-
-  octave_uint8 clip_code (double x, double y, double z) const
-    {
-      return ((x < xmin ? 1 : 0)
-              | (x > xmax ? 1 : 0) << 1
-              | (y < ymin ? 1 : 0) << 2
-              | (y > ymax ? 1 : 0) << 3
-              | (z < zmin ? 1 : 0) << 4
-              | (z > zmax ? 1 : 0) << 5
-              | (is_nan_or_inf (x, y, z) ? 0 : 1) << 6);
-    }
-
-  unsigned int make_marker_list (const std::string& m, double size,
-                                 bool filled) const;
-
-  void draw_axes_planes (const axes::properties& props);
-  void draw_axes_boxes (const axes::properties& props);
-
-  void draw_axes_x_grid (const axes::properties& props);
-  void draw_axes_y_grid (const axes::properties& props);
-  void draw_axes_z_grid (const axes::properties& props);
-
-  void draw_axes_children (const axes::properties& props);
-
-private:
-  // The graphics toolkit associated with the figure being rendered.
-  graphics_toolkit toolkit;
-
-  // axes transformation data
-  graphics_xform xform;
-
-  // axis limits in model scaled coordinate
-  double xmin, xmax;
-  double ymin, ymax;
-  double zmin, zmax;
-
-  // Z projection limits in windows coordinate
-  double xZ1, xZ2;
-
-  // call lists identifiers for markers
-  unsigned int marker_id, filled_marker_id;
-
-  // camera information for primitive sorting
-  ColumnVector camera_pos, camera_dir;
-
-#if HAVE_FREETYPE
-  // freetype render, used for text rendering
-  ft_render text_renderer;
-#endif
-
-private:
-  class patch_tesselator;
-};
-
-#endif
--- a/src/gl2ps-renderer.cc	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,232 +0,0 @@
-/*
-
-Copyright (C) 2009-2012 Shai Ayal
-
-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/>.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#if defined (HAVE_OPENGL)
-
-#include <cstdio>
-
-#include "lo-mappers.h"
-#include "oct-locbuf.h"
-
-#include "gl2ps-renderer.h"
-#include "gl2ps.h"
-
-void
-glps_renderer::draw (const graphics_object& go)
-{
-  static bool in_draw = false;
-
-  if (!in_draw)
-    {
-      in_draw = true;
-
-      GLint buffsize = 0, state = GL2PS_OVERFLOW;
-      GLint viewport[4];
-
-      glGetIntegerv (GL_VIEWPORT, viewport);
-
-      GLint gl2ps_term;
-      if (term.find ("eps") != std::string::npos) gl2ps_term = GL2PS_EPS;
-      else if (term.find ("pdf") != std::string::npos) gl2ps_term = GL2PS_PDF;
-      else if (term.find ("svg") != std::string::npos) gl2ps_term = GL2PS_SVG;
-      else if (term.find ("ps") != std::string::npos) gl2ps_term = GL2PS_PS;
-      else if (term.find ("pgf") != std::string::npos) gl2ps_term = GL2PS_PGF;
-      else if (term.find ("tex") != std::string::npos) gl2ps_term = GL2PS_TEX;
-      else
-        {
-          error ("gl2ps-renderer:: Unknown terminal");
-          return;
-        }
-
-      GLint gl2ps_text = 0;
-      if (term.find ("notxt") != std::string::npos) gl2ps_text = GL2PS_NO_TEXT;
-
-      // Default sort order optimizes for 3D plots
-      GLint gl2ps_sort = GL2PS_BSP_SORT;
-      if (term.find ("is2D") != std::string::npos) gl2ps_sort = GL2PS_NO_SORT;
-
-      while (state == GL2PS_OVERFLOW)
-        {
-          buffsize += 1024*1024;
-          gl2psBeginPage ("glps_renderer figure", "Octave", viewport,
-                          gl2ps_term, gl2ps_sort,
-                          (GL2PS_SILENT | GL2PS_SIMPLE_LINE_OFFSET
-                           | GL2PS_NO_BLENDING | GL2PS_OCCLUSION_CULL
-                           | GL2PS_BEST_ROOT | gl2ps_text
-                           | GL2PS_NO_PS3_SHADING),
-                          GL_RGBA, 0, NULL, 0, 0, 0,
-                          buffsize, fp, "" );
-
-          opengl_renderer::draw (go);
-          state = gl2psEndPage ();
-        }
-
-      in_draw = 0;
-    }
-  else
-    opengl_renderer::draw (go);
-}
-
-int
-glps_renderer::alignment_to_mode (int ha, int va) const
-{
-  int gl2psa=GL2PS_TEXT_BL;
-  if (ha == 0)
-    {
-      if (va == 0 || va == 3)
-        gl2psa=GL2PS_TEXT_BL;
-      else if (va == 2)
-        gl2psa=GL2PS_TEXT_TL;
-      else if (va == 1)
-        gl2psa=GL2PS_TEXT_CL;
-    }
-  else if (ha == 2)
-    {
-      if (va == 0 || va == 3)
-        gl2psa=GL2PS_TEXT_BR;
-      else if (va == 2)
-        gl2psa=GL2PS_TEXT_TR;
-      else if (va == 1)
-        gl2psa=GL2PS_TEXT_CR;
-    }
-  else if (ha == 1)
-    {
-      if (va == 0 || va == 3)
-        gl2psa=GL2PS_TEXT_B;
-      else if (va == 2)
-        gl2psa=GL2PS_TEXT_T;
-      else if (va == 1)
-        gl2psa=GL2PS_TEXT_C;
-    }
-  return gl2psa;
-}
-
-Matrix
-glps_renderer::render_text (const std::string& txt,
-                            double x, double y, double z,
-                            int ha, int va, double rotation)
-{
-  if (txt.empty ())
-    return Matrix (1, 4, 0.0);
-
-  glRasterPos3d (x, y, z);
-  gl2psTextOpt (txt.c_str (), fontname.c_str (), fontsize,
-                alignment_to_mode (ha, va), rotation);
-
-  // FIXME? -- we have no way of getting a bounding box from gl2ps, so
-  // we use freetype
-  Matrix bbox;
-  uint8NDArray pixels;
-  text_to_pixels (txt, pixels, bbox, 0, 0, rotation);
-  return bbox;
-}
-
-void
-glps_renderer::set_font (const base_properties& props)
-{
-  opengl_renderer::set_font (props);
-
-  fontsize = props.get ("fontsize").double_value ();
-
-  caseless_str fn = props.get ("fontname").string_value ();
-  fontname = "";
-  if (fn == "times" || fn == "times-roman")
-    fontname = "Times-Roman";
-  else if (fn == "courier")
-    fontname = "Courier";
-  else if (fn == "symbol")
-    fontname = "Symbol";
-  else if (fn == "zapfdingbats")
-    fontname = "ZapfDingbats";
-  else
-    fontname = "Helvetica";
-
-  // FIXME -- add support for bold and italic
-}
-
-template <typename T>
-static void
-draw_pixels (GLsizei w, GLsizei h, GLenum format, const T *data)
-{
-  OCTAVE_LOCAL_BUFFER (GLfloat, a, 3*w*h);
-
-  for (int i = 0; i < 3*w*h; i++)
-    a[i] = data[i];
-
-  gl2psDrawPixels (w, h, 0, 0, format, GL_FLOAT, a);
-}
-
-void
-glps_renderer::draw_pixels (GLsizei w, GLsizei h, GLenum format,
-                            GLenum type, const GLvoid *data)
-{
-  if (type == GL_UNSIGNED_SHORT)
-    ::draw_pixels (w, h, format, static_cast<const GLushort *> (data));
-  else if (type == GL_UNSIGNED_BYTE)
-    ::draw_pixels (w, h, format, static_cast<const GLubyte *> (data));
-  else
-    gl2psDrawPixels (w, h, 0, 0, format, type, data);
-}
-
-void
-glps_renderer::draw_text (const text::properties& props)
-{
-  if (props.get_string ().is_empty ())
-    return;
-
-  set_font (props);
-  set_color (props.get_color_rgb ());
-
-  const Matrix pos = get_transform ().scale (props.get_data_position ());
-  int halign = 0, valign = 0;
-
-  if (props.horizontalalignment_is ("center"))
-    halign = 1;
-  else if (props.horizontalalignment_is ("right"))
-    halign = 2;
-
-  if (props.verticalalignment_is ("top"))
-    valign = 2;
-  else if (props.verticalalignment_is ("baseline"))
-    valign = 3;
-  else if (props.verticalalignment_is ("middle"))
-    valign = 1;
-
-  // FIXME: handle margin and surrounding box
-
-  glRasterPos3d (pos(0), pos(1), pos.numel () > 2 ? pos(2) : 0.0);
-
-  octave_value string_prop = props.get_string ();
-
-  string_vector sv = string_prop.all_strings ();
-
-  std::string s = sv.join ("\n");
-
-  gl2psTextOpt (s.c_str (), fontname.c_str (), fontsize,
-                alignment_to_mode (halign, valign), props.get_rotation ());
-}
-
-#endif
--- a/src/gl2ps-renderer.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-/*
-
-Copyright (C) 2009-2012 Shai Ayal
-
-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/>.
-
-*/
-
-#if !defined (gl2ps_renderer_h)
-#define gl2ps_renderer_h 1
-
-#include "gl-render.h"
-#include "gl2ps.h"
-
-class
-OCTINTERP_API
-glps_renderer : public opengl_renderer
-{
-public:
-  glps_renderer (FILE *_fp, const std::string& _term)
-    : opengl_renderer () , fp (_fp), term (_term),
-    fontsize (), fontname () { }
-
-  ~glps_renderer (void) { }
-
-  void draw (const graphics_object& go);
-
-protected:
-
-  Matrix render_text (const std::string& txt,
-                      double x, double y, double z,
-                      int halign, int valign, double rotation = 0.0);
-
-
-  void set_font (const base_properties& props);
-
-  void draw_text (const text::properties& props);
-  void draw_pixels (GLsizei w, GLsizei h, GLenum format,
-                    GLenum type, const GLvoid *data);
-
-  void set_linestyle (const std::string& s, bool use_stipple = false)
-  {
-    opengl_renderer::set_linestyle (s, use_stipple);
-
-    if (s == "-" && ! use_stipple)
-      gl2psDisable (GL2PS_LINE_STIPPLE);
-    else
-      gl2psEnable (GL2PS_LINE_STIPPLE);
-  }
-
-  void set_polygon_offset (bool on, double offset = 0.0)
-  {
-    opengl_renderer::set_polygon_offset (on, offset);
-    if (on)
-      gl2psEnable (GL2PS_POLYGON_OFFSET_FILL);
-    else
-      gl2psDisable (GL2PS_POLYGON_OFFSET_FILL);
-  }
-
-  void set_linewidth (float w)
-  {
-    gl2psLineWidth (w);
-  }
-
-private:
-  int alignment_to_mode (int ha, int va) const;
-  FILE *fp;
-  caseless_str term;
-  double fontsize;
-  std::string fontname;
-};
-
-#endif
--- a/src/gl2ps.c	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,6078 +0,0 @@
-/*
- * GL2PS, an OpenGL to PostScript Printing Library
- * Copyright (C) 1999-2011 C. Geuzaine
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of either:
- *
- * a) the GNU Library General Public License as published by the Free
- * Software Foundation, either version 2 of the License, or (at your
- * option) any later version; or
- *
- * b) the GL2PS License as published by Christophe Geuzaine, either
- * version 2 of the License, or (at your option) any later version.
- *
- * This program 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 either
- * the GNU Library General Public License or the GL2PS License for
- * more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library in the file named "COPYING.LGPL";
- * if not, write to the Free Software Foundation, Inc., 675 Mass Ave,
- * Cambridge, MA 02139, USA.
- *
- * You should have received a copy of the GL2PS License with this
- * library in the file named "COPYING.GL2PS"; if not, I will be glad
- * to provide one.
- *
- * For the latest info about gl2ps and a full list of contributors,
- * see http://www.geuz.org/gl2ps/.
- *
- * Please report all bugs and problems to <gl2ps@geuz.org>.
- */
-
-#include "gl2ps.h"
-
-#include <math.h>
-#include <string.h>
-#include <sys/types.h>
-#include <stdarg.h>
-#include <time.h>
-#include <float.h>
-
-#if defined(GL2PS_HAVE_ZLIB)
-#include <zlib.h>
-#endif
-
-#if defined(GL2PS_HAVE_LIBPNG)
-#include <png.h>
-#endif
-
-/*********************************************************************
- *
- * Private definitions, data structures and prototypes
- *
- *********************************************************************/
-
-/* Magic numbers (assuming that the order of magnitude of window
-   coordinates is 10^3) */
-
-#define GL2PS_EPSILON       5.0e-3F
-#define GL2PS_ZSCALE        1000.0F
-#define GL2PS_ZOFFSET       5.0e-2F
-#define GL2PS_ZOFFSET_LARGE 20.0F
-#define GL2PS_ZERO(arg)     (fabs(arg) < 1.e-20)
-
-/* Primitive types */
-
-#define GL2PS_NO_TYPE          -1
-#define GL2PS_TEXT             1
-#define GL2PS_POINT            2
-#define GL2PS_LINE             3
-#define GL2PS_QUADRANGLE       4
-#define GL2PS_TRIANGLE         5
-#define GL2PS_PIXMAP           6
-#define GL2PS_IMAGEMAP         7
-#define GL2PS_IMAGEMAP_WRITTEN 8
-#define GL2PS_IMAGEMAP_VISIBLE 9
-#define GL2PS_SPECIAL          10
-
-/* BSP tree primitive comparison */
-
-#define GL2PS_COINCIDENT  1
-#define GL2PS_IN_FRONT_OF 2
-#define GL2PS_IN_BACK_OF  3
-#define GL2PS_SPANNING    4
-
-/* 2D BSP tree primitive comparison */
-
-#define GL2PS_POINT_COINCIDENT 0
-#define GL2PS_POINT_INFRONT    1
-#define GL2PS_POINT_BACK       2
-
-/* Internal feedback buffer pass-through tokens */
-
-#define GL2PS_BEGIN_OFFSET_TOKEN   1
-#define GL2PS_END_OFFSET_TOKEN     2
-#define GL2PS_BEGIN_BOUNDARY_TOKEN 3
-#define GL2PS_END_BOUNDARY_TOKEN   4
-#define GL2PS_BEGIN_STIPPLE_TOKEN  5
-#define GL2PS_END_STIPPLE_TOKEN    6
-#define GL2PS_POINT_SIZE_TOKEN     7
-#define GL2PS_LINE_WIDTH_TOKEN     8
-#define GL2PS_BEGIN_BLEND_TOKEN    9
-#define GL2PS_END_BLEND_TOKEN      10
-#define GL2PS_SRC_BLEND_TOKEN      11
-#define GL2PS_DST_BLEND_TOKEN      12
-#define GL2PS_IMAGEMAP_TOKEN       13
-#define GL2PS_DRAW_PIXELS_TOKEN    14
-#define GL2PS_TEXT_TOKEN           15
-
-typedef enum {
-  T_UNDEFINED    = -1,
-  T_CONST_COLOR  = 1,
-  T_VAR_COLOR    = 1<<1,
-  T_ALPHA_1      = 1<<2,
-  T_ALPHA_LESS_1 = 1<<3,
-  T_VAR_ALPHA    = 1<<4
-} GL2PS_TRIANGLE_PROPERTY;
-
-typedef GLfloat GL2PSxyz[3];
-typedef GLfloat GL2PSplane[4];
-
-typedef struct _GL2PSbsptree2d GL2PSbsptree2d;
-
-struct _GL2PSbsptree2d {
-  GL2PSplane plane;
-  GL2PSbsptree2d *front, *back;
-};
-
-typedef struct {
-  GLint nmax, size, incr, n;
-  char *array;
-} GL2PSlist;
-
-typedef struct _GL2PSbsptree GL2PSbsptree;
-
-struct _GL2PSbsptree {
-  GL2PSplane plane;
-  GL2PSlist *primitives;
-  GL2PSbsptree *front, *back;
-};
-
-typedef struct {
-  GL2PSxyz xyz;
-  GL2PSrgba rgba;
-} GL2PSvertex;
-
-typedef struct {
-  GL2PSvertex vertex[3];
-  int prop;
-} GL2PStriangle;
-
-typedef struct {
-  GLshort fontsize;
-  char *str, *fontname;
-  /* Note: for a 'special' string, 'alignment' holds the format
-     (PostScript, PDF, etc.) of the special string */
-  GLint alignment;
-  GLfloat angle;
-} GL2PSstring;
-
-typedef struct {
-  GLsizei width, height;
-  /* Note: for an imagemap, 'type' indicates if it has already been
-     written to the file or not, and 'format' indicates if it is
-     visible or not */
-  GLenum format, type;
-  GLfloat zoom_x, zoom_y;
-  GLfloat *pixels;
-} GL2PSimage;
-
-typedef struct _GL2PSimagemap GL2PSimagemap;
-
-struct _GL2PSimagemap {
-  GL2PSimage *image;
-  GL2PSimagemap *next;
-};
-
-typedef struct {
-  GLshort type, numverts;
-  GLushort pattern;
-  char boundary, offset, culled;
-  GLint factor;
-  GLfloat width;
-  GL2PSvertex *verts;
-  union {
-    GL2PSstring *text;
-    GL2PSimage *image;
-  } data;
-} GL2PSprimitive;
-
-typedef struct {
-#if defined(GL2PS_HAVE_ZLIB)
-  Bytef *dest, *src, *start;
-  uLongf destLen, srcLen;
-#else
-  int dummy;
-#endif
-} GL2PScompress;
-
-typedef struct{
-  GL2PSlist* ptrlist;
-  int gsno, fontno, imno, shno, maskshno, trgroupno;
-  int gsobjno, fontobjno, imobjno, shobjno, maskshobjno, trgroupobjno;
-} GL2PSpdfgroup;
-
-typedef struct {
-  /* General */
-  GLint format, sort, options, colorsize, colormode, buffersize;
-  char *title, *producer, *filename;
-  GLboolean boundary, blending;
-  GLfloat *feedback, offset[2], lastlinewidth;
-  GLint viewport[4], blendfunc[2], lastfactor;
-  GL2PSrgba *colormap, lastrgba, threshold, bgcolor;
-  GLushort lastpattern;
-  GL2PSvertex lastvertex;
-  GL2PSlist *primitives, *auxprimitives;
-  FILE *stream;
-  GL2PScompress *compress;
-  GLboolean header;
-
-  /* BSP-specific */
-  GLint maxbestroot;
-
-  /* Occlusion culling-specific */
-  GLboolean zerosurfacearea;
-  GL2PSbsptree2d *imagetree;
-  GL2PSprimitive *primitivetoadd;
-
-  /* PDF-specific */
-  int streamlength;
-  GL2PSlist *pdfprimlist, *pdfgrouplist;
-  int *xreflist;
-  int objects_stack; /* available objects */
-  int extgs_stack; /* graphics state object number */
-  int font_stack; /* font object number */
-  int im_stack; /* image object number */
-  int trgroupobjects_stack; /* xobject numbers */
-  int shader_stack; /* shader object numbers */
-  int mshader_stack; /* mask shader object numbers */
-
-  /* for image map list */
-  GL2PSimagemap *imagemap_head;
-  GL2PSimagemap *imagemap_tail;
-} GL2PScontext;
-
-typedef struct {
-  void  (*printHeader)(void);
-  void  (*printFooter)(void);
-  void  (*beginViewport)(GLint viewport[4]);
-  GLint (*endViewport)(void);
-  void  (*printPrimitive)(void *data);
-  void  (*printFinalPrimitive)(void);
-  const char *file_extension;
-  const char *description;
-} GL2PSbackend;
-
-/* The gl2ps context. gl2ps is not thread safe (we should create a
-   local GL2PScontext during gl2psBeginPage) */
-
-static GL2PScontext *gl2ps = NULL;
-
-/* Need to forward-declare this one */
-
-static GLint gl2psPrintPrimitives(void);
-
-/*********************************************************************
- *
- * Utility routines
- *
- *********************************************************************/
-
-static void gl2psMsg(GLint level, const char *fmt, ...)
-{
-  va_list args;
-
-  if(!(gl2ps->options & GL2PS_SILENT)){
-    switch(level){
-    case GL2PS_INFO : fprintf(stderr, "GL2PS info: "); break;
-    case GL2PS_WARNING : fprintf(stderr, "GL2PS warning: "); break;
-    case GL2PS_ERROR : fprintf(stderr, "GL2PS error: "); break;
-    }
-    va_start(args, fmt);
-    vfprintf(stderr, fmt, args);
-    va_end(args);
-    fprintf(stderr, "\n");
-  }
-  /* if(level == GL2PS_ERROR) exit(1); */
-}
-
-static void *gl2psMalloc(size_t size)
-{
-  void *ptr;
-
-  if(!size) return NULL;
-  ptr = malloc(size);
-  if(!ptr){
-    gl2psMsg(GL2PS_ERROR, "Couldn't allocate requested memory");
-    return NULL;
-  }
-  return ptr;
-}
-
-static void *gl2psRealloc(void *ptr, size_t size)
-{
-  void *orig = ptr;
-  if(!size) return NULL;
-  ptr = realloc(orig, size);
-  if(!ptr){
-    gl2psMsg(GL2PS_ERROR, "Couldn't reallocate requested memory");
-    free(orig);
-    return NULL;
-  }
-  return ptr;
-}
-
-static void gl2psFree(void *ptr)
-{
-  if(!ptr) return;
-  free(ptr);
-}
-
-static int gl2psWriteBigEndian(unsigned long data, int bytes)
-{
-  int i;
-  int size = sizeof(unsigned long);
-  for(i = 1; i <= bytes; ++i){
-    fputc(0xff & (data >> (size - i) * 8), gl2ps->stream);
-  }
-  return bytes;
-}
-
-/* zlib compression helper routines */
-
-#if defined(GL2PS_HAVE_ZLIB)
-
-static void gl2psSetupCompress(void)
-{
-  gl2ps->compress = (GL2PScompress*)gl2psMalloc(sizeof(GL2PScompress));
-  gl2ps->compress->src = NULL;
-  gl2ps->compress->start = NULL;
-  gl2ps->compress->dest = NULL;
-  gl2ps->compress->srcLen = 0;
-  gl2ps->compress->destLen = 0;
-}
-
-static void gl2psFreeCompress(void)
-{
-  if(!gl2ps->compress)
-    return;
-  gl2psFree(gl2ps->compress->start);
-  gl2psFree(gl2ps->compress->dest);
-  gl2ps->compress->src = NULL;
-  gl2ps->compress->start = NULL;
-  gl2ps->compress->dest = NULL;
-  gl2ps->compress->srcLen = 0;
-  gl2ps->compress->destLen = 0;
-}
-
-static int gl2psAllocCompress(unsigned int srcsize)
-{
-  gl2psFreeCompress();
-
-  if(!gl2ps->compress || !srcsize)
-    return GL2PS_ERROR;
-
-  gl2ps->compress->srcLen = srcsize;
-  gl2ps->compress->destLen = (int)ceil(1.001 * gl2ps->compress->srcLen + 12);
-  gl2ps->compress->src = (Bytef*)gl2psMalloc(gl2ps->compress->srcLen);
-  gl2ps->compress->start = gl2ps->compress->src;
-  gl2ps->compress->dest = (Bytef*)gl2psMalloc(gl2ps->compress->destLen);
-
-  return GL2PS_SUCCESS;
-}
-
-static void *gl2psReallocCompress(unsigned int srcsize)
-{
-  if(!gl2ps->compress || !srcsize)
-    return NULL;
-
-  if(srcsize < gl2ps->compress->srcLen)
-    return gl2ps->compress->start;
-
-  gl2ps->compress->srcLen = srcsize;
-  gl2ps->compress->destLen = (int)ceil(1.001 * gl2ps->compress->srcLen + 12);
-  gl2ps->compress->src = (Bytef*)gl2psRealloc(gl2ps->compress->src,
-                                              gl2ps->compress->srcLen);
-  gl2ps->compress->start = gl2ps->compress->src;
-  gl2ps->compress->dest = (Bytef*)gl2psRealloc(gl2ps->compress->dest,
-                                               gl2ps->compress->destLen);
-
-  return gl2ps->compress->start;
-}
-
-static int gl2psWriteBigEndianCompress(unsigned long data, int bytes)
-{
-  int i;
-  int size = sizeof(unsigned long);
-  for(i = 1; i <= bytes; ++i){
-    *gl2ps->compress->src = (Bytef)(0xff & (data >> (size-i) * 8));
-    ++gl2ps->compress->src;
-  }
-  return bytes;
-}
-
-static int gl2psDeflate(void)
-{
-  /* For compatibility with older zlib versions, we use compress(...)
-     instead of compress2(..., Z_BEST_COMPRESSION) */
-  return compress(gl2ps->compress->dest, &gl2ps->compress->destLen,
-                  gl2ps->compress->start, gl2ps->compress->srcLen);
-}
-
-#endif
-
-static int gl2psPrintf(const char* fmt, ...)
-{
-  int ret;
-  va_list args;
-
-#if defined(GL2PS_HAVE_ZLIB)
-  unsigned int oldsize = 0;
-  static char buf[1000];
-  if(gl2ps->options & GL2PS_COMPRESS){
-    va_start(args, fmt);
-    ret = vsprintf(buf, fmt, args);
-    va_end(args);
-    oldsize = gl2ps->compress->srcLen;
-    gl2ps->compress->start = (Bytef*)gl2psReallocCompress(oldsize + ret);
-    memcpy(gl2ps->compress->start+oldsize, buf, ret);
-    ret = 0;
-  }
-  else{
-#endif
-    va_start(args, fmt);
-    ret = vfprintf(gl2ps->stream, fmt, args);
-    va_end(args);
-#if defined(GL2PS_HAVE_ZLIB)
-  }
-#endif
-  return ret;
-}
-
-static void gl2psPrintGzipHeader(void)
-{
-#if defined(GL2PS_HAVE_ZLIB)
-  char tmp[10] = {'\x1f', '\x8b', /* magic numbers: 0x1f, 0x8b */
-                  8, /* compression method: Z_DEFLATED */
-                  0, /* flags */
-                  0, 0, 0, 0, /* time */
-                  2, /* extra flags: max compression */
-                  '\x03'}; /* OS code: 0x03 (Unix) */
-
-  if(gl2ps->options & GL2PS_COMPRESS){
-    gl2psSetupCompress();
-    /* add the gzip file header */
-    fwrite(tmp, 10, 1, gl2ps->stream);
-  }
-#endif
-}
-
-static void gl2psPrintGzipFooter(void)
-{
-#if defined(GL2PS_HAVE_ZLIB)
-  int n;
-  uLong crc, len;
-  char tmp[8];
-
-  if(gl2ps->options & GL2PS_COMPRESS){
-    if(Z_OK != gl2psDeflate()){
-      gl2psMsg(GL2PS_ERROR, "Zlib deflate error");
-    }
-    else{
-      /* determine the length of the header in the zlib stream */
-      n = 2; /* CMF+FLG */
-      if(gl2ps->compress->dest[1] & (1<<5)){
-        n += 4; /* DICTID */
-      }
-      /* write the data, without the zlib header and footer */
-      fwrite(gl2ps->compress->dest+n, gl2ps->compress->destLen-(n+4),
-             1, gl2ps->stream);
-      /* add the gzip file footer */
-      crc = crc32(0L, gl2ps->compress->start, gl2ps->compress->srcLen);
-      for(n = 0; n < 4; ++n){
-        tmp[n] = (char)(crc & 0xff);
-        crc >>= 8;
-      }
-      len = gl2ps->compress->srcLen;
-      for(n = 4; n < 8; ++n){
-        tmp[n] = (char)(len & 0xff);
-        len >>= 8;
-      }
-      fwrite(tmp, 8, 1, gl2ps->stream);
-    }
-    gl2psFreeCompress();
-    gl2psFree(gl2ps->compress);
-    gl2ps->compress = NULL;
-  }
-#endif
-}
-
-/* The list handling routines */
-
-static void gl2psListRealloc(GL2PSlist *list, GLint n)
-{
-  if(!list){
-    gl2psMsg(GL2PS_ERROR, "Cannot reallocate NULL list");
-    return;
-  }
-  if(n <= 0) return;
-  if(!list->array){
-    list->nmax = n;
-    list->array = (char*)gl2psMalloc(list->nmax * list->size);
-  }
-  else{
-    if(n > list->nmax){
-      list->nmax = ((n - 1) / list->incr + 1) * list->incr;
-      list->array = (char*)gl2psRealloc(list->array,
-                                        list->nmax * list->size);
-    }
-  }
-}
-
-static GL2PSlist *gl2psListCreate(GLint n, GLint incr, GLint size)
-{
-  GL2PSlist *list;
-
-  if(n < 0) n = 0;
-  if(incr <= 0) incr = 1;
-  list = (GL2PSlist*)gl2psMalloc(sizeof(GL2PSlist));
-  list->nmax = 0;
-  list->incr = incr;
-  list->size = size;
-  list->n = 0;
-  list->array = NULL;
-  gl2psListRealloc(list, n);
-  return list;
-}
-
-static void gl2psListReset(GL2PSlist *list)
-{
-  if(!list) return;
-  list->n = 0;
-}
-
-static void gl2psListDelete(GL2PSlist *list)
-{
-  if(!list) return;
-  gl2psFree(list->array);
-  gl2psFree(list);
-}
-
-static void gl2psListAdd(GL2PSlist *list, void *data)
-{
-  if(!list){
-    gl2psMsg(GL2PS_ERROR, "Cannot add into unallocated list");
-    return;
-  }
-  list->n++;
-  gl2psListRealloc(list, list->n);
-  memcpy(&list->array[(list->n - 1) * list->size], data, list->size);
-}
-
-static int gl2psListNbr(GL2PSlist *list)
-{
-  if(!list)
-    return 0;
-  return list->n;
-}
-
-static void *gl2psListPointer(GL2PSlist *list, GLint index)
-{
-  if(!list){
-    gl2psMsg(GL2PS_ERROR, "Cannot point into unallocated list");
-    return NULL;
-  }
-  if((index < 0) || (index >= list->n)){
-    gl2psMsg(GL2PS_ERROR, "Wrong list index in gl2psListPointer");
-    return NULL;
-  }
-  return &list->array[index * list->size];
-}
-
-static void gl2psListSort(GL2PSlist *list,
-                          int (*fcmp)(const void *a, const void *b))
-{
-  if(!list)
-    return;
-  qsort(list->array, list->n, list->size, fcmp);
-}
-
-static void gl2psListAction(GL2PSlist *list, void (*action)(void *data))
-{
-  GLint i;
-
-  for(i = 0; i < gl2psListNbr(list); i++){
-    (*action)(gl2psListPointer(list, i));
-  }
-}
-
-static void gl2psListActionInverse(GL2PSlist *list, void (*action)(void *data))
-{
-  GLint i;
-
-  for(i = gl2psListNbr(list); i > 0; i--){
-    (*action)(gl2psListPointer(list, i-1));
-  }
-}
-
-#if defined(GL2PS_HAVE_LIBPNG)
-
-static void gl2psListRead(GL2PSlist *list, int index, void *data)
-{
-  if((index < 0) || (index >= list->n))
-    gl2psMsg(GL2PS_ERROR, "Wrong list index in gl2psListRead");
-  memcpy(data, &list->array[index * list->size], list->size);
-}
-
-static void gl2psEncodeBase64Block(unsigned char in[3], unsigned char out[4], int len)
-{
-  static const char cb64[] =
-    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
-  out[0] = cb64[ in[0] >> 2 ];
-  out[1] = cb64[ ((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4) ];
-  out[2] = (len > 1) ? cb64[ ((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6) ] : '=';
-  out[3] = (len > 2) ? cb64[ in[2] & 0x3f ] : '=';
-}
-
-static void gl2psListEncodeBase64(GL2PSlist *list)
-{
-  unsigned char *buffer, in[3], out[4];
-  int i, n, index, len;
-
-  n = list->n * list->size;
-  buffer = (unsigned char*)gl2psMalloc(n * sizeof(unsigned char));
-  memcpy(buffer, list->array, n * sizeof(unsigned char));
-  gl2psListReset(list);
-
-  index = 0;
-  while(index < n) {
-    len = 0;
-    for(i = 0; i < 3; i++) {
-      if(index < n){
-        in[i] = buffer[index];
-        len++;
-      }
-      else{
-        in[i] = 0;
-      }
-      index++;
-    }
-    if(len) {
-      gl2psEncodeBase64Block(in, out, len);
-      for(i = 0; i < 4; i++)
-        gl2psListAdd(list, &out[i]);
-    }
-  }
-  gl2psFree(buffer);
-}
-
-#endif
-
-/* Helpers for rgba colors */
-
-static GLboolean gl2psSameColor(GL2PSrgba rgba1, GL2PSrgba rgba2)
-{
-  if(!GL2PS_ZERO(rgba1[0] - rgba2[0]) ||
-     !GL2PS_ZERO(rgba1[1] - rgba2[1]) ||
-     !GL2PS_ZERO(rgba1[2] - rgba2[2]))
-    return GL_FALSE;
-  return GL_TRUE;
-}
-
-static GLboolean gl2psVertsSameColor(const GL2PSprimitive *prim)
-{
-  int i;
-
-  for(i = 1; i < prim->numverts; i++){
-    if(!gl2psSameColor(prim->verts[0].rgba, prim->verts[i].rgba)){
-      return GL_FALSE;
-    }
-  }
-  return GL_TRUE;
-}
-
-static GLboolean gl2psSameColorThreshold(int n, GL2PSrgba rgba[],
-                                         GL2PSrgba threshold)
-{
-  int i;
-
-  if(n < 2) return GL_TRUE;
-
-  for(i = 1; i < n; i++){
-    if(fabs(rgba[0][0] - rgba[i][0]) > threshold[0] ||
-       fabs(rgba[0][1] - rgba[i][1]) > threshold[1] ||
-       fabs(rgba[0][2] - rgba[i][2]) > threshold[2])
-      return GL_FALSE;
-  }
-
-  return GL_TRUE;
-}
-
-static void gl2psSetLastColor(GL2PSrgba rgba)
-{
-  int i;
-  for(i = 0; i < 3; ++i){
-    gl2ps->lastrgba[i] = rgba[i];
-  }
-}
-
-static GLfloat gl2psGetRGB(GL2PSimage *im, GLuint x, GLuint y,
-                           GLfloat *red, GLfloat *green, GLfloat *blue)
-{
-
-  GLsizei width = im->width;
-  GLsizei height = im->height;
-  GLfloat *pixels = im->pixels;
-  GLfloat *pimag;
-
-  /* OpenGL image is from down to up, PS image is up to down */
-  switch(im->format){
-  case GL_RGBA:
-    pimag = pixels + 4 * (width * (height - 1 - y) + x);
-    break;
-  case GL_RGB:
-  default:
-    pimag = pixels + 3 * (width * (height - 1 - y) + x);
-    break;
-  }
-  *red = *pimag; pimag++;
-  *green = *pimag; pimag++;
-  *blue = *pimag; pimag++;
-
-  return (im->format == GL_RGBA) ? *pimag : 1.0F;
-}
-
-/* Helper routines for pixmaps */
-
-static GL2PSimage *gl2psCopyPixmap(GL2PSimage *im)
-{
-  int size;
-  GL2PSimage *image = (GL2PSimage*)gl2psMalloc(sizeof(GL2PSimage));
-
-  image->width = im->width;
-  image->height = im->height;
-  image->format = im->format;
-  image->type = im->type;
-  image->zoom_x = im->zoom_x;
-  image->zoom_y = im->zoom_y;
-
-  switch(image->format){
-  case GL_RGBA:
-    size = image->height * image->width * 4 * sizeof(GLfloat);
-    break;
-  case GL_RGB:
-  default:
-    size = image->height * image->width * 3 * sizeof(GLfloat);
-    break;
-  }
-
-  image->pixels = (GLfloat*)gl2psMalloc(size);
-  memcpy(image->pixels, im->pixels, size);
-
-  return image;
-}
-
-static void gl2psFreePixmap(GL2PSimage *im)
-{
-  if(!im)
-    return;
-  gl2psFree(im->pixels);
-  gl2psFree(im);
-}
-
-#if defined(GL2PS_HAVE_LIBPNG)
-
-#if !defined(png_jmpbuf)
-#  define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf)
-#endif
-
-static void gl2psUserWritePNG(png_structp png_ptr, png_bytep data, png_size_t length)
-{
-  unsigned int i;
-  GL2PSlist *png = (GL2PSlist*)png_get_io_ptr(png_ptr);
-  for(i = 0; i < length; i++)
-    gl2psListAdd(png, &data[i]);
-}
-
-static void gl2psUserFlushPNG(png_structp png_ptr)
-{
-  (void) png_ptr;  /* not used */
-}
-
-static void gl2psConvertPixmapToPNG(GL2PSimage *pixmap, GL2PSlist *png)
-{
-  png_structp png_ptr;
-  png_infop info_ptr;
-  unsigned char *row_data;
-  GLfloat dr, dg, db;
-  int row, col;
-
-  if(!(png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)))
-    return;
-
-  if(!(info_ptr = png_create_info_struct(png_ptr))){
-    png_destroy_write_struct(&png_ptr, NULL);
-    return;
-  }
-
-  if(setjmp(png_jmpbuf(png_ptr))) {
-    png_destroy_write_struct(&png_ptr, &info_ptr);
-    return;
-  }
-
-  png_set_write_fn(png_ptr, (void *)png, gl2psUserWritePNG, gl2psUserFlushPNG);
-  png_set_compression_level(png_ptr, Z_DEFAULT_COMPRESSION);
-  png_set_IHDR(png_ptr, info_ptr, pixmap->width, pixmap->height, 8,
-               PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
-               PNG_FILTER_TYPE_BASE);
-  png_write_info(png_ptr, info_ptr);
-
-  row_data = (unsigned char*)gl2psMalloc(3 * pixmap->width * sizeof(unsigned char));
-  for(row = 0; row < pixmap->height; row++){
-    for(col = 0; col < pixmap->width; col++){
-      gl2psGetRGB(pixmap, col, row, &dr, &dg, &db);
-      row_data[3*col] = (unsigned char)(255. * dr);
-      row_data[3*col+1] = (unsigned char)(255. * dg);
-      row_data[3*col+2] = (unsigned char)(255. * db);
-    }
-    png_write_row(png_ptr, (png_bytep)row_data);
-  }
-  gl2psFree(row_data);
-
-  png_write_end(png_ptr, info_ptr);
-  png_destroy_write_struct(&png_ptr, &info_ptr);
-}
-
-#endif
-
-/* Helper routines for text strings */
-
-static GLint gl2psAddText(GLint type, const char *str, const char *fontname,
-                          GLshort fontsize, GLint alignment, GLfloat angle)
-{
-  GLfloat pos[4];
-  GL2PSprimitive *prim;
-  GLboolean valid;
-
-  if(!gl2ps || !str || !fontname) return GL2PS_UNINITIALIZED;
-
-  if(gl2ps->options & GL2PS_NO_TEXT) return GL2PS_SUCCESS;
-
-  glGetBooleanv(GL_CURRENT_RASTER_POSITION_VALID, &valid);
-  if(GL_FALSE == valid) return GL2PS_SUCCESS; /* the primitive is culled */
-
-  glGetFloatv(GL_CURRENT_RASTER_POSITION, pos);
-
-  prim = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
-  prim->type = type;
-  prim->boundary = 0;
-  prim->numverts = 1;
-  prim->verts = (GL2PSvertex*)gl2psMalloc(sizeof(GL2PSvertex));
-  prim->verts[0].xyz[0] = pos[0];
-  prim->verts[0].xyz[1] = pos[1];
-  prim->verts[0].xyz[2] = pos[2];
-  prim->culled = 0;
-  prim->offset = 0;
-  prim->pattern = 0;
-  prim->factor = 0;
-  prim->width = 1;
-  glGetFloatv(GL_CURRENT_RASTER_COLOR, prim->verts[0].rgba);
-  prim->data.text = (GL2PSstring*)gl2psMalloc(sizeof(GL2PSstring));
-  prim->data.text->str = (char*)gl2psMalloc((strlen(str)+1)*sizeof(char));
-  strcpy(prim->data.text->str, str);
-  prim->data.text->fontname = (char*)gl2psMalloc((strlen(fontname)+1)*sizeof(char));
-  strcpy(prim->data.text->fontname, fontname);
-  prim->data.text->fontsize = fontsize;
-  prim->data.text->alignment = alignment;
-  prim->data.text->angle = angle;
-
-  gl2psListAdd(gl2ps->auxprimitives, &prim);
-  glPassThrough(GL2PS_TEXT_TOKEN);
-
-  return GL2PS_SUCCESS;
-}
-
-static GL2PSstring *gl2psCopyText(GL2PSstring *t)
-{
-  GL2PSstring *text = (GL2PSstring*)gl2psMalloc(sizeof(GL2PSstring));
-  text->str = (char*)gl2psMalloc((strlen(t->str)+1)*sizeof(char));
-  strcpy(text->str, t->str);
-  text->fontname = (char*)gl2psMalloc((strlen(t->fontname)+1)*sizeof(char));
-  strcpy(text->fontname, t->fontname);
-  text->fontsize = t->fontsize;
-  text->alignment = t->alignment;
-  text->angle = t->angle;
-
-  return text;
-}
-
-static void gl2psFreeText(GL2PSstring *text)
-{
-  if(!text)
-    return;
-  gl2psFree(text->str);
-  gl2psFree(text->fontname);
-  gl2psFree(text);
-}
-
-/* Helpers for blending modes */
-
-static GLboolean gl2psSupportedBlendMode(GLenum sfactor, GLenum dfactor)
-{
-  /* returns TRUE if gl2ps supports the argument combination: only two
-     blending modes have been implemented so far */
-
-  if( (sfactor == GL_SRC_ALPHA && dfactor == GL_ONE_MINUS_SRC_ALPHA) ||
-      (sfactor == GL_ONE && dfactor == GL_ZERO) )
-    return GL_TRUE;
-  return GL_FALSE;
-}
-
-static void gl2psAdaptVertexForBlending(GL2PSvertex *v)
-{
-  /* Transforms vertex depending on the actual blending function -
-     currently the vertex v is considered as source vertex and his
-     alpha value is changed to 1.0 if source blending GL_ONE is
-     active. This might be extended in the future */
-
-  if(!v || !gl2ps)
-    return;
-
-  if(gl2ps->options & GL2PS_NO_BLENDING || !gl2ps->blending){
-    v->rgba[3] = 1.0F;
-    return;
-  }
-
-  switch(gl2ps->blendfunc[0]){
-  case GL_ONE:
-    v->rgba[3] = 1.0F;
-    break;
-  default:
-    break;
-  }
-}
-
-static void gl2psAssignTriangleProperties(GL2PStriangle *t)
-{
-  /* int i; */
-
-  t->prop = T_VAR_COLOR;
-
-  /* Uncommenting the following lines activates an even more fine
-     grained distinction between triangle types - please don't delete,
-     a remarkable amount of PDF handling code inside this file depends
-     on it if activated */
-  /*
-  t->prop = T_CONST_COLOR;
-  for(i = 0; i < 3; ++i){
-    if(!GL2PS_ZERO(t->vertex[0].rgba[i] - t->vertex[1].rgba[i]) ||
-       !GL2PS_ZERO(t->vertex[1].rgba[i] - t->vertex[2].rgba[i])){
-      t->prop = T_VAR_COLOR;
-      break;
-    }
-  }
-  */
-
-  if(!GL2PS_ZERO(t->vertex[0].rgba[3] - t->vertex[1].rgba[3]) ||
-     !GL2PS_ZERO(t->vertex[1].rgba[3] - t->vertex[2].rgba[3])){
-    t->prop |= T_VAR_ALPHA;
-  }
-  else{
-    if(t->vertex[0].rgba[3] < 1)
-      t->prop |= T_ALPHA_LESS_1;
-    else
-      t->prop |= T_ALPHA_1;
-  }
-}
-
-static void gl2psFillTriangleFromPrimitive(GL2PStriangle *t, GL2PSprimitive *p,
-                                           GLboolean assignprops)
-{
-  t->vertex[0] = p->verts[0];
-  t->vertex[1] = p->verts[1];
-  t->vertex[2] = p->verts[2];
-  if(GL_TRUE == assignprops)
-    gl2psAssignTriangleProperties(t);
-}
-
-static void gl2psInitTriangle(GL2PStriangle *t)
-{
-  int i;
-  GL2PSvertex vertex = { {-1.0F, -1.0F, -1.0F}, {-1.0F, -1.0F, -1.0F, -1.0F} };
-  for(i = 0; i < 3; i++)
-    t->vertex[i] = vertex;
-  t->prop = T_UNDEFINED;
-}
-
-/* Miscellaneous helper routines */
-
-static GL2PSprimitive *gl2psCopyPrimitive(GL2PSprimitive *p)
-{
-  GL2PSprimitive *prim;
-
-  if(!p){
-    gl2psMsg(GL2PS_ERROR, "Trying to copy an empty primitive");
-    return NULL;
-  }
-
-  prim = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
-
-  prim->type = p->type;
-  prim->numverts = p->numverts;
-  prim->boundary = p->boundary;
-  prim->offset = p->offset;
-  prim->pattern = p->pattern;
-  prim->factor = p->factor;
-  prim->culled = p->culled;
-  prim->width = p->width;
-  prim->verts = (GL2PSvertex*)gl2psMalloc(p->numverts*sizeof(GL2PSvertex));
-  memcpy(prim->verts, p->verts, p->numverts * sizeof(GL2PSvertex));
-
-  switch(prim->type){
-  case GL2PS_PIXMAP :
-    prim->data.image = gl2psCopyPixmap(p->data.image);
-    break;
-  case GL2PS_TEXT :
-  case GL2PS_SPECIAL :
-    prim->data.text = gl2psCopyText(p->data.text);
-    break;
-  default:
-    break;
-  }
-
-  return prim;
-}
-
-static GLboolean gl2psSamePosition(GL2PSxyz p1, GL2PSxyz p2)
-{
-  if(!GL2PS_ZERO(p1[0] - p2[0]) ||
-     !GL2PS_ZERO(p1[1] - p2[1]) ||
-     !GL2PS_ZERO(p1[2] - p2[2]))
-    return GL_FALSE;
-  return GL_TRUE;
-}
-
-/*********************************************************************
- *
- * 3D sorting routines
- *
- *********************************************************************/
-
-static GLfloat gl2psComparePointPlane(GL2PSxyz point, GL2PSplane plane)
-{
-  return (plane[0] * point[0] +
-          plane[1] * point[1] +
-          plane[2] * point[2] +
-          plane[3]);
-}
-
-static GLfloat gl2psPsca(GLfloat *a, GLfloat *b)
-{
-  return (a[0]*b[0] + a[1]*b[1] + a[2]*b[2]);
-}
-
-static void gl2psPvec(GLfloat *a, GLfloat *b, GLfloat *c)
-{
-  c[0] = a[1]*b[2] - a[2]*b[1];
-  c[1] = a[2]*b[0] - a[0]*b[2];
-  c[2] = a[0]*b[1] - a[1]*b[0];
-}
-
-static GLfloat gl2psNorm(GLfloat *a)
-{
-  return (GLfloat)sqrt(a[0]*a[0] + a[1]*a[1] + a[2]*a[2]);
-}
-
-static void gl2psGetNormal(GLfloat *a, GLfloat *b, GLfloat *c)
-{
-  GLfloat norm;
-
-  gl2psPvec(a, b, c);
-  if(!GL2PS_ZERO(norm = gl2psNorm(c))){
-    c[0] = c[0] / norm;
-    c[1] = c[1] / norm;
-    c[2] = c[2] / norm;
-  }
-  else{
-    /* The plane is still wrong despite our tests in gl2psGetPlane.
-       Let's return a dummy value for now (this is a hack: we should
-       do more intelligent tests in GetPlane) */
-    c[0] = c[1] = 0.0F;
-    c[2] = 1.0F;
-  }
-}
-
-static void gl2psGetPlane(GL2PSprimitive *prim, GL2PSplane plane)
-{
-  GL2PSxyz v = {0.0F, 0.0F, 0.0F}, w = {0.0F, 0.0F, 0.0F};
-
-  switch(prim->type){
-  case GL2PS_TRIANGLE :
-  case GL2PS_QUADRANGLE :
-    v[0] = prim->verts[1].xyz[0] - prim->verts[0].xyz[0];
-    v[1] = prim->verts[1].xyz[1] - prim->verts[0].xyz[1];
-    v[2] = prim->verts[1].xyz[2] - prim->verts[0].xyz[2];
-    w[0] = prim->verts[2].xyz[0] - prim->verts[0].xyz[0];
-    w[1] = prim->verts[2].xyz[1] - prim->verts[0].xyz[1];
-    w[2] = prim->verts[2].xyz[2] - prim->verts[0].xyz[2];
-    if((GL2PS_ZERO(v[0]) && GL2PS_ZERO(v[1]) && GL2PS_ZERO(v[2])) ||
-       (GL2PS_ZERO(w[0]) && GL2PS_ZERO(w[1]) && GL2PS_ZERO(w[2]))){
-      plane[0] = plane[1] = 0.0F;
-      plane[2] = 1.0F;
-      plane[3] = -prim->verts[0].xyz[2];
-    }
-    else{
-      gl2psGetNormal(v, w, plane);
-      plane[3] =
-        - plane[0] * prim->verts[0].xyz[0]
-        - plane[1] * prim->verts[0].xyz[1]
-        - plane[2] * prim->verts[0].xyz[2];
-    }
-    break;
-  case GL2PS_LINE :
-    v[0] = prim->verts[1].xyz[0] - prim->verts[0].xyz[0];
-    v[1] = prim->verts[1].xyz[1] - prim->verts[0].xyz[1];
-    v[2] = prim->verts[1].xyz[2] - prim->verts[0].xyz[2];
-    if(GL2PS_ZERO(v[0]) && GL2PS_ZERO(v[1]) && GL2PS_ZERO(v[2])){
-      plane[0] = plane[1] = 0.0F;
-      plane[2] = 1.0F;
-      plane[3] = -prim->verts[0].xyz[2];
-    }
-    else{
-      if(GL2PS_ZERO(v[0]))      w[0] = 1.0F;
-      else if(GL2PS_ZERO(v[1])) w[1] = 1.0F;
-      else                      w[2] = 1.0F;
-      gl2psGetNormal(v, w, plane);
-      plane[3] =
-        - plane[0] * prim->verts[0].xyz[0]
-        - plane[1] * prim->verts[0].xyz[1]
-        - plane[2] * prim->verts[0].xyz[2];
-    }
-    break;
-  case GL2PS_POINT :
-  case GL2PS_PIXMAP :
-  case GL2PS_TEXT :
-  case GL2PS_SPECIAL :
-  case GL2PS_IMAGEMAP:
-    plane[0] = plane[1] = 0.0F;
-    plane[2] = 1.0F;
-    plane[3] = -prim->verts[0].xyz[2];
-    break;
-  default :
-    gl2psMsg(GL2PS_ERROR, "Unknown primitive type in BSP tree");
-    plane[0] = plane[1] = plane[3] = 0.0F;
-    plane[2] = 1.0F;
-    break;
-  }
-}
-
-static void gl2psCutEdge(GL2PSvertex *a, GL2PSvertex *b, GL2PSplane plane,
-                         GL2PSvertex *c)
-{
-  GL2PSxyz v;
-  GLfloat sect, psca;
-
-  v[0] = b->xyz[0] - a->xyz[0];
-  v[1] = b->xyz[1] - a->xyz[1];
-  v[2] = b->xyz[2] - a->xyz[2];
-
-  if(!GL2PS_ZERO(psca = gl2psPsca(plane, v)))
-    sect = -gl2psComparePointPlane(a->xyz, plane) / psca;
-  else
-    sect = 0.0F;
-
-  c->xyz[0] = a->xyz[0] + v[0] * sect;
-  c->xyz[1] = a->xyz[1] + v[1] * sect;
-  c->xyz[2] = a->xyz[2] + v[2] * sect;
-
-  c->rgba[0] = (1 - sect) * a->rgba[0] + sect * b->rgba[0];
-  c->rgba[1] = (1 - sect) * a->rgba[1] + sect * b->rgba[1];
-  c->rgba[2] = (1 - sect) * a->rgba[2] + sect * b->rgba[2];
-  c->rgba[3] = (1 - sect) * a->rgba[3] + sect * b->rgba[3];
-}
-
-static void gl2psCreateSplitPrimitive(GL2PSprimitive *parent, GL2PSplane plane,
-                                      GL2PSprimitive *child, GLshort numverts,
-                                      GLshort *index0, GLshort *index1)
-{
-  GLshort i;
-
-  if(parent->type == GL2PS_IMAGEMAP){
-    child->type = GL2PS_IMAGEMAP;
-    child->data.image = parent->data.image;
-  }
-  else{
-    if(numverts > 4){
-      gl2psMsg(GL2PS_WARNING, "%d vertices in polygon", numverts);
-      numverts = 4;
-    }
-    switch(numverts){
-    case 1 : child->type = GL2PS_POINT; break;
-    case 2 : child->type = GL2PS_LINE; break;
-    case 3 : child->type = GL2PS_TRIANGLE; break;
-    case 4 : child->type = GL2PS_QUADRANGLE; break;
-    default: child->type = GL2PS_NO_TYPE; break;
-    }
-  }
-
-  child->boundary = 0; /* FIXME: not done! */
-  child->culled = parent->culled;
-  child->offset = parent->offset;
-  child->pattern = parent->pattern;
-  child->factor = parent->factor;
-  child->width = parent->width;
-  child->numverts = numverts;
-  child->verts = (GL2PSvertex*)gl2psMalloc(numverts * sizeof(GL2PSvertex));
-
-  for(i = 0; i < numverts; i++){
-    if(index1[i] < 0){
-      child->verts[i] = parent->verts[index0[i]];
-    }
-    else{
-      gl2psCutEdge(&parent->verts[index0[i]], &parent->verts[index1[i]],
-                   plane, &child->verts[i]);
-    }
-  }
-}
-
-static void gl2psAddIndex(GLshort *index0, GLshort *index1, GLshort *nb,
-                          GLshort i, GLshort j)
-{
-  GLint k;
-
-  for(k = 0; k < *nb; k++){
-    if((index0[k] == i && index1[k] == j) ||
-       (index1[k] == i && index0[k] == j)) return;
-  }
-  index0[*nb] = i;
-  index1[*nb] = j;
-  (*nb)++;
-}
-
-static GLshort gl2psGetIndex(GLshort i, GLshort num)
-{
-  return (i < num - 1) ? i + 1 : 0;
-}
-
-static GLint gl2psTestSplitPrimitive(GL2PSprimitive *prim, GL2PSplane plane)
-{
-  GLint type = GL2PS_COINCIDENT;
-  GLshort i, j;
-  GLfloat d[5];
-
-  for(i = 0; i < prim->numverts; i++){
-    d[i] = gl2psComparePointPlane(prim->verts[i].xyz, plane);
-  }
-
-  if(prim->numverts < 2){
-    return 0;
-  }
-  else{
-    for(i = 0; i < prim->numverts; i++){
-      j = gl2psGetIndex(i, prim->numverts);
-      if(d[j] > GL2PS_EPSILON){
-        if(type == GL2PS_COINCIDENT)      type = GL2PS_IN_BACK_OF;
-        else if(type != GL2PS_IN_BACK_OF) return 1;
-        if(d[i] < -GL2PS_EPSILON)         return 1;
-      }
-      else if(d[j] < -GL2PS_EPSILON){
-        if(type == GL2PS_COINCIDENT)       type = GL2PS_IN_FRONT_OF;
-        else if(type != GL2PS_IN_FRONT_OF) return 1;
-        if(d[i] > GL2PS_EPSILON)           return 1;
-      }
-    }
-  }
-  return 0;
-}
-
-static GLint gl2psSplitPrimitive(GL2PSprimitive *prim, GL2PSplane plane,
-                                 GL2PSprimitive **front, GL2PSprimitive **back)
-{
-  GLshort i, j, in = 0, out = 0, in0[5], in1[5], out0[5], out1[5];
-  GLint type;
-  GLfloat d[5];
-
-  type = GL2PS_COINCIDENT;
-
-  for(i = 0; i < prim->numverts; i++){
-    d[i] = gl2psComparePointPlane(prim->verts[i].xyz, plane);
-  }
-
-  switch(prim->type){
-  case GL2PS_POINT :
-    if(d[0] > GL2PS_EPSILON)       type = GL2PS_IN_BACK_OF;
-    else if(d[0] < -GL2PS_EPSILON) type = GL2PS_IN_FRONT_OF;
-    else                           type = GL2PS_COINCIDENT;
-    break;
-  default :
-    for(i = 0; i < prim->numverts; i++){
-      j = gl2psGetIndex(i, prim->numverts);
-      if(d[j] > GL2PS_EPSILON){
-        if(type == GL2PS_COINCIDENT)      type = GL2PS_IN_BACK_OF;
-        else if(type != GL2PS_IN_BACK_OF) type = GL2PS_SPANNING;
-        if(d[i] < -GL2PS_EPSILON){
-          gl2psAddIndex(in0, in1, &in, i, j);
-          gl2psAddIndex(out0, out1, &out, i, j);
-          type = GL2PS_SPANNING;
-        }
-        gl2psAddIndex(out0, out1, &out, j, -1);
-      }
-      else if(d[j] < -GL2PS_EPSILON){
-        if(type == GL2PS_COINCIDENT)       type = GL2PS_IN_FRONT_OF;
-        else if(type != GL2PS_IN_FRONT_OF) type = GL2PS_SPANNING;
-        if(d[i] > GL2PS_EPSILON){
-          gl2psAddIndex(in0, in1, &in, i, j);
-          gl2psAddIndex(out0, out1, &out, i, j);
-          type = GL2PS_SPANNING;
-        }
-        gl2psAddIndex(in0, in1, &in, j, -1);
-      }
-      else{
-        gl2psAddIndex(in0, in1, &in, j, -1);
-        gl2psAddIndex(out0, out1, &out, j, -1);
-      }
-    }
-    break;
-  }
-
-  if(type == GL2PS_SPANNING){
-    *back = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
-    *front = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
-    gl2psCreateSplitPrimitive(prim, plane, *back, out, out0, out1);
-    gl2psCreateSplitPrimitive(prim, plane, *front, in, in0, in1);
-  }
-
-  return type;
-}
-
-static void gl2psDivideQuad(GL2PSprimitive *quad,
-                            GL2PSprimitive **t1, GL2PSprimitive **t2)
-{
-  *t1 = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
-  *t2 = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
-  (*t1)->type = (*t2)->type = GL2PS_TRIANGLE;
-  (*t1)->numverts = (*t2)->numverts = 3;
-  (*t1)->culled = (*t2)->culled = quad->culled;
-  (*t1)->offset = (*t2)->offset = quad->offset;
-  (*t1)->pattern = (*t2)->pattern = quad->pattern;
-  (*t1)->factor = (*t2)->factor = quad->factor;
-  (*t1)->width = (*t2)->width = quad->width;
-  (*t1)->verts = (GL2PSvertex*)gl2psMalloc(3 * sizeof(GL2PSvertex));
-  (*t2)->verts = (GL2PSvertex*)gl2psMalloc(3 * sizeof(GL2PSvertex));
-  (*t1)->verts[0] = quad->verts[0];
-  (*t1)->verts[1] = quad->verts[1];
-  (*t1)->verts[2] = quad->verts[2];
-  (*t1)->boundary = ((quad->boundary & 1) ? 1 : 0) | ((quad->boundary & 2) ? 2 : 0);
-  (*t2)->verts[0] = quad->verts[0];
-  (*t2)->verts[1] = quad->verts[2];
-  (*t2)->verts[2] = quad->verts[3];
-  (*t2)->boundary = ((quad->boundary & 4) ? 2 : 0) | ((quad->boundary & 8) ? 4 : 0);
-}
-
-static int gl2psCompareDepth(const void *a, const void *b)
-{
-  const GL2PSprimitive *q, *w;
-  GLfloat dq = 0.0F, dw = 0.0F, diff;
-  int i;
-
-  q = *(const GL2PSprimitive* const*)a;
-  w = *(const GL2PSprimitive* const*)b;
-
-  for(i = 0; i < q->numverts; i++){
-    dq += q->verts[i].xyz[2];
-  }
-  dq /= (GLfloat)q->numverts;
-
-  for(i = 0; i < w->numverts; i++){
-    dw += w->verts[i].xyz[2];
-  }
-  dw /= (GLfloat)w->numverts;
-
-  diff = dq - dw;
-  if(diff > 0.){
-    return -1;
-  }
-  else if(diff < 0.){
-    return 1;
-  }
-  else{
-    return 0;
-  }
-}
-
-static int gl2psTrianglesFirst(const void *a, const void *b)
-{
-  const GL2PSprimitive *q, *w;
-
-  q = *(const GL2PSprimitive* const*)a;
-  w = *(const GL2PSprimitive* const*)b;
-  return (q->type < w->type ? 1 : -1);
-}
-
-static GLint gl2psFindRoot(GL2PSlist *primitives, GL2PSprimitive **root)
-{
-  GLint i, j, count, best = 1000000, index = 0;
-  GL2PSprimitive *prim1, *prim2;
-  GL2PSplane plane;
-  GLint maxp;
-
-  if(!gl2psListNbr(primitives)){
-    gl2psMsg(GL2PS_ERROR, "Cannot fint root in empty primitive list");
-    return 0;
-  }
-
-  *root = *(GL2PSprimitive**)gl2psListPointer(primitives, 0);
-
-  if(gl2ps->options & GL2PS_BEST_ROOT){
-    maxp = gl2psListNbr(primitives);
-    if(maxp > gl2ps->maxbestroot){
-      maxp = gl2ps->maxbestroot;
-    }
-    for(i = 0; i < maxp; i++){
-      prim1 = *(GL2PSprimitive**)gl2psListPointer(primitives, i);
-      gl2psGetPlane(prim1, plane);
-      count = 0;
-      for(j = 0; j < gl2psListNbr(primitives); j++){
-        if(j != i){
-          prim2 = *(GL2PSprimitive**)gl2psListPointer(primitives, j);
-          count += gl2psTestSplitPrimitive(prim2, plane);
-        }
-        if(count > best) break;
-      }
-      if(count < best){
-        best = count;
-        index = i;
-        *root = prim1;
-        if(!count) return index;
-      }
-    }
-    /* if(index) gl2psMsg(GL2PS_INFO, "GL2PS_BEST_ROOT was worth it: %d", index); */
-    return index;
-  }
-  else{
-    return 0;
-  }
-}
-
-static void gl2psFreeImagemap(GL2PSimagemap *list)
-{
-  GL2PSimagemap *next;
-  while(list != NULL){
-    next = list->next;
-    gl2psFree(list->image->pixels);
-    gl2psFree(list->image);
-    gl2psFree(list);
-    list = next;
-  }
-}
-
-static void gl2psFreePrimitive(void *data)
-{
-  GL2PSprimitive *q;
-
-  q = *(GL2PSprimitive**)data;
-  gl2psFree(q->verts);
-  if(q->type == GL2PS_TEXT || q->type == GL2PS_SPECIAL){
-    gl2psFreeText(q->data.text);
-  }
-  else if(q->type == GL2PS_PIXMAP){
-    gl2psFreePixmap(q->data.image);
-  }
-  gl2psFree(q);
-}
-
-static void gl2psAddPrimitiveInList(GL2PSprimitive *prim, GL2PSlist *list)
-{
-  GL2PSprimitive *t1, *t2;
-
-  if(prim->type != GL2PS_QUADRANGLE){
-    gl2psListAdd(list, &prim);
-  }
-  else{
-    gl2psDivideQuad(prim, &t1, &t2);
-    gl2psListAdd(list, &t1);
-    gl2psListAdd(list, &t2);
-    gl2psFreePrimitive(&prim);
-  }
-
-}
-
-static void gl2psFreeBspTree(GL2PSbsptree **tree)
-{
-  if(*tree){
-    if((*tree)->back) gl2psFreeBspTree(&(*tree)->back);
-    if((*tree)->primitives){
-      gl2psListAction((*tree)->primitives, gl2psFreePrimitive);
-      gl2psListDelete((*tree)->primitives);
-    }
-    if((*tree)->front) gl2psFreeBspTree(&(*tree)->front);
-    gl2psFree(*tree);
-    *tree = NULL;
-  }
-}
-
-static GLboolean gl2psGreater(GLfloat f1, GLfloat f2)
-{
-  if(f1 > f2) return GL_TRUE;
-  else return GL_FALSE;
-}
-
-static GLboolean gl2psLess(GLfloat f1, GLfloat f2)
-{
-  if(f1 < f2) return GL_TRUE;
-  else return GL_FALSE;
-}
-
-static void gl2psBuildBspTree(GL2PSbsptree *tree, GL2PSlist *primitives)
-{
-  GL2PSprimitive *prim, *frontprim = NULL, *backprim = NULL;
-  GL2PSlist *frontlist, *backlist;
-  GLint i, index;
-
-  tree->front = NULL;
-  tree->back = NULL;
-  tree->primitives = gl2psListCreate(1, 2, sizeof(GL2PSprimitive*));
-  index = gl2psFindRoot(primitives, &prim);
-  gl2psGetPlane(prim, tree->plane);
-  gl2psAddPrimitiveInList(prim, tree->primitives);
-
-  frontlist = gl2psListCreate(1, 2, sizeof(GL2PSprimitive*));
-  backlist = gl2psListCreate(1, 2, sizeof(GL2PSprimitive*));
-
-  for(i = 0; i < gl2psListNbr(primitives); i++){
-    if(i != index){
-      prim = *(GL2PSprimitive**)gl2psListPointer(primitives,i);
-      switch(gl2psSplitPrimitive(prim, tree->plane, &frontprim, &backprim)){
-      case GL2PS_COINCIDENT:
-        gl2psAddPrimitiveInList(prim, tree->primitives);
-        break;
-      case GL2PS_IN_BACK_OF:
-        gl2psAddPrimitiveInList(prim, backlist);
-        break;
-      case GL2PS_IN_FRONT_OF:
-        gl2psAddPrimitiveInList(prim, frontlist);
-        break;
-      case GL2PS_SPANNING:
-        gl2psAddPrimitiveInList(backprim, backlist);
-        gl2psAddPrimitiveInList(frontprim, frontlist);
-        gl2psFreePrimitive(&prim);
-        break;
-      }
-    }
-  }
-
-  if(gl2psListNbr(tree->primitives)){
-    gl2psListSort(tree->primitives, gl2psTrianglesFirst);
-  }
-
-  if(gl2psListNbr(frontlist)){
-    gl2psListSort(frontlist, gl2psTrianglesFirst);
-    tree->front = (GL2PSbsptree*)gl2psMalloc(sizeof(GL2PSbsptree));
-    gl2psBuildBspTree(tree->front, frontlist);
-  }
-  else{
-    gl2psListDelete(frontlist);
-  }
-
-  if(gl2psListNbr(backlist)){
-    gl2psListSort(backlist, gl2psTrianglesFirst);
-    tree->back = (GL2PSbsptree*)gl2psMalloc(sizeof(GL2PSbsptree));
-    gl2psBuildBspTree(tree->back, backlist);
-  }
-  else{
-    gl2psListDelete(backlist);
-  }
-
-  gl2psListDelete(primitives);
-}
-
-static void gl2psTraverseBspTree(GL2PSbsptree *tree, GL2PSxyz eye, GLfloat epsilon,
-                                 GLboolean (*compare)(GLfloat f1, GLfloat f2),
-                                 void (*action)(void *data), int inverse)
-{
-  GLfloat result;
-
-  if(!tree) return;
-
-  result = gl2psComparePointPlane(eye, tree->plane);
-
-  if(GL_TRUE == compare(result, epsilon)){
-    gl2psTraverseBspTree(tree->back, eye, epsilon, compare, action, inverse);
-    if(inverse){
-      gl2psListActionInverse(tree->primitives, action);
-    }
-    else{
-      gl2psListAction(tree->primitives, action);
-    }
-    gl2psTraverseBspTree(tree->front, eye, epsilon, compare, action, inverse);
-  }
-  else if(GL_TRUE == compare(-epsilon, result)){
-    gl2psTraverseBspTree(tree->front, eye, epsilon, compare, action, inverse);
-    if(inverse){
-      gl2psListActionInverse(tree->primitives, action);
-    }
-    else{
-      gl2psListAction(tree->primitives, action);
-    }
-    gl2psTraverseBspTree(tree->back, eye, epsilon, compare, action, inverse);
-  }
-  else{
-    gl2psTraverseBspTree(tree->front, eye, epsilon, compare, action, inverse);
-    gl2psTraverseBspTree(tree->back, eye, epsilon, compare, action, inverse);
-  }
-}
-
-static void gl2psRescaleAndOffset(void)
-{
-  GL2PSprimitive *prim;
-  GLfloat minZ, maxZ, rangeZ, scaleZ;
-  GLfloat factor, units, area, dZ, dZdX, dZdY, maxdZ;
-  int i, j;
-
-  if(!gl2psListNbr(gl2ps->primitives))
-    return;
-
-  /* get z-buffer range */
-  prim = *(GL2PSprimitive**)gl2psListPointer(gl2ps->primitives, 0);
-  minZ = maxZ = prim->verts[0].xyz[2];
-  for(i = 1; i < prim->numverts; i++){
-    if(prim->verts[i].xyz[2] < minZ) minZ = prim->verts[i].xyz[2];
-    if(prim->verts[i].xyz[2] > maxZ) maxZ = prim->verts[i].xyz[2];
-  }
-  for(i = 1; i < gl2psListNbr(gl2ps->primitives); i++){
-    prim = *(GL2PSprimitive**)gl2psListPointer(gl2ps->primitives, i);
-    for(j = 0; j < prim->numverts; j++){
-      if(prim->verts[j].xyz[2] < minZ) minZ = prim->verts[j].xyz[2];
-      if(prim->verts[j].xyz[2] > maxZ) maxZ = prim->verts[j].xyz[2];
-    }
-  }
-  rangeZ = (maxZ - minZ);
-
-  /* rescale z-buffer coordinate in [0,GL2PS_ZSCALE], to make it of
-     the same order of magnitude as the x and y coordinates */
-  scaleZ = GL2PS_ZERO(rangeZ) ? GL2PS_ZSCALE : (GL2PS_ZSCALE / rangeZ);
-  /* avoid precision loss (we use floats!) */
-  if(scaleZ > 100000.F) scaleZ = 100000.F;
-
-  /* apply offsets */
-  for(i = 0; i < gl2psListNbr(gl2ps->primitives); i++){
-    prim = *(GL2PSprimitive**)gl2psListPointer(gl2ps->primitives, i);
-    for(j = 0; j < prim->numverts; j++){
-      prim->verts[j].xyz[2] = (prim->verts[j].xyz[2] - minZ) * scaleZ;
-    }
-    if((gl2ps->options & GL2PS_SIMPLE_LINE_OFFSET) &&
-       (prim->type == GL2PS_LINE)){
-      if(gl2ps->sort == GL2PS_SIMPLE_SORT){
-        prim->verts[0].xyz[2] -= GL2PS_ZOFFSET_LARGE;
-        prim->verts[1].xyz[2] -= GL2PS_ZOFFSET_LARGE;
-      }
-      else{
-        prim->verts[0].xyz[2] -= GL2PS_ZOFFSET;
-        prim->verts[1].xyz[2] -= GL2PS_ZOFFSET;
-      }
-    }
-    else if(prim->offset && (prim->type == GL2PS_TRIANGLE)){
-      factor = gl2ps->offset[0];
-      units = gl2ps->offset[1];
-      area =
-        (prim->verts[1].xyz[0] - prim->verts[0].xyz[0]) *
-        (prim->verts[2].xyz[1] - prim->verts[1].xyz[1]) -
-        (prim->verts[2].xyz[0] - prim->verts[1].xyz[0]) *
-        (prim->verts[1].xyz[1] - prim->verts[0].xyz[1]);
-      if(!GL2PS_ZERO(area)){
-        dZdX =
-          ((prim->verts[2].xyz[1] - prim->verts[1].xyz[1]) *
-           (prim->verts[1].xyz[2] - prim->verts[0].xyz[2]) -
-           (prim->verts[1].xyz[1] - prim->verts[0].xyz[1]) *
-           (prim->verts[2].xyz[2] - prim->verts[1].xyz[2])) / area;
-        dZdY =
-          ((prim->verts[1].xyz[0] - prim->verts[0].xyz[0]) *
-           (prim->verts[2].xyz[2] - prim->verts[1].xyz[2]) -
-           (prim->verts[2].xyz[0] - prim->verts[1].xyz[0]) *
-           (prim->verts[1].xyz[2] - prim->verts[0].xyz[2])) / area;
-        maxdZ = (GLfloat)sqrt(dZdX * dZdX + dZdY * dZdY);
-      }
-      else{
-        maxdZ = 0.0F;
-      }
-      dZ = factor * maxdZ + units;
-      prim->verts[0].xyz[2] += dZ;
-      prim->verts[1].xyz[2] += dZ;
-      prim->verts[2].xyz[2] += dZ;
-    }
-  }
-}
-
-/*********************************************************************
- *
- * 2D sorting routines (for occlusion culling)
- *
- *********************************************************************/
-
-static GLint gl2psGetPlaneFromPoints(GL2PSxyz a, GL2PSxyz b, GL2PSplane plane)
-{
-  GLfloat n;
-
-  plane[0] = b[1] - a[1];
-  plane[1] = a[0] - b[0];
-  n = (GLfloat)sqrt(plane[0]*plane[0] + plane[1]*plane[1]);
-  plane[2] = 0.0F;
-  if(!GL2PS_ZERO(n)){
-    plane[0] /= n;
-    plane[1] /= n;
-    plane[3] = -plane[0]*a[0]-plane[1]*a[1];
-    return 1;
-  }
-  else{
-    plane[0] = -1.0F;
-    plane[1] = 0.0F;
-    plane[3] = a[0];
-    return 0;
-  }
-}
-
-static void gl2psFreeBspImageTree(GL2PSbsptree2d **tree)
-{
-  if(*tree){
-    if((*tree)->back)  gl2psFreeBspImageTree(&(*tree)->back);
-    if((*tree)->front) gl2psFreeBspImageTree(&(*tree)->front);
-    gl2psFree(*tree);
-    *tree = NULL;
-  }
-}
-
-static GLint gl2psCheckPoint(GL2PSxyz point, GL2PSplane plane)
-{
-  GLfloat pt_dis;
-
-  pt_dis = gl2psComparePointPlane(point, plane);
-  if(pt_dis > GL2PS_EPSILON)        return GL2PS_POINT_INFRONT;
-  else if(pt_dis < -GL2PS_EPSILON)  return GL2PS_POINT_BACK;
-  else                              return GL2PS_POINT_COINCIDENT;
-}
-
-static void gl2psAddPlanesInBspTreeImage(GL2PSprimitive *prim,
-                                         GL2PSbsptree2d **tree)
-{
-  GLint ret = 0;
-  GLint i;
-  GLint offset = 0;
-  GL2PSbsptree2d *head = NULL, *cur = NULL;
-
-  if((*tree == NULL) && (prim->numverts > 2)){
-    /* don't cull if transparent
-    for(i = 0; i < prim->numverts - 1; i++)
-      if(prim->verts[i].rgba[3] < 1.0F) return;
-    */
-    head = (GL2PSbsptree2d*)gl2psMalloc(sizeof(GL2PSbsptree2d));
-    for(i = 0; i < prim->numverts-1; i++){
-      if(!gl2psGetPlaneFromPoints(prim->verts[i].xyz,
-                                  prim->verts[i+1].xyz,
-                                  head->plane)){
-        if(prim->numverts-i > 3){
-          offset++;
-        }
-        else{
-          gl2psFree(head);
-          return;
-        }
-      }
-      else{
-        break;
-      }
-    }
-    head->back = NULL;
-    head->front = NULL;
-    for(i = 2+offset; i < prim->numverts; i++){
-      ret = gl2psCheckPoint(prim->verts[i].xyz, head->plane);
-      if(ret != GL2PS_POINT_COINCIDENT) break;
-    }
-    switch(ret){
-    case GL2PS_POINT_INFRONT :
-      cur = head;
-      for(i = 1+offset; i < prim->numverts-1; i++){
-        if(cur->front == NULL){
-          cur->front = (GL2PSbsptree2d*)gl2psMalloc(sizeof(GL2PSbsptree2d));
-        }
-        if(gl2psGetPlaneFromPoints(prim->verts[i].xyz,
-                                   prim->verts[i+1].xyz,
-                                   cur->front->plane)){
-          cur = cur->front;
-          cur->front = NULL;
-          cur->back = NULL;
-        }
-      }
-      if(cur->front == NULL){
-        cur->front = (GL2PSbsptree2d*)gl2psMalloc(sizeof(GL2PSbsptree2d));
-      }
-      if(gl2psGetPlaneFromPoints(prim->verts[i].xyz,
-                                 prim->verts[offset].xyz,
-                                 cur->front->plane)){
-        cur->front->front = NULL;
-        cur->front->back = NULL;
-      }
-      else{
-        gl2psFree(cur->front);
-        cur->front = NULL;
-      }
-      break;
-    case GL2PS_POINT_BACK :
-      for(i = 0; i < 4; i++){
-        head->plane[i] = -head->plane[i];
-      }
-      cur = head;
-      for(i = 1+offset; i < prim->numverts-1; i++){
-        if(cur->front == NULL){
-          cur->front = (GL2PSbsptree2d*)gl2psMalloc(sizeof(GL2PSbsptree2d));
-        }
-        if(gl2psGetPlaneFromPoints(prim->verts[i+1].xyz,
-                                   prim->verts[i].xyz,
-                                   cur->front->plane)){
-          cur = cur->front;
-          cur->front = NULL;
-          cur->back = NULL;
-        }
-      }
-      if(cur->front == NULL){
-        cur->front = (GL2PSbsptree2d*)gl2psMalloc(sizeof(GL2PSbsptree2d));
-      }
-      if(gl2psGetPlaneFromPoints(prim->verts[offset].xyz,
-                                 prim->verts[i].xyz,
-                                 cur->front->plane)){
-        cur->front->front = NULL;
-        cur->front->back = NULL;
-      }
-      else{
-        gl2psFree(cur->front);
-        cur->front = NULL;
-      }
-      break;
-    default:
-      gl2psFree(head);
-      return;
-    }
-    (*tree) = head;
-  }
-}
-
-static GLint gl2psCheckPrimitive(GL2PSprimitive *prim, GL2PSplane plane)
-{
-  GLint i;
-  GLint pos;
-
-  pos = gl2psCheckPoint(prim->verts[0].xyz, plane);
-  for(i = 1; i < prim->numverts; i++){
-    pos |= gl2psCheckPoint(prim->verts[i].xyz, plane);
-    if(pos == (GL2PS_POINT_INFRONT | GL2PS_POINT_BACK)) return GL2PS_SPANNING;
-  }
-  if(pos & GL2PS_POINT_INFRONT)   return GL2PS_IN_FRONT_OF;
-  else if(pos & GL2PS_POINT_BACK) return GL2PS_IN_BACK_OF;
-  else                            return GL2PS_COINCIDENT;
-}
-
-static GL2PSprimitive *gl2psCreateSplitPrimitive2D(GL2PSprimitive *parent,
-                                                   GLshort numverts,
-                                                   GL2PSvertex *vertx)
-{
-  GLint i;
-  GL2PSprimitive *child = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
-
-  if(parent->type == GL2PS_IMAGEMAP){
-    child->type = GL2PS_IMAGEMAP;
-    child->data.image = parent->data.image;
-  }
-  else {
-    switch(numverts){
-    case 1 : child->type = GL2PS_POINT; break;
-    case 2 : child->type = GL2PS_LINE; break;
-    case 3 : child->type = GL2PS_TRIANGLE; break;
-    case 4 : child->type = GL2PS_QUADRANGLE; break;
-    default: child->type = GL2PS_NO_TYPE; break; /* FIXME */
-    }
-  }
-  child->boundary = 0; /* FIXME: not done! */
-  child->culled = parent->culled;
-  child->offset = parent->offset;
-  child->pattern = parent->pattern;
-  child->factor = parent->factor;
-  child->width = parent->width;
-  child->numverts = numverts;
-  child->verts = (GL2PSvertex*)gl2psMalloc(numverts * sizeof(GL2PSvertex));
-  for(i = 0; i < numverts; i++){
-    child->verts[i] = vertx[i];
-  }
-  return child;
-}
-
-static void gl2psSplitPrimitive2D(GL2PSprimitive *prim,
-                                  GL2PSplane plane,
-                                  GL2PSprimitive **front,
-                                  GL2PSprimitive **back)
-{
-  /* cur will hold the position of the current vertex
-     prev will hold the position of the previous vertex
-     prev0 will hold the position of the vertex number 0
-     v1 and v2 represent the current and previous vertices, respectively
-     flag is set if the current vertex should be checked against the plane */
-  GLint cur = -1, prev = -1, i, v1 = 0, v2 = 0, flag = 1, prev0 = -1;
-
-  /* list of vertices that will go in front and back primitive */
-  GL2PSvertex *front_list = NULL, *back_list = NULL;
-
-  /* number of vertices in front and back list */
-  GLshort front_count = 0, back_count = 0;
-
-  for(i = 0; i <= prim->numverts; i++){
-    v1 = i;
-    if(v1 == prim->numverts){
-      if(prim->numverts < 3) break;
-      v1 = 0;
-      v2 = prim->numverts - 1;
-      cur = prev0;
-    }
-    else if(flag){
-      cur = gl2psCheckPoint(prim->verts[v1].xyz, plane);
-      if(i == 0){
-        prev0 = cur;
-      }
-    }
-    if(((prev == -1) || (prev == cur) || (prev == 0) || (cur == 0)) &&
-       (i < prim->numverts)){
-      if(cur == GL2PS_POINT_INFRONT){
-        front_count++;
-        front_list = (GL2PSvertex*)gl2psRealloc(front_list,
-                                                sizeof(GL2PSvertex)*front_count);
-        front_list[front_count-1] = prim->verts[v1];
-      }
-      else if(cur == GL2PS_POINT_BACK){
-        back_count++;
-        back_list = (GL2PSvertex*)gl2psRealloc(back_list,
-                                               sizeof(GL2PSvertex)*back_count);
-        back_list[back_count-1] = prim->verts[v1];
-      }
-      else{
-        front_count++;
-        front_list = (GL2PSvertex*)gl2psRealloc(front_list,
-                                                sizeof(GL2PSvertex)*front_count);
-        front_list[front_count-1] = prim->verts[v1];
-        back_count++;
-        back_list = (GL2PSvertex*)gl2psRealloc(back_list,
-                                               sizeof(GL2PSvertex)*back_count);
-        back_list[back_count-1] = prim->verts[v1];
-      }
-      flag = 1;
-    }
-    else if((prev != cur) && (cur != 0) && (prev != 0)){
-      if(v1 != 0){
-        v2 = v1-1;
-        i--;
-      }
-      front_count++;
-      front_list = (GL2PSvertex*)gl2psRealloc(front_list,
-                                              sizeof(GL2PSvertex)*front_count);
-      gl2psCutEdge(&prim->verts[v2], &prim->verts[v1],
-                   plane, &front_list[front_count-1]);
-      back_count++;
-      back_list = (GL2PSvertex*)gl2psRealloc(back_list,
-                                             sizeof(GL2PSvertex)*back_count);
-      back_list[back_count-1] = front_list[front_count-1];
-      flag = 0;
-    }
-    prev = cur;
-  }
-  *front = gl2psCreateSplitPrimitive2D(prim, front_count, front_list);
-  *back = gl2psCreateSplitPrimitive2D(prim, back_count, back_list);
-  gl2psFree(front_list);
-  gl2psFree(back_list);
-}
-
-static GLint gl2psAddInBspImageTree(GL2PSprimitive *prim, GL2PSbsptree2d **tree)
-{
-  GLint ret = 0;
-  GL2PSprimitive *frontprim = NULL, *backprim = NULL;
-
-  /* FIXME: until we consider the actual extent of text strings and
-     pixmaps, never cull them. Otherwise the whole string/pixmap gets
-     culled as soon as the reference point is hidden */
-  if(prim->type == GL2PS_PIXMAP ||
-     prim->type == GL2PS_TEXT ||
-     prim->type == GL2PS_SPECIAL){
-    return 1;
-  }
-
-  if(*tree == NULL){
-    if((prim->type != GL2PS_IMAGEMAP) && (GL_FALSE == gl2ps->zerosurfacearea)){
-      gl2psAddPlanesInBspTreeImage(gl2ps->primitivetoadd, tree);
-    }
-    return 1;
-  }
-  else{
-    switch(gl2psCheckPrimitive(prim, (*tree)->plane)){
-    case GL2PS_IN_BACK_OF: return gl2psAddInBspImageTree(prim, &(*tree)->back);
-    case GL2PS_IN_FRONT_OF:
-      if((*tree)->front != NULL) return gl2psAddInBspImageTree(prim, &(*tree)->front);
-      else                       return 0;
-    case GL2PS_SPANNING:
-      gl2psSplitPrimitive2D(prim, (*tree)->plane, &frontprim, &backprim);
-      ret = gl2psAddInBspImageTree(backprim, &(*tree)->back);
-      if((*tree)->front != NULL){
-        if(gl2psAddInBspImageTree(frontprim, &(*tree)->front)){
-          ret = 1;
-        }
-      }
-      gl2psFree(frontprim->verts);
-      gl2psFree(frontprim);
-      gl2psFree(backprim->verts);
-      gl2psFree(backprim);
-      return ret;
-    case GL2PS_COINCIDENT:
-      if((*tree)->back != NULL){
-        gl2ps->zerosurfacearea = GL_TRUE;
-        ret = gl2psAddInBspImageTree(prim, &(*tree)->back);
-        gl2ps->zerosurfacearea = GL_FALSE;
-        if(ret) return ret;
-      }
-      if((*tree)->front != NULL){
-        gl2ps->zerosurfacearea = GL_TRUE;
-        ret = gl2psAddInBspImageTree(prim, &(*tree)->front);
-        gl2ps->zerosurfacearea = GL_FALSE;
-        if(ret) return ret;
-      }
-      if(prim->type == GL2PS_LINE) return 1;
-      else                         return 0;
-    }
-  }
-  return 0;
-}
-
-static void gl2psAddInImageTree(void *data)
-{
-  GL2PSprimitive *prim = *(GL2PSprimitive **)data;
-  gl2ps->primitivetoadd = prim;
-  if(prim->type == GL2PS_IMAGEMAP && prim->data.image->format == GL2PS_IMAGEMAP_VISIBLE){
-    prim->culled = 1;
-  }
-  else if(!gl2psAddInBspImageTree(prim, &gl2ps->imagetree)){
-    prim->culled = 1;
-  }
-  else if(prim->type == GL2PS_IMAGEMAP){
-    prim->data.image->format = GL2PS_IMAGEMAP_VISIBLE;
-  }
-}
-
-/* Boundary construction */
-
-static void gl2psAddBoundaryInList(GL2PSprimitive *prim, GL2PSlist *list)
-{
-  GL2PSprimitive *b;
-  GLshort i;
-  GL2PSxyz c;
-
-  c[0] = c[1] = c[2] = 0.0F;
-  for(i = 0; i < prim->numverts; i++){
-    c[0] += prim->verts[i].xyz[0];
-    c[1] += prim->verts[i].xyz[1];
-  }
-  c[0] /= prim->numverts;
-  c[1] /= prim->numverts;
-
-  for(i = 0; i < prim->numverts; i++){
-    if(prim->boundary & (GLint)pow(2., i)){
-      b = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
-      b->type = GL2PS_LINE;
-      b->offset = prim->offset;
-      b->pattern = prim->pattern;
-      b->factor = prim->factor;
-      b->culled = prim->culled;
-      b->width = prim->width;
-      b->boundary = 0;
-      b->numverts = 2;
-      b->verts = (GL2PSvertex*)gl2psMalloc(2 * sizeof(GL2PSvertex));
-
-#if 0 /* FIXME: need to work on boundary offset... */
-      v[0] = c[0] - prim->verts[i].xyz[0];
-      v[1] = c[1] - prim->verts[i].xyz[1];
-      v[2] = 0.0F;
-      norm = gl2psNorm(v);
-      v[0] /= norm;
-      v[1] /= norm;
-      b->verts[0].xyz[0] = prim->verts[i].xyz[0] +0.1*v[0];
-      b->verts[0].xyz[1] = prim->verts[i].xyz[1] +0.1*v[1];
-      b->verts[0].xyz[2] = prim->verts[i].xyz[2];
-      v[0] = c[0] - prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[0];
-      v[1] = c[1] - prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[1];
-      norm = gl2psNorm(v);
-      v[0] /= norm;
-      v[1] /= norm;
-      b->verts[1].xyz[0] = prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[0] +0.1*v[0];
-      b->verts[1].xyz[1] = prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[1] +0.1*v[1];
-      b->verts[1].xyz[2] = prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[2];
-#else
-      b->verts[0].xyz[0] = prim->verts[i].xyz[0];
-      b->verts[0].xyz[1] = prim->verts[i].xyz[1];
-      b->verts[0].xyz[2] = prim->verts[i].xyz[2];
-      b->verts[1].xyz[0] = prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[0];
-      b->verts[1].xyz[1] = prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[1];
-      b->verts[1].xyz[2] = prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[2];
-#endif
-
-      b->verts[0].rgba[0] = 0.0F;
-      b->verts[0].rgba[1] = 0.0F;
-      b->verts[0].rgba[2] = 0.0F;
-      b->verts[0].rgba[3] = 0.0F;
-      b->verts[1].rgba[0] = 0.0F;
-      b->verts[1].rgba[1] = 0.0F;
-      b->verts[1].rgba[2] = 0.0F;
-      b->verts[1].rgba[3] = 0.0F;
-      gl2psListAdd(list, &b);
-    }
-  }
-
-}
-
-static void gl2psBuildPolygonBoundary(GL2PSbsptree *tree)
-{
-  GLint i;
-  GL2PSprimitive *prim;
-
-  if(!tree) return;
-  gl2psBuildPolygonBoundary(tree->back);
-  for(i = 0; i < gl2psListNbr(tree->primitives); i++){
-    prim = *(GL2PSprimitive**)gl2psListPointer(tree->primitives, i);
-    if(prim->boundary) gl2psAddBoundaryInList(prim, tree->primitives);
-  }
-  gl2psBuildPolygonBoundary(tree->front);
-}
-
-/*********************************************************************
- *
- * Feedback buffer parser
- *
- *********************************************************************/
-
-static void gl2psAddPolyPrimitive(GLshort type, GLshort numverts,
-                                  GL2PSvertex *verts, GLint offset,
-                                  GLushort pattern, GLint factor,
-                                  GLfloat width, char boundary)
-{
-  GL2PSprimitive *prim;
-
-  prim = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
-  prim->type = type;
-  prim->numverts = numverts;
-  prim->verts = (GL2PSvertex*)gl2psMalloc(numverts * sizeof(GL2PSvertex));
-  memcpy(prim->verts, verts, numverts * sizeof(GL2PSvertex));
-  prim->boundary = boundary;
-  prim->offset = offset;
-  prim->pattern = pattern;
-  prim->factor = factor;
-  prim->width = width;
-  prim->culled = 0;
-
-  /* FIXME: here we should have an option to split stretched
-     tris/quads to enhance SIMPLE_SORT */
-
-  gl2psListAdd(gl2ps->primitives, &prim);
-}
-
-static GLint gl2psGetVertex(GL2PSvertex *v, GLfloat *p)
-{
-  GLint i;
-
-  v->xyz[0] = p[0];
-  v->xyz[1] = p[1];
-  v->xyz[2] = p[2];
-
-  if(gl2ps->colormode == GL_COLOR_INDEX && gl2ps->colorsize > 0){
-    i = (GLint)(p[3] + 0.5);
-    v->rgba[0] = gl2ps->colormap[i][0];
-    v->rgba[1] = gl2ps->colormap[i][1];
-    v->rgba[2] = gl2ps->colormap[i][2];
-    v->rgba[3] = gl2ps->colormap[i][3];
-    return 4;
-  }
-  else{
-    v->rgba[0] = p[3];
-    v->rgba[1] = p[4];
-    v->rgba[2] = p[5];
-    v->rgba[3] = p[6];
-    return 7;
-  }
-}
-
-static void gl2psParseFeedbackBuffer(GLint used)
-{
-  char flag;
-  GLushort pattern = 0;
-  GLboolean boundary;
-  GLint i, sizeoffloat, count, v, vtot, offset = 0, factor = 0, auxindex = 0;
-  GLfloat lwidth = 1.0F, psize = 1.0F;
-  GLfloat *current;
-  GL2PSvertex vertices[3];
-  GL2PSprimitive *prim;
-  GL2PSimagemap *node;
-
-  current = gl2ps->feedback;
-  boundary = gl2ps->boundary = GL_FALSE;
-
-  while(used > 0){
-
-    if(GL_TRUE == boundary) gl2ps->boundary = GL_TRUE;
-
-    switch((GLint)*current){
-    case GL_POINT_TOKEN :
-      current ++;
-      used --;
-      i = gl2psGetVertex(&vertices[0], current);
-      current += i;
-      used    -= i;
-      gl2psAddPolyPrimitive(GL2PS_POINT, 1, vertices, 0,
-                            pattern, factor, psize, 0);
-      break;
-    case GL_LINE_TOKEN :
-    case GL_LINE_RESET_TOKEN :
-      current ++;
-      used --;
-      i = gl2psGetVertex(&vertices[0], current);
-      current += i;
-      used    -= i;
-      i = gl2psGetVertex(&vertices[1], current);
-      current += i;
-      used    -= i;
-      gl2psAddPolyPrimitive(GL2PS_LINE, 2, vertices, 0,
-                            pattern, factor, lwidth, 0);
-      break;
-    case GL_POLYGON_TOKEN :
-      count = (GLint)current[1];
-      current += 2;
-      used -= 2;
-      v = vtot = 0;
-      while(count > 0 && used > 0){
-        i = gl2psGetVertex(&vertices[v], current);
-        gl2psAdaptVertexForBlending(&vertices[v]);
-        current += i;
-        used    -= i;
-        count --;
-        vtot++;
-        if(v == 2){
-          if(GL_TRUE == boundary){
-            if(!count && vtot == 2) flag = 1|2|4;
-            else if(!count) flag = 2|4;
-            else if(vtot == 2) flag = 1|2;
-            else flag = 2;
-          }
-          else
-            flag = 0;
-          gl2psAddPolyPrimitive(GL2PS_TRIANGLE, 3, vertices, offset,
-                                pattern, factor, 1, flag);
-          vertices[1] = vertices[2];
-        }
-        else
-          v ++;
-      }
-      break;
-    case GL_BITMAP_TOKEN :
-    case GL_DRAW_PIXEL_TOKEN :
-    case GL_COPY_PIXEL_TOKEN :
-      current ++;
-      used --;
-      i = gl2psGetVertex(&vertices[0], current);
-      current += i;
-      used    -= i;
-      break;
-    case GL_PASS_THROUGH_TOKEN :
-      switch((GLint)current[1]){
-      case GL2PS_BEGIN_OFFSET_TOKEN : offset = 1; break;
-      case GL2PS_END_OFFSET_TOKEN : offset = 0; break;
-      case GL2PS_BEGIN_BOUNDARY_TOKEN : boundary = GL_TRUE; break;
-      case GL2PS_END_BOUNDARY_TOKEN : boundary = GL_FALSE; break;
-      case GL2PS_END_STIPPLE_TOKEN : pattern = factor = 0; break;
-      case GL2PS_BEGIN_BLEND_TOKEN : gl2ps->blending = GL_TRUE; break;
-      case GL2PS_END_BLEND_TOKEN : gl2ps->blending = GL_FALSE; break;
-      case GL2PS_BEGIN_STIPPLE_TOKEN :
-        current += 2;
-        used -= 2;
-        pattern = (GLushort)current[1];
-        current += 2;
-        used -= 2;
-        factor = (GLint)current[1];
-        break;
-      case GL2PS_SRC_BLEND_TOKEN :
-        current += 2;
-        used -= 2;
-        gl2ps->blendfunc[0] = (GLint)current[1];
-        break;
-      case GL2PS_DST_BLEND_TOKEN :
-        current += 2;
-        used -= 2;
-        gl2ps->blendfunc[1] = (GLint)current[1];
-        break;
-      case GL2PS_POINT_SIZE_TOKEN :
-        current += 2;
-        used -= 2;
-        psize = current[1];
-        break;
-      case GL2PS_LINE_WIDTH_TOKEN :
-        current += 2;
-        used -= 2;
-        lwidth = current[1];
-        break;
-      case GL2PS_IMAGEMAP_TOKEN :
-        prim = (GL2PSprimitive *)gl2psMalloc(sizeof(GL2PSprimitive));
-        prim->type = GL2PS_IMAGEMAP;
-        prim->boundary = 0;
-        prim->numverts = 4;
-        prim->verts = (GL2PSvertex *)gl2psMalloc(4 * sizeof(GL2PSvertex));
-        prim->culled = 0;
-        prim->offset = 0;
-        prim->pattern = 0;
-        prim->factor = 0;
-        prim->width = 1;
-
-        node = (GL2PSimagemap*)gl2psMalloc(sizeof(GL2PSimagemap));
-        node->image = (GL2PSimage*)gl2psMalloc(sizeof(GL2PSimage));
-        node->image->type = 0;
-        node->image->format = 0;
-        node->image->zoom_x = 1.0F;
-        node->image->zoom_y = 1.0F;
-        node->next = NULL;
-
-        if(gl2ps->imagemap_head == NULL)
-          gl2ps->imagemap_head = node;
-        else
-          gl2ps->imagemap_tail->next = node;
-        gl2ps->imagemap_tail = node;
-        prim->data.image = node->image;
-
-        current += 2; used -= 2;
-        i = gl2psGetVertex(&prim->verts[0], &current[1]);
-        current += i; used -= i;
-
-        node->image->width = (GLint)current[2];
-        current += 2; used -= 2;
-        node->image->height = (GLint)current[2];
-        prim->verts[0].xyz[0] = prim->verts[0].xyz[0] - (int)(node->image->width / 2) + 0.5F;
-        prim->verts[0].xyz[1] = prim->verts[0].xyz[1] - (int)(node->image->height / 2) + 0.5F;
-        for(i = 1; i < 4; i++){
-          for(v = 0; v < 3; v++){
-            prim->verts[i].xyz[v] = prim->verts[0].xyz[v];
-            prim->verts[i].rgba[v] = prim->verts[0].rgba[v];
-          }
-          prim->verts[i].rgba[v] = prim->verts[0].rgba[v];
-        }
-        prim->verts[1].xyz[0] = prim->verts[1].xyz[0] + node->image->width;
-        prim->verts[2].xyz[0] = prim->verts[1].xyz[0];
-        prim->verts[2].xyz[1] = prim->verts[2].xyz[1] + node->image->height;
-        prim->verts[3].xyz[1] = prim->verts[2].xyz[1];
-
-        sizeoffloat = sizeof(GLfloat);
-        v = 2 * sizeoffloat;
-        vtot = node->image->height + node->image->height *
-          ((node->image->width - 1) / 8);
-        node->image->pixels = (GLfloat*)gl2psMalloc(v + vtot);
-        node->image->pixels[0] = prim->verts[0].xyz[0];
-        node->image->pixels[1] = prim->verts[0].xyz[1];
-
-        for(i = 0; i < vtot; i += sizeoffloat){
-          current += 2; used -= 2;
-          if((vtot - i) >= 4)
-            memcpy(&(((char*)(node->image->pixels))[i + v]), &(current[2]), sizeoffloat);
-          else
-            memcpy(&(((char*)(node->image->pixels))[i + v]), &(current[2]), vtot - i);
-        }
-        current++; used--;
-        gl2psListAdd(gl2ps->primitives, &prim);
-        break;
-      case GL2PS_DRAW_PIXELS_TOKEN :
-      case GL2PS_TEXT_TOKEN :
-        if(auxindex < gl2psListNbr(gl2ps->auxprimitives))
-          gl2psListAdd(gl2ps->primitives,
-                       gl2psListPointer(gl2ps->auxprimitives, auxindex++));
-        else
-          gl2psMsg(GL2PS_ERROR, "Wrong number of auxiliary tokens in buffer");
-        break;
-      }
-      current += 2;
-      used -= 2;
-      break;
-    default :
-      gl2psMsg(GL2PS_WARNING, "Unknown token in buffer");
-      current ++;
-      used --;
-      break;
-    }
-  }
-
-  gl2psListReset(gl2ps->auxprimitives);
-}
-
-/*********************************************************************
- *
- * PostScript routines
- *
- *********************************************************************/
-
-static void gl2psWriteByte(unsigned char byte)
-{
-  unsigned char h = byte / 16;
-  unsigned char l = byte % 16;
-  gl2psPrintf("%x%x", h, l);
-}
-
-static void gl2psPrintPostScriptPixmap(GLfloat x, GLfloat y, GL2PSimage *im)
-{
-  GLuint nbhex, nbyte, nrgb, nbits;
-  GLuint row, col, ibyte, icase;
-  GLfloat dr, dg, db, fgrey;
-  unsigned char red = 0, green = 0, blue = 0, b, grey;
-  GLuint width = (GLuint)im->width;
-  GLuint height = (GLuint)im->height;
-
-  /* FIXME: should we define an option for these? Or just keep the
-     8-bit per component case? */
-  int greyscale = 0; /* set to 1 to output greyscale image */
-  int nbit = 8; /* number of bits per color compoment (2, 4 or 8) */
-
-  if((width <= 0) || (height <= 0)) return;
-
-  gl2psPrintf("gsave\n");
-  gl2psPrintf("%.2f %.2f translate\n", x, y);
-  gl2psPrintf("%.2f %.2f scale\n", width * im->zoom_x, height * im->zoom_y);
-
-  if(greyscale){ /* greyscale */
-    gl2psPrintf("/picstr %d string def\n", width);
-    gl2psPrintf("%d %d %d\n", width, height, 8);
-    gl2psPrintf("[ %d 0 0 -%d 0 %d ]\n", width, height, height);
-    gl2psPrintf("{ currentfile picstr readhexstring pop }\n");
-    gl2psPrintf("image\n");
-    for(row = 0; row < height; row++){
-      for(col = 0; col < width; col++){
-        gl2psGetRGB(im, col, row, &dr, &dg, &db);
-        fgrey = (0.30F * dr + 0.59F * dg + 0.11F * db);
-        grey = (unsigned char)(255. * fgrey);
-        gl2psWriteByte(grey);
-      }
-      gl2psPrintf("\n");
-    }
-    nbhex = width * height * 2;
-    gl2psPrintf("%%%% nbhex digit          :%d\n", nbhex);
-  }
-  else if(nbit == 2){ /* color, 2 bits for r and g and b; rgbs following each other */
-    nrgb = width  * 3;
-    nbits = nrgb * nbit;
-    nbyte = nbits / 8;
-    if((nbyte * 8) != nbits) nbyte++;
-    gl2psPrintf("/rgbstr %d string def\n", nbyte);
-    gl2psPrintf("%d %d %d\n", width, height, nbit);
-    gl2psPrintf("[ %d 0 0 -%d 0 %d ]\n", width, height, height);
-    gl2psPrintf("{ currentfile rgbstr readhexstring pop }\n");
-    gl2psPrintf("false 3\n");
-    gl2psPrintf("colorimage\n");
-    for(row = 0; row < height; row++){
-      icase = 1;
-      col = 0;
-      b = 0;
-      for(ibyte = 0; ibyte < nbyte; ibyte++){
-        if(icase == 1) {
-          if(col < width) {
-            gl2psGetRGB(im, col, row, &dr, &dg, &db);
-          }
-          else {
-            dr = dg = db = 0;
-          }
-          col++;
-          red = (unsigned char)(3. * dr);
-          green = (unsigned char)(3. * dg);
-          blue = (unsigned char)(3. * db);
-          b = red;
-          b = (b<<2) + green;
-          b = (b<<2) + blue;
-          if(col < width) {
-            gl2psGetRGB(im, col, row, &dr, &dg, &db);
-          }
-          else {
-            dr = dg = db = 0;
-          }
-          col++;
-          red = (unsigned char)(3. * dr);
-          green = (unsigned char)(3. * dg);
-          blue = (unsigned char)(3. * db);
-          b = (b<<2) + red;
-          gl2psWriteByte(b);
-          b = 0;
-          icase++;
-        }
-        else if(icase == 2) {
-          b = green;
-          b = (b<<2) + blue;
-          if(col < width) {
-            gl2psGetRGB(im, col, row, &dr, &dg, &db);
-          }
-          else {
-            dr = dg = db = 0;
-          }
-          col++;
-          red = (unsigned char)(3. * dr);
-          green = (unsigned char)(3. * dg);
-          blue = (unsigned char)(3. * db);
-          b = (b<<2) + red;
-          b = (b<<2) + green;
-          gl2psWriteByte(b);
-          b = 0;
-          icase++;
-        }
-        else if(icase == 3) {
-          b = blue;
-          if(col < width) {
-            gl2psGetRGB(im, col, row, &dr, &dg, &db);
-          }
-          else {
-            dr = dg = db = 0;
-          }
-          col++;
-          red = (unsigned char)(3. * dr);
-          green = (unsigned char)(3. * dg);
-          blue = (unsigned char)(3. * db);
-          b = (b<<2) + red;
-          b = (b<<2) + green;
-          b = (b<<2) + blue;
-          gl2psWriteByte(b);
-          b = 0;
-          icase = 1;
-        }
-      }
-      gl2psPrintf("\n");
-    }
-  }
-  else if(nbit == 4){ /* color, 4 bits for r and g and b; rgbs following each other */
-    nrgb = width  * 3;
-    nbits = nrgb * nbit;
-    nbyte = nbits / 8;
-    if((nbyte * 8) != nbits) nbyte++;
-    gl2psPrintf("/rgbstr %d string def\n", nbyte);
-    gl2psPrintf("%d %d %d\n", width, height, nbit);
-    gl2psPrintf("[ %d 0 0 -%d 0 %d ]\n", width, height, height);
-    gl2psPrintf("{ currentfile rgbstr readhexstring pop }\n");
-    gl2psPrintf("false 3\n");
-    gl2psPrintf("colorimage\n");
-    for(row = 0; row < height; row++){
-      col = 0;
-      icase = 1;
-      for(ibyte = 0; ibyte < nbyte; ibyte++){
-        if(icase == 1) {
-          if(col < width) {
-            gl2psGetRGB(im, col, row, &dr, &dg, &db);
-          }
-          else {
-            dr = dg = db = 0;
-          }
-          col++;
-          red = (unsigned char)(15. * dr);
-          green = (unsigned char)(15. * dg);
-          gl2psPrintf("%x%x", red, green);
-          icase++;
-        }
-        else if(icase == 2) {
-          blue = (unsigned char)(15. * db);
-          if(col < width) {
-            gl2psGetRGB(im, col, row, &dr, &dg, &db);
-          }
-          else {
-            dr = dg = db = 0;
-          }
-          col++;
-          red = (unsigned char)(15. * dr);
-          gl2psPrintf("%x%x", blue, red);
-          icase++;
-        }
-        else if(icase == 3) {
-          green = (unsigned char)(15. * dg);
-          blue = (unsigned char)(15. * db);
-          gl2psPrintf("%x%x", green, blue);
-          icase = 1;
-        }
-      }
-      gl2psPrintf("\n");
-    }
-  }
-  else{ /* 8 bit for r and g and b */
-    nbyte = width * 3;
-    gl2psPrintf("/rgbstr %d string def\n", nbyte);
-    gl2psPrintf("%d %d %d\n", width, height, 8);
-    gl2psPrintf("[ %d 0 0 -%d 0 %d ]\n", width, height, height);
-    gl2psPrintf("{ currentfile rgbstr readhexstring pop }\n");
-    gl2psPrintf("false 3\n");
-    gl2psPrintf("colorimage\n");
-    for(row = 0; row < height; row++){
-      for(col = 0; col < width; col++){
-        gl2psGetRGB(im, col, row, &dr, &dg, &db);
-        red = (unsigned char)(255. * dr);
-        gl2psWriteByte(red);
-        green = (unsigned char)(255. * dg);
-        gl2psWriteByte(green);
-        blue = (unsigned char)(255. * db);
-        gl2psWriteByte(blue);
-      }
-      gl2psPrintf("\n");
-    }
-  }
-
-  gl2psPrintf("grestore\n");
-}
-
-static void gl2psPrintPostScriptImagemap(GLfloat x, GLfloat y,
-                                         GLsizei width, GLsizei height,
-                                         const unsigned char *imagemap){
-  int i, size;
-
-  if((width <= 0) || (height <= 0)) return;
-
-  size = height + height * (width - 1) / 8;
-
-  gl2psPrintf("gsave\n");
-  gl2psPrintf("%.2f %.2f translate\n", x, y);
-  gl2psPrintf("%d %d scale\n%d %d\ntrue\n", width, height,width, height);
-  gl2psPrintf("[ %d 0 0 -%d 0 %d ] {<", width, height);
-  for(i = 0; i < size; i++){
-    gl2psWriteByte(*imagemap);
-    imagemap++;
-  }
-  gl2psPrintf(">} imagemask\ngrestore\n");
-}
-
-static void gl2psPrintPostScriptHeader(void)
-{
-  time_t now;
-
-  /* Since compression is not part of the PostScript standard,
-     compressed PostScript files are just gzipped PostScript files
-     ("ps.gz" or "eps.gz") */
-  gl2psPrintGzipHeader();
-
-  time(&now);
-
-  if(gl2ps->format == GL2PS_PS){
-    gl2psPrintf("%%!PS-Adobe-3.0\n");
-  }
-  else{
-    gl2psPrintf("%%!PS-Adobe-3.0 EPSF-3.0\n");
-  }
-
-  gl2psPrintf("%%%%Title: %s\n"
-              "%%%%Creator: GL2PS %d.%d.%d%s, %s\n"
-              "%%%%For: %s\n"
-              "%%%%CreationDate: %s"
-              "%%%%LanguageLevel: 3\n"
-              "%%%%DocumentData: Clean7Bit\n"
-              "%%%%Pages: 1\n",
-              gl2ps->title, GL2PS_MAJOR_VERSION, GL2PS_MINOR_VERSION,
-              GL2PS_PATCH_VERSION, GL2PS_EXTRA_VERSION, GL2PS_COPYRIGHT,
-              gl2ps->producer, ctime(&now));
-
-  if(gl2ps->format == GL2PS_PS){
-    gl2psPrintf("%%%%Orientation: %s\n"
-                "%%%%DocumentMedia: Default %d %d 0 () ()\n",
-                (gl2ps->options & GL2PS_LANDSCAPE) ? "Landscape" : "Portrait",
-                (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[3] :
-                (int)gl2ps->viewport[2],
-                (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[2] :
-                (int)gl2ps->viewport[3]);
-  }
-
-  gl2psPrintf("%%%%BoundingBox: %d %d %d %d\n"
-              "%%%%EndComments\n",
-              (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[1] :
-              (int)gl2ps->viewport[0],
-              (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[0] :
-              (int)gl2ps->viewport[1],
-              (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[3] :
-              (int)gl2ps->viewport[2],
-              (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[2] :
-              (int)gl2ps->viewport[3]);
-
-  /* RGB color: r g b C (replace C by G in output to change from rgb to gray)
-     Grayscale: r g b G
-     Font choose: size fontname FC
-     Text string: (string) x y size fontname S??
-     Rotated text string: (string) angle x y size fontname S??R
-     Point primitive: x y size P
-     Line width: width W
-     Line start: x y LS
-     Line joining last point: x y L
-     Line end: x y LE
-     Flat-shaded triangle: x3 y3 x2 y2 x1 y1 T
-     Smooth-shaded triangle: x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 ST */
-
-  gl2psPrintf("%%%%BeginProlog\n"
-              "/gl2psdict 64 dict def gl2psdict begin\n"
-              "0 setlinecap 0 setlinejoin\n"
-              "/tryPS3shading %s def %% set to false to force subdivision\n"
-              "/rThreshold %g def %% red component subdivision threshold\n"
-              "/gThreshold %g def %% green component subdivision threshold\n"
-              "/bThreshold %g def %% blue component subdivision threshold\n",
-              (gl2ps->options & GL2PS_NO_PS3_SHADING) ? "false" : "true",
-              gl2ps->threshold[0], gl2ps->threshold[1], gl2ps->threshold[2]);
-
-  gl2psPrintf("/BD { bind def } bind def\n"
-              "/C  { setrgbcolor } BD\n"
-              "/G  { 0.082 mul exch 0.6094 mul add exch 0.3086 mul add neg 1.0 add setgray } BD\n"
-              "/W  { setlinewidth } BD\n");
-
-  gl2psPrintf("/FC { findfont exch /SH exch def SH scalefont setfont } BD\n"
-              "/SW { dup stringwidth pop } BD\n"
-              "/S  { FC moveto show } BD\n"
-              "/SBC{ FC moveto SW -2 div 0 rmoveto show } BD\n"
-              "/SBR{ FC moveto SW neg 0 rmoveto show } BD\n"
-              "/SCL{ FC moveto 0 SH -2 div rmoveto show } BD\n"
-              "/SCC{ FC moveto SW -2 div SH -2 div rmoveto show } BD\n"
-              "/SCR{ FC moveto SW neg SH -2 div rmoveto show } BD\n"
-              "/STL{ FC moveto 0 SH neg rmoveto show } BD\n"
-              "/STC{ FC moveto SW -2 div SH neg rmoveto show } BD\n"
-              "/STR{ FC moveto SW neg SH neg rmoveto show } BD\n");
-
-  /* rotated text routines: same nameanem with R appended */
-
-  gl2psPrintf("/FCT { FC translate 0 0 } BD\n"
-              "/SR  { gsave FCT moveto rotate show grestore } BD\n"
-              "/SBCR{ gsave FCT moveto rotate SW -2 div 0 rmoveto show grestore } BD\n"
-              "/SBRR{ gsave FCT moveto rotate SW neg 0 rmoveto show grestore } BD\n"
-              "/SCLR{ gsave FCT moveto rotate 0 SH -2 div rmoveto show grestore} BD\n");
-  gl2psPrintf("/SCCR{ gsave FCT moveto rotate SW -2 div SH -2 div rmoveto show grestore} BD\n"
-              "/SCRR{ gsave FCT moveto rotate SW neg SH -2 div rmoveto show grestore} BD\n"
-              "/STLR{ gsave FCT moveto rotate 0 SH neg rmoveto show grestore } BD\n"
-              "/STCR{ gsave FCT moveto rotate SW -2 div SH neg rmoveto show grestore } BD\n"
-              "/STRR{ gsave FCT moveto rotate SW neg SH neg rmoveto show grestore } BD\n");
-
-  gl2psPrintf("/P  { newpath 0.0 360.0 arc closepath fill } BD\n"
-              "/LS { newpath moveto } BD\n"
-              "/L  { lineto } BD\n"
-              "/LE { lineto stroke } BD\n"
-              "/T  { newpath moveto lineto lineto closepath fill } BD\n");
-
-  /* Smooth-shaded triangle with PostScript level 3 shfill operator:
-        x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 STshfill */
-
-  gl2psPrintf("/STshfill {\n"
-              "      /b1 exch def /g1 exch def /r1 exch def /y1 exch def /x1 exch def\n"
-              "      /b2 exch def /g2 exch def /r2 exch def /y2 exch def /x2 exch def\n"
-              "      /b3 exch def /g3 exch def /r3 exch def /y3 exch def /x3 exch def\n"
-              "      gsave << /ShadingType 4 /ColorSpace [/DeviceRGB]\n"
-              "      /DataSource [ 0 x1 y1 r1 g1 b1 0 x2 y2 r2 g2 b2 0 x3 y3 r3 g3 b3 ] >>\n"
-              "      shfill grestore } BD\n");
-
-  /* Flat-shaded triangle with middle color:
-        x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 Tm */
-
-  gl2psPrintf(/* stack : x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 */
-              "/Tm { 3 -1 roll 8 -1 roll 13 -1 roll add add 3 div\n" /* r = (r1+r2+r3)/3 */
-              /* stack : x3 y3 g3 b3 x2 y2 g2 b2 x1 y1 g1 b1 r */
-              "      3 -1 roll 7 -1 roll 11 -1 roll add add 3 div\n" /* g = (g1+g2+g3)/3 */
-              /* stack : x3 y3 b3 x2 y2 b2 x1 y1 b1 r g b */
-              "      3 -1 roll 6 -1 roll 9 -1 roll add add 3 div" /* b = (b1+b2+b3)/3 */
-              /* stack : x3 y3 x2 y2 x1 y1 r g b */
-              " C T } BD\n");
-
-  /* Split triangle in four sub-triangles (at sides middle points) and call the
-     STnoshfill procedure on each, interpolating the colors in RGB space:
-        x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 STsplit
-     (in procedure comments key: (Vi) = xi yi ri gi bi) */
-
-  gl2psPrintf("/STsplit {\n"
-              "      4 index 15 index add 0.5 mul\n" /* x13 = (x1+x3)/2 */
-              "      4 index 15 index add 0.5 mul\n" /* y13 = (y1+y3)/2 */
-              "      4 index 15 index add 0.5 mul\n" /* r13 = (r1+r3)/2 */
-              "      4 index 15 index add 0.5 mul\n" /* g13 = (g1+g3)/2 */
-              "      4 index 15 index add 0.5 mul\n" /* b13 = (b1+b3)/2 */
-              "      5 copy 5 copy 25 15 roll\n");
-
-  /* at his point, stack = (V3) (V13) (V13) (V13) (V2) (V1) */
-
-  gl2psPrintf("      9 index 30 index add 0.5 mul\n" /* x23 = (x2+x3)/2 */
-              "      9 index 30 index add 0.5 mul\n" /* y23 = (y2+y3)/2 */
-              "      9 index 30 index add 0.5 mul\n" /* r23 = (r2+r3)/2 */
-              "      9 index 30 index add 0.5 mul\n" /* g23 = (g2+g3)/2 */
-              "      9 index 30 index add 0.5 mul\n" /* b23 = (b2+b3)/2 */
-              "      5 copy 5 copy 35 5 roll 25 5 roll 15 5 roll\n");
-
-  /* stack = (V3) (V13) (V23) (V13) (V23) (V13) (V23) (V2) (V1) */
-
-  gl2psPrintf("      4 index 10 index add 0.5 mul\n" /* x12 = (x1+x2)/2 */
-              "      4 index 10 index add 0.5 mul\n" /* y12 = (y1+y2)/2 */
-              "      4 index 10 index add 0.5 mul\n" /* r12 = (r1+r2)/2 */
-              "      4 index 10 index add 0.5 mul\n" /* g12 = (g1+g2)/2 */
-              "      4 index 10 index add 0.5 mul\n" /* b12 = (b1+b2)/2 */
-              "      5 copy 5 copy 40 5 roll 25 5 roll 15 5 roll 25 5 roll\n");
-
-  /* stack = (V3) (V13) (V23) (V13) (V12) (V23) (V13) (V1) (V12) (V23) (V12) (V2) */
-
-  gl2psPrintf("      STnoshfill STnoshfill STnoshfill STnoshfill } BD\n");
-
-  /* Gouraud shaded triangle using recursive subdivision until the difference
-     between corner colors does not exceed the thresholds:
-        x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 STnoshfill  */
-
-  gl2psPrintf("/STnoshfill {\n"
-              "      2 index 8 index sub abs rThreshold gt\n" /* |r1-r2|>rth */
-              "      { STsplit }\n"
-              "      { 1 index 7 index sub abs gThreshold gt\n" /* |g1-g2|>gth */
-              "        { STsplit }\n"
-              "        { dup 6 index sub abs bThreshold gt\n" /* |b1-b2|>bth */
-              "          { STsplit }\n"
-              "          { 2 index 13 index sub abs rThreshold gt\n" /* |r1-r3|>rht */
-              "            { STsplit }\n"
-              "            { 1 index 12 index sub abs gThreshold gt\n" /* |g1-g3|>gth */
-              "              { STsplit }\n"
-              "              { dup 11 index sub abs bThreshold gt\n" /* |b1-b3|>bth */
-              "                { STsplit }\n"
-              "                { 7 index 13 index sub abs rThreshold gt\n"); /* |r2-r3|>rht */
-  gl2psPrintf("                  { STsplit }\n"
-              "                  { 6 index 12 index sub abs gThreshold gt\n" /* |g2-g3|>gth */
-              "                    { STsplit }\n"
-              "                    { 5 index 11 index sub abs bThreshold gt\n" /* |b2-b3|>bth */
-              "                      { STsplit }\n"
-              "                      { Tm }\n" /* all colors sufficiently similar */
-              "                      ifelse }\n"
-              "                    ifelse }\n"
-              "                  ifelse }\n"
-              "                ifelse }\n"
-              "              ifelse }\n"
-              "            ifelse }\n"
-              "          ifelse }\n"
-              "        ifelse }\n"
-              "      ifelse } BD\n");
-
-  gl2psPrintf("tryPS3shading\n"
-              "{ /shfill where\n"
-              "  { /ST { STshfill } BD }\n"
-              "  { /ST { STnoshfill } BD }\n"
-              "  ifelse }\n"
-              "{ /ST { STnoshfill } BD }\n"
-              "ifelse\n");
-
-  gl2psPrintf("end\n"
-              "%%%%EndProlog\n"
-              "%%%%BeginSetup\n"
-              "/DeviceRGB setcolorspace\n"
-              "gl2psdict begin\n"
-              "%%%%EndSetup\n"
-              "%%%%Page: 1 1\n"
-              "%%%%BeginPageSetup\n");
-
-  if(gl2ps->options & GL2PS_LANDSCAPE){
-    gl2psPrintf("%d 0 translate 90 rotate\n",
-                (int)gl2ps->viewport[3]);
-  }
-
-  gl2psPrintf("%%%%EndPageSetup\n"
-              "mark\n"
-              "gsave\n"
-              "1.0 1.0 scale\n");
-
-  if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
-    gl2psPrintf("%g %g %g C\n"
-                "newpath %d %d moveto %d %d lineto %d %d lineto %d %d lineto\n"
-                "closepath fill\n",
-                gl2ps->bgcolor[0], gl2ps->bgcolor[1], gl2ps->bgcolor[2],
-                (int)gl2ps->viewport[0], (int)gl2ps->viewport[1], (int)gl2ps->viewport[2],
-                (int)gl2ps->viewport[1], (int)gl2ps->viewport[2], (int)gl2ps->viewport[3],
-                (int)gl2ps->viewport[0], (int)gl2ps->viewport[3]);
-  }
-}
-
-static void gl2psPrintPostScriptColor(GL2PSrgba rgba)
-{
-  if(!gl2psSameColor(gl2ps->lastrgba, rgba)){
-    gl2psSetLastColor(rgba);
-    gl2psPrintf("%g %g %g C\n", rgba[0], rgba[1], rgba[2]);
-  }
-}
-
-static void gl2psResetPostScriptColor(void)
-{
-  gl2ps->lastrgba[0] = gl2ps->lastrgba[1] = gl2ps->lastrgba[2] = -1.;
-}
-
-static void gl2psEndPostScriptLine(void)
-{
-  int i;
-  if(gl2ps->lastvertex.rgba[0] >= 0.){
-    gl2psPrintf("%g %g LE\n", gl2ps->lastvertex.xyz[0], gl2ps->lastvertex.xyz[1]);
-    for(i = 0; i < 3; i++)
-      gl2ps->lastvertex.xyz[i] = -1.;
-    for(i = 0; i < 4; i++)
-      gl2ps->lastvertex.rgba[i] = -1.;
-  }
-}
-
-static void gl2psParseStipplePattern(GLushort pattern, GLint factor,
-                                     int *nb, int array[10])
-{
-  int i, n;
-  int on[8] = {0, 0, 0, 0, 0, 0, 0, 0};
-  int off[8] = {0, 0, 0, 0, 0, 0, 0, 0};
-  char tmp[16];
-
-  /* extract the 16 bits from the OpenGL stipple pattern */
-  for(n = 15; n >= 0; n--){
-    tmp[n] = (char)(pattern & 0x01);
-    pattern >>= 1;
-  }
-  /* compute the on/off pixel sequence */
-  n = 0;
-  for(i = 0; i < 8; i++){
-    while(n < 16 && !tmp[n]){ off[i]++; n++; }
-    while(n < 16 && tmp[n]){ on[i]++; n++; }
-    if(n >= 15){ i++; break; }
-  }
-
-  /* store the on/off array from right to left, starting with off
-     pixels. The PostScript specification allows for at most 11
-     elements in the on/off array, so we limit ourselves to 5 on/off
-     couples (our longest possible array is thus [on4 off4 on3 off3
-     on2 off2 on1 off1 on0 off0]) */
-  *nb = 0;
-  for(n = i - 1; n >= 0; n--){
-    array[(*nb)++] = factor * on[n];
-    array[(*nb)++] = factor * off[n];
-    if(*nb == 10) break;
-  }
-}
-
-static int gl2psPrintPostScriptDash(GLushort pattern, GLint factor, const char *str)
-{
-  int len = 0, i, n, array[10];
-
-  if(pattern == gl2ps->lastpattern && factor == gl2ps->lastfactor)
-    return 0;
-
-  gl2ps->lastpattern = pattern;
-  gl2ps->lastfactor = factor;
-
-  if(!pattern || !factor){
-    /* solid line */
-    len += gl2psPrintf("[] 0 %s\n", str);
-  }
-  else{
-    gl2psParseStipplePattern(pattern, factor, &n, array);
-    len += gl2psPrintf("[");
-    for(i = 0; i < n; i++){
-      if(i) len += gl2psPrintf(" ");
-      len += gl2psPrintf("%d", array[i]);
-    }
-    len += gl2psPrintf("] 0 %s\n", str);
-  }
-
-  return len;
-}
-
-static void gl2psPrintPostScriptPrimitive(void *data)
-{
-  int newline;
-  GL2PSprimitive *prim;
-
-  prim = *(GL2PSprimitive**)data;
-
-  if((gl2ps->options & GL2PS_OCCLUSION_CULL) && prim->culled) return;
-
-  /* Every effort is made to draw lines as connected segments (i.e.,
-     using a single PostScript path): this is the only way to get nice
-     line joins and to not restart the stippling for every line
-     segment. So if the primitive to print is not a line we must first
-     finish the current line (if any): */
-  if(prim->type != GL2PS_LINE) gl2psEndPostScriptLine();
-
-  switch(prim->type){
-  case GL2PS_POINT :
-    gl2psPrintPostScriptColor(prim->verts[0].rgba);
-    gl2psPrintf("%g %g %g P\n",
-                prim->verts[0].xyz[0], prim->verts[0].xyz[1], 0.5 * prim->width);
-    break;
-  case GL2PS_LINE :
-    if(!gl2psSamePosition(gl2ps->lastvertex.xyz, prim->verts[0].xyz) ||
-       !gl2psSameColor(gl2ps->lastrgba, prim->verts[0].rgba) ||
-       gl2ps->lastlinewidth != prim->width ||
-       gl2ps->lastpattern != prim->pattern ||
-       gl2ps->lastfactor != prim->factor){
-      /* End the current line if the new segment does not start where
-         the last one ended, or if the color, the width or the
-         stippling have changed (multi-stroking lines with changing
-         colors is necessary until we use /shfill for lines;
-         unfortunately this means that at the moment we can screw up
-         line stippling for smooth-shaded lines) */
-      gl2psEndPostScriptLine();
-      newline = 1;
-    }
-    else{
-      newline = 0;
-    }
-    if(gl2ps->lastlinewidth != prim->width){
-      gl2ps->lastlinewidth = prim->width;
-      gl2psPrintf("%g W\n", gl2ps->lastlinewidth);
-    }
-    gl2psPrintPostScriptDash(prim->pattern, prim->factor, "setdash");
-    gl2psPrintPostScriptColor(prim->verts[0].rgba);
-    gl2psPrintf("%g %g %s\n", prim->verts[0].xyz[0], prim->verts[0].xyz[1],
-                newline ? "LS" : "L");
-    gl2ps->lastvertex = prim->verts[1];
-    break;
-  case GL2PS_TRIANGLE :
-    if(!gl2psVertsSameColor(prim)){
-      gl2psResetPostScriptColor();
-      gl2psPrintf("%g %g %g %g %g %g %g %g %g %g %g %g %g %g %g ST\n",
-                  prim->verts[2].xyz[0], prim->verts[2].xyz[1],
-                  prim->verts[2].rgba[0], prim->verts[2].rgba[1],
-                  prim->verts[2].rgba[2], prim->verts[1].xyz[0],
-                  prim->verts[1].xyz[1], prim->verts[1].rgba[0],
-                  prim->verts[1].rgba[1], prim->verts[1].rgba[2],
-                  prim->verts[0].xyz[0], prim->verts[0].xyz[1],
-                  prim->verts[0].rgba[0], prim->verts[0].rgba[1],
-                  prim->verts[0].rgba[2]);
-    }
-    else{
-      gl2psPrintPostScriptColor(prim->verts[0].rgba);
-      gl2psPrintf("%g %g %g %g %g %g T\n",
-                  prim->verts[2].xyz[0], prim->verts[2].xyz[1],
-                  prim->verts[1].xyz[0], prim->verts[1].xyz[1],
-                  prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
-    }
-    break;
-  case GL2PS_QUADRANGLE :
-    gl2psMsg(GL2PS_WARNING, "There should not be any quad left to print");
-    break;
-  case GL2PS_PIXMAP :
-    gl2psPrintPostScriptPixmap(prim->verts[0].xyz[0], prim->verts[0].xyz[1],
-                               prim->data.image);
-    break;
-  case GL2PS_IMAGEMAP :
-    if(prim->data.image->type != GL2PS_IMAGEMAP_WRITTEN){
-      gl2psPrintPostScriptColor(prim->verts[0].rgba);
-      gl2psPrintPostScriptImagemap(prim->data.image->pixels[0],
-                                   prim->data.image->pixels[1],
-                                   prim->data.image->width, prim->data.image->height,
-                                   (const unsigned char*)(&(prim->data.image->pixels[2])));
-      prim->data.image->type = GL2PS_IMAGEMAP_WRITTEN;
-    }
-    break;
-  case GL2PS_TEXT :
-    gl2psPrintPostScriptColor(prim->verts[0].rgba);
-    gl2psPrintf("(%s) ", prim->data.text->str);
-    if(prim->data.text->angle)
-      gl2psPrintf("%g ", prim->data.text->angle);
-    gl2psPrintf("%g %g %d /%s ",
-                prim->verts[0].xyz[0], prim->verts[0].xyz[1],
-                prim->data.text->fontsize, prim->data.text->fontname);
-    switch(prim->data.text->alignment){
-    case GL2PS_TEXT_C:
-      gl2psPrintf(prim->data.text->angle ? "SCCR\n" : "SCC\n");
-      break;
-    case GL2PS_TEXT_CL:
-      gl2psPrintf(prim->data.text->angle ? "SCLR\n" : "SCL\n");
-      break;
-    case GL2PS_TEXT_CR:
-      gl2psPrintf(prim->data.text->angle ? "SCRR\n" : "SCR\n");
-      break;
-    case GL2PS_TEXT_B:
-      gl2psPrintf(prim->data.text->angle ? "SBCR\n" : "SBC\n");
-      break;
-    case GL2PS_TEXT_BR:
-      gl2psPrintf(prim->data.text->angle ? "SBRR\n" : "SBR\n");
-      break;
-    case GL2PS_TEXT_T:
-      gl2psPrintf(prim->data.text->angle ? "STCR\n" : "STC\n");
-      break;
-    case GL2PS_TEXT_TL:
-      gl2psPrintf(prim->data.text->angle ? "STLR\n" : "STL\n");
-      break;
-    case GL2PS_TEXT_TR:
-      gl2psPrintf(prim->data.text->angle ? "STRR\n" : "STR\n");
-      break;
-    case GL2PS_TEXT_BL:
-    default:
-      gl2psPrintf(prim->data.text->angle ? "SR\n" : "S\n");
-      break;
-    }
-    break;
-  case GL2PS_SPECIAL :
-    /* alignment contains the format for which the special output text
-       is intended */
-    if(prim->data.text->alignment == GL2PS_PS ||
-       prim->data.text->alignment == GL2PS_EPS)
-      gl2psPrintf("%s\n", prim->data.text->str);
-    break;
-  default :
-    break;
-  }
-}
-
-static void gl2psPrintPostScriptFooter(void)
-{
-  gl2psPrintf("grestore\n"
-              "showpage\n"
-              "cleartomark\n"
-              "%%%%PageTrailer\n"
-              "%%%%Trailer\n"
-              "end\n"
-              "%%%%EOF\n");
-
-  gl2psPrintGzipFooter();
-}
-
-static void gl2psPrintPostScriptBeginViewport(GLint viewport[4])
-{
-  GLint index;
-  GLfloat rgba[4];
-  int x = viewport[0], y = viewport[1], w = viewport[2], h = viewport[3];
-
-  glRenderMode(GL_FEEDBACK);
-
-  if(gl2ps->header){
-    gl2psPrintPostScriptHeader();
-    gl2ps->header = GL_FALSE;
-  }
-
-  gl2psPrintf("gsave\n"
-              "1.0 1.0 scale\n");
-
-  if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
-    if(gl2ps->colormode == GL_RGBA || gl2ps->colorsize == 0){
-      glGetFloatv(GL_COLOR_CLEAR_VALUE, rgba);
-    }
-    else{
-      glGetIntegerv(GL_INDEX_CLEAR_VALUE, &index);
-      rgba[0] = gl2ps->colormap[index][0];
-      rgba[1] = gl2ps->colormap[index][1];
-      rgba[2] = gl2ps->colormap[index][2];
-      rgba[3] = 1.0F;
-    }
-    gl2psPrintf("%g %g %g C\n"
-                "newpath %d %d moveto %d %d lineto %d %d lineto %d %d lineto\n"
-                "closepath fill\n",
-                rgba[0], rgba[1], rgba[2],
-                x, y, x+w, y, x+w, y+h, x, y+h);
-  }
-
-  gl2psPrintf("newpath %d %d moveto %d %d lineto %d %d lineto %d %d lineto\n"
-              "closepath clip\n",
-              x, y, x+w, y, x+w, y+h, x, y+h);
-
-}
-
-static GLint gl2psPrintPostScriptEndViewport(void)
-{
-  GLint res;
-
-  res = gl2psPrintPrimitives();
-  gl2psPrintf("grestore\n");
-  return res;
-}
-
-static void gl2psPrintPostScriptFinalPrimitive(void)
-{
-  /* End any remaining line, if any */
-  gl2psEndPostScriptLine();
-}
-
-/* definition of the PostScript and Encapsulated PostScript backends */
-
-static GL2PSbackend gl2psPS = {
-  gl2psPrintPostScriptHeader,
-  gl2psPrintPostScriptFooter,
-  gl2psPrintPostScriptBeginViewport,
-  gl2psPrintPostScriptEndViewport,
-  gl2psPrintPostScriptPrimitive,
-  gl2psPrintPostScriptFinalPrimitive,
-  "ps",
-  "Postscript"
-};
-
-static GL2PSbackend gl2psEPS = {
-  gl2psPrintPostScriptHeader,
-  gl2psPrintPostScriptFooter,
-  gl2psPrintPostScriptBeginViewport,
-  gl2psPrintPostScriptEndViewport,
-  gl2psPrintPostScriptPrimitive,
-  gl2psPrintPostScriptFinalPrimitive,
-  "eps",
-  "Encapsulated Postscript"
-};
-
-/*********************************************************************
- *
- * LaTeX routines
- *
- *********************************************************************/
-
-static void gl2psPrintTeXHeader(void)
-{
-  char name[256];
-  time_t now;
-  int i;
-
-  if(gl2ps->filename && strlen(gl2ps->filename) < 256){
-    for(i = (int)strlen(gl2ps->filename) - 1; i >= 0; i--){
-      if(gl2ps->filename[i] == '.'){
-        strncpy(name, gl2ps->filename, i);
-        name[i] = '\0';
-        break;
-      }
-    }
-    if(i <= 0) strcpy(name, gl2ps->filename);
-  }
-  else{
-    strcpy(name, "untitled");
-  }
-
-  time(&now);
-
-  fprintf(gl2ps->stream,
-          "%% Title: %s\n"
-          "%% Creator: GL2PS %d.%d.%d%s, %s\n"
-          "%% For: %s\n"
-          "%% CreationDate: %s",
-          gl2ps->title, GL2PS_MAJOR_VERSION, GL2PS_MINOR_VERSION,
-          GL2PS_PATCH_VERSION, GL2PS_EXTRA_VERSION, GL2PS_COPYRIGHT,
-          gl2ps->producer, ctime(&now));
-
-  fprintf(gl2ps->stream,
-          "\\setlength{\\unitlength}{1pt}\n"
-          "\\begin{picture}(0,0)\n"
-          "\\includegraphics{%s}\n"
-          "\\end{picture}%%\n"
-          "%s\\begin{picture}(%d,%d)(0,0)\n",
-          name, (gl2ps->options & GL2PS_LANDSCAPE) ? "\\rotatebox{90}{" : "",
-          (int)gl2ps->viewport[2], (int)gl2ps->viewport[3]);
-}
-
-static void gl2psPrintTeXPrimitive(void *data)
-{
-  GL2PSprimitive *prim;
-
-  prim = *(GL2PSprimitive**)data;
-
-  switch(prim->type){
-  case GL2PS_TEXT :
-    fprintf(gl2ps->stream, "\\fontsize{%d}{0}\n\\selectfont",
-            prim->data.text->fontsize);
-    fprintf(gl2ps->stream, "\\put(%g,%g)",
-            prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
-    if(prim->data.text->angle)
-      fprintf(gl2ps->stream, "{\\rotatebox{%g}", prim->data.text->angle);
-    fprintf(gl2ps->stream, "{\\makebox(0,0)");
-    switch(prim->data.text->alignment){
-    case GL2PS_TEXT_C:
-      fprintf(gl2ps->stream, "{");
-      break;
-    case GL2PS_TEXT_CL:
-      fprintf(gl2ps->stream, "[l]{");
-      break;
-    case GL2PS_TEXT_CR:
-      fprintf(gl2ps->stream, "[r]{");
-      break;
-    case GL2PS_TEXT_B:
-      fprintf(gl2ps->stream, "[b]{");
-      break;
-    case GL2PS_TEXT_BR:
-      fprintf(gl2ps->stream, "[br]{");
-      break;
-    case GL2PS_TEXT_T:
-      fprintf(gl2ps->stream, "[t]{");
-      break;
-    case GL2PS_TEXT_TL:
-      fprintf(gl2ps->stream, "[tl]{");
-      break;
-    case GL2PS_TEXT_TR:
-      fprintf(gl2ps->stream, "[tr]{");
-      break;
-    case GL2PS_TEXT_BL:
-    default:
-      fprintf(gl2ps->stream, "[bl]{");
-      break;
-    }
-    fprintf(gl2ps->stream, "\\textcolor[rgb]{%g,%g,%g}{{%s}}",
-            prim->verts[0].rgba[0], prim->verts[0].rgba[1], prim->verts[0].rgba[2],
-            prim->data.text->str);
-    if(prim->data.text->angle)
-      fprintf(gl2ps->stream, "}");
-    fprintf(gl2ps->stream, "}}\n");
-    break;
-  case GL2PS_SPECIAL :
-    /* alignment contains the format for which the special output text
-       is intended */
-    if (prim->data.text->alignment == GL2PS_TEX)
-      fprintf(gl2ps->stream, "%s\n", prim->data.text->str);
-    break;
-  default :
-    break;
-  }
-}
-
-static void gl2psPrintTeXFooter(void)
-{
-  fprintf(gl2ps->stream, "\\end{picture}%s\n",
-          (gl2ps->options & GL2PS_LANDSCAPE) ? "}" : "");
-}
-
-static void gl2psPrintTeXBeginViewport(GLint viewport[4])
-{
-  (void) viewport;  /* not used */
-  glRenderMode(GL_FEEDBACK);
-
-  if(gl2ps->header){
-    gl2psPrintTeXHeader();
-    gl2ps->header = GL_FALSE;
-  }
-}
-
-static GLint gl2psPrintTeXEndViewport(void)
-{
-  return gl2psPrintPrimitives();
-}
-
-static void gl2psPrintTeXFinalPrimitive(void)
-{
-}
-
-/* definition of the LaTeX backend */
-
-static GL2PSbackend gl2psTEX = {
-  gl2psPrintTeXHeader,
-  gl2psPrintTeXFooter,
-  gl2psPrintTeXBeginViewport,
-  gl2psPrintTeXEndViewport,
-  gl2psPrintTeXPrimitive,
-  gl2psPrintTeXFinalPrimitive,
-  "tex",
-  "LaTeX text"
-};
-
-/*********************************************************************
- *
- * PDF routines
- *
- *********************************************************************/
-
-static int gl2psPrintPDFCompressorType(void)
-{
-#if defined(GL2PS_HAVE_ZLIB)
-  if(gl2ps->options & GL2PS_COMPRESS){
-    return fprintf(gl2ps->stream, "/Filter [/FlateDecode]\n");
-  }
-#endif
-  return 0;
-}
-
-static int gl2psPrintPDFStrokeColor(GL2PSrgba rgba)
-{
-  int i, offs = 0;
-
-  gl2psSetLastColor(rgba);
-  for(i = 0; i < 3; ++i){
-    if(GL2PS_ZERO(rgba[i]))
-      offs += gl2psPrintf("%.0f ", 0.);
-    else if(rgba[i] < 1e-4 || rgba[i] > 1e6) /* avoid %e formatting */
-      offs += gl2psPrintf("%f ", rgba[i]);
-    else
-      offs += gl2psPrintf("%g ", rgba[i]);
-  }
-  offs += gl2psPrintf("RG\n");
-  return offs;
-}
-
-static int gl2psPrintPDFFillColor(GL2PSrgba rgba)
-{
-  int i, offs = 0;
-
-  for(i = 0; i < 3; ++i){
-    if(GL2PS_ZERO(rgba[i]))
-      offs += gl2psPrintf("%.0f ", 0.);
-    else if(rgba[i] < 1e-4 || rgba[i] > 1e6) /* avoid %e formatting */
-      offs += gl2psPrintf("%f ", rgba[i]);
-    else
-      offs += gl2psPrintf("%g ", rgba[i]);
-  }
-  offs += gl2psPrintf("rg\n");
-  return offs;
-}
-
-static int gl2psPrintPDFLineWidth(GLfloat lw)
-{
-  if(GL2PS_ZERO(lw))
-    return gl2psPrintf("%.0f w\n", 0.);
-  else if(lw < 1e-4 || lw > 1e6) /* avoid %e formatting */
-    return gl2psPrintf("%f w\n", lw);
-  else
-    return gl2psPrintf("%g w\n", lw);
-}
-
-static void gl2psPutPDFText(GL2PSstring *text, int cnt, GLfloat x, GLfloat y)
-{
-  GLfloat rad, crad, srad;
-
-  if(text->angle == 0.0F){
-    gl2ps->streamlength += gl2psPrintf
-      ("BT\n"
-       "/F%d %d Tf\n"
-       "%f %f Td\n"
-       "(%s) Tj\n"
-       "ET\n",
-       cnt, text->fontsize, x, y, text->str);
-  }
-  else{
-    rad = (GLfloat)(M_PI * text->angle / 180.0F);
-    srad = (GLfloat)sin(rad);
-    crad = (GLfloat)cos(rad);
-    gl2ps->streamlength += gl2psPrintf
-      ("BT\n"
-       "/F%d %d Tf\n"
-       "%f %f %f %f %f %f Tm\n"
-       "(%s) Tj\n"
-       "ET\n",
-       cnt, text->fontsize, crad, srad, -srad, crad, x, y, text->str);
-  }
-}
-
-static void gl2psPutPDFImage(GL2PSimage *image, int cnt, GLfloat x, GLfloat y)
-{
-  gl2ps->streamlength += gl2psPrintf
-    ("q\n"
-     "%d 0 0 %d %f %f cm\n"
-     "/Im%d Do\n"
-     "Q\n",
-     (int)image->width, (int)image->height, x, y, cnt);
-}
-
-static void gl2psPDFstacksInit(void)
-{
-  gl2ps->objects_stack = 7 /* FIXED_XREF_ENTRIES */ + 1;
-  gl2ps->extgs_stack = 0;
-  gl2ps->font_stack = 0;
-  gl2ps->im_stack = 0;
-  gl2ps->trgroupobjects_stack = 0;
-  gl2ps->shader_stack = 0;
-  gl2ps->mshader_stack = 0;
-}
-
-static void gl2psPDFgroupObjectInit(GL2PSpdfgroup *gro)
-{
-  if(!gro)
-    return;
-
-  gro->ptrlist = NULL;
-  gro->fontno = gro->gsno = gro->imno = gro->maskshno = gro->shno
-    = gro->trgroupno = gro->fontobjno = gro->imobjno = gro->shobjno
-    = gro->maskshobjno = gro->gsobjno = gro->trgroupobjno = -1;
-}
-
-/* Build up group objects and assign name and object numbers */
-
-static void gl2psPDFgroupListInit(void)
-{
-  int i;
-  GL2PSprimitive *p = NULL;
-  GL2PSpdfgroup gro;
-  int lasttype = GL2PS_NO_TYPE;
-  GL2PSrgba lastrgba = {-1.0F, -1.0F, -1.0F, -1.0F};
-  GLushort lastpattern = 0;
-  GLint lastfactor = 0;
-  GLfloat lastwidth = 1;
-  GL2PStriangle lastt, tmpt;
-  int lastTriangleWasNotSimpleWithSameColor = 0;
-
-  if(!gl2ps->pdfprimlist)
-    return;
-
-  gl2ps->pdfgrouplist = gl2psListCreate(500, 500, sizeof(GL2PSpdfgroup));
-  gl2psInitTriangle(&lastt);
-
-  for(i = 0; i < gl2psListNbr(gl2ps->pdfprimlist); ++i){
-    p = *(GL2PSprimitive**)gl2psListPointer(gl2ps->pdfprimlist, i);
-    switch(p->type){
-    case GL2PS_PIXMAP:
-      gl2psPDFgroupObjectInit(&gro);
-      gro.ptrlist = gl2psListCreate(1, 2, sizeof(GL2PSprimitive*));
-      gro.imno = gl2ps->im_stack++;
-      gl2psListAdd(gro.ptrlist, &p);
-      gl2psListAdd(gl2ps->pdfgrouplist, &gro);
-      break;
-    case GL2PS_TEXT:
-      gl2psPDFgroupObjectInit(&gro);
-      gro.ptrlist = gl2psListCreate(1, 2, sizeof(GL2PSprimitive*));
-      gro.fontno = gl2ps->font_stack++;
-      gl2psListAdd(gro.ptrlist, &p);
-      gl2psListAdd(gl2ps->pdfgrouplist, &gro);
-      break;
-    case GL2PS_LINE:
-      if(lasttype != p->type || lastwidth != p->width ||
-         lastpattern != p->pattern || lastfactor != p->factor ||
-         !gl2psSameColor(p->verts[0].rgba, lastrgba)){
-        gl2psPDFgroupObjectInit(&gro);
-        gro.ptrlist = gl2psListCreate(1, 2, sizeof(GL2PSprimitive*));
-        gl2psListAdd(gro.ptrlist, &p);
-        gl2psListAdd(gl2ps->pdfgrouplist, &gro);
-      }
-      else{
-        gl2psListAdd(gro.ptrlist, &p);
-      }
-      lastpattern = p->pattern;
-      lastfactor = p->factor;
-      lastwidth = p->width;
-      lastrgba[0] = p->verts[0].rgba[0];
-      lastrgba[1] = p->verts[0].rgba[1];
-      lastrgba[2] = p->verts[0].rgba[2];
-      break;
-    case GL2PS_POINT:
-      if(lasttype != p->type || lastwidth != p->width ||
-         !gl2psSameColor(p->verts[0].rgba, lastrgba)){
-        gl2psPDFgroupObjectInit(&gro);
-        gro.ptrlist = gl2psListCreate(1,2,sizeof(GL2PSprimitive*));
-        gl2psListAdd(gro.ptrlist, &p);
-        gl2psListAdd(gl2ps->pdfgrouplist, &gro);
-      }
-      else{
-        gl2psListAdd(gro.ptrlist, &p);
-      }
-      lastwidth = p->width;
-      lastrgba[0] = p->verts[0].rgba[0];
-      lastrgba[1] = p->verts[0].rgba[1];
-      lastrgba[2] = p->verts[0].rgba[2];
-      break;
-    case GL2PS_TRIANGLE:
-      gl2psFillTriangleFromPrimitive(&tmpt, p, GL_TRUE);
-      lastTriangleWasNotSimpleWithSameColor =
-        !(tmpt.prop & T_CONST_COLOR && tmpt.prop & T_ALPHA_1) ||
-        !gl2psSameColor(tmpt.vertex[0].rgba, lastt.vertex[0].rgba);
-      if(lasttype == p->type && tmpt.prop == lastt.prop &&
-         lastTriangleWasNotSimpleWithSameColor){
-        /* TODO Check here for last alpha */
-        gl2psListAdd(gro.ptrlist, &p);
-      }
-      else{
-        gl2psPDFgroupObjectInit(&gro);
-        gro.ptrlist = gl2psListCreate(1, 2, sizeof(GL2PSprimitive*));
-        gl2psListAdd(gro.ptrlist, &p);
-        gl2psListAdd(gl2ps->pdfgrouplist, &gro);
-      }
-      lastt = tmpt;
-      break;
-    default:
-      break;
-    }
-    lasttype = p->type;
-  }
-}
-
-static void gl2psSortOutTrianglePDFgroup(GL2PSpdfgroup *gro)
-{
-  GL2PStriangle t;
-  GL2PSprimitive *prim = NULL;
-
-  if(!gro)
-    return;
-
-  if(!gl2psListNbr(gro->ptrlist))
-    return;
-
-  prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, 0);
-
-  if(prim->type != GL2PS_TRIANGLE)
-    return;
-
-  gl2psFillTriangleFromPrimitive(&t, prim, GL_TRUE);
-
-  if(t.prop & T_CONST_COLOR && t.prop & T_ALPHA_LESS_1){
-    gro->gsno = gl2ps->extgs_stack++;
-    gro->gsobjno = gl2ps->objects_stack ++;
-  }
-  else if(t.prop & T_CONST_COLOR && t.prop & T_VAR_ALPHA){
-    gro->gsno = gl2ps->extgs_stack++;
-    gro->gsobjno = gl2ps->objects_stack++;
-    gro->trgroupno = gl2ps->trgroupobjects_stack++;
-    gro->trgroupobjno = gl2ps->objects_stack++;
-    gro->maskshno = gl2ps->mshader_stack++;
-    gro->maskshobjno = gl2ps->objects_stack++;
-  }
-  else if(t.prop & T_VAR_COLOR && t.prop & T_ALPHA_1){
-    gro->shno = gl2ps->shader_stack++;
-    gro->shobjno = gl2ps->objects_stack++;
-  }
-  else if(t.prop & T_VAR_COLOR && t.prop & T_ALPHA_LESS_1){
-    gro->gsno = gl2ps->extgs_stack++;
-    gro->gsobjno = gl2ps->objects_stack++;
-    gro->shno = gl2ps->shader_stack++;
-    gro->shobjno = gl2ps->objects_stack++;
-  }
-  else if(t.prop & T_VAR_COLOR && t.prop & T_VAR_ALPHA){
-    gro->gsno = gl2ps->extgs_stack++;
-    gro->gsobjno = gl2ps->objects_stack++;
-    gro->shno = gl2ps->shader_stack++;
-    gro->shobjno = gl2ps->objects_stack++;
-    gro->trgroupno = gl2ps->trgroupobjects_stack++;
-    gro->trgroupobjno = gl2ps->objects_stack++;
-    gro->maskshno = gl2ps->mshader_stack++;
-    gro->maskshobjno = gl2ps->objects_stack++;
-  }
-}
-
-/* Main stream data */
-
-static void gl2psPDFgroupListWriteMainStream(void)
-{
-  int i, j, lastel;
-  GL2PSprimitive *prim = NULL, *prev = NULL;
-  GL2PSpdfgroup *gro;
-  GL2PStriangle t;
-
-  if(!gl2ps->pdfgrouplist)
-    return;
-
-  for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){
-    gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i);
-
-    lastel = gl2psListNbr(gro->ptrlist) - 1;
-    if(lastel < 0)
-      continue;
-
-    prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, 0);
-
-    switch(prim->type){
-    case GL2PS_POINT:
-      gl2ps->streamlength += gl2psPrintf("1 J\n");
-      gl2ps->streamlength += gl2psPrintPDFLineWidth(prim->width);
-      gl2ps->streamlength += gl2psPrintPDFStrokeColor(prim->verts[0].rgba);
-      for(j = 0; j <= lastel; ++j){
-        prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
-        gl2ps->streamlength +=
-          gl2psPrintf("%f %f m %f %f l\n",
-                      prim->verts[0].xyz[0], prim->verts[0].xyz[1],
-                      prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
-      }
-      gl2ps->streamlength += gl2psPrintf("S\n");
-      gl2ps->streamlength += gl2psPrintf("0 J\n");
-      break;
-    case GL2PS_LINE:
-      /* We try to use as few paths as possible to draw lines, in
-         order to get nice stippling even when the individual segments
-         are smaller than the stipple */
-      gl2ps->streamlength += gl2psPrintPDFLineWidth(prim->width);
-      gl2ps->streamlength += gl2psPrintPDFStrokeColor(prim->verts[0].rgba);
-      gl2ps->streamlength += gl2psPrintPostScriptDash(prim->pattern, prim->factor, "d");
-      /* start new path */
-      gl2ps->streamlength +=
-        gl2psPrintf("%f %f m\n",
-                    prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
-
-      for(j = 1; j <= lastel; ++j){
-        prev = prim;
-        prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
-        if(!gl2psSamePosition(prim->verts[0].xyz, prev->verts[1].xyz)){
-          /* the starting point of the new segment does not match the
-             end point of the previous line, so we end the current
-             path and start a new one */
-          gl2ps->streamlength +=
-            gl2psPrintf("%f %f l\n",
-                        prev->verts[1].xyz[0], prev->verts[1].xyz[1]);
-          gl2ps->streamlength +=
-            gl2psPrintf("%f %f m\n",
-                        prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
-        }
-        else{
-          /* the two segements are connected, so we just append to the
-             current path */
-          gl2ps->streamlength +=
-            gl2psPrintf("%f %f l\n",
-                        prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
-        }
-      }
-      /* end last path */
-      gl2ps->streamlength +=
-        gl2psPrintf("%f %f l\n",
-                    prim->verts[1].xyz[0], prim->verts[1].xyz[1]);
-      gl2ps->streamlength += gl2psPrintf("S\n");
-      break;
-    case GL2PS_TRIANGLE:
-      gl2psFillTriangleFromPrimitive(&t, prim, GL_TRUE);
-      gl2psSortOutTrianglePDFgroup(gro);
-
-      /* No alpha and const color: Simple PDF draw orders  */
-      if(t.prop & T_CONST_COLOR && t.prop & T_ALPHA_1){
-        gl2ps->streamlength += gl2psPrintPDFFillColor(t.vertex[0].rgba);
-        for(j = 0; j <= lastel; ++j){
-          prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
-          gl2psFillTriangleFromPrimitive(&t, prim, GL_FALSE);
-          gl2ps->streamlength
-            += gl2psPrintf("%f %f m\n"
-                           "%f %f l\n"
-                           "%f %f l\n"
-                           "h f\n",
-                           t.vertex[0].xyz[0], t.vertex[0].xyz[1],
-                           t.vertex[1].xyz[0], t.vertex[1].xyz[1],
-                           t.vertex[2].xyz[0], t.vertex[2].xyz[1]);
-        }
-      }
-      /* Const alpha < 1 and const color: Simple PDF draw orders
-         and an extra extended Graphics State for the alpha const */
-      else if(t.prop & T_CONST_COLOR && t.prop & T_ALPHA_LESS_1){
-        gl2ps->streamlength += gl2psPrintf("q\n"
-                                           "/GS%d gs\n",
-                                           gro->gsno);
-        gl2ps->streamlength += gl2psPrintPDFFillColor(prim->verts[0].rgba);
-        for(j = 0; j <= lastel; ++j){
-          prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
-          gl2psFillTriangleFromPrimitive(&t, prim, GL_FALSE);
-          gl2ps->streamlength
-            += gl2psPrintf("%f %f m\n"
-                           "%f %f l\n"
-                           "%f %f l\n"
-                           "h f\n",
-                           t.vertex[0].xyz[0], t.vertex[0].xyz[1],
-                           t.vertex[1].xyz[0], t.vertex[1].xyz[1],
-                           t.vertex[2].xyz[0], t.vertex[2].xyz[1]);
-        }
-        gl2ps->streamlength += gl2psPrintf("Q\n");
-      }
-      /* Variable alpha and const color: Simple PDF draw orders
-         and an extra extended Graphics State + Xobject + Shader
-         object for the alpha mask */
-      else if(t.prop & T_CONST_COLOR && t.prop & T_VAR_ALPHA){
-        gl2ps->streamlength += gl2psPrintf("q\n"
-                                           "/GS%d gs\n"
-                                           "/TrG%d Do\n",
-                                           gro->gsno, gro->trgroupno);
-        gl2ps->streamlength += gl2psPrintPDFFillColor(prim->verts[0].rgba);
-        for(j = 0; j <= lastel; ++j){
-          prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
-          gl2psFillTriangleFromPrimitive(&t, prim, GL_FALSE);
-          gl2ps->streamlength
-            += gl2psPrintf("%f %f m\n"
-                           "%f %f l\n"
-                           "%f %f l\n"
-                           "h f\n",
-                           t.vertex[0].xyz[0], t.vertex[0].xyz[1],
-                           t.vertex[1].xyz[0], t.vertex[1].xyz[1],
-                           t.vertex[2].xyz[0], t.vertex[2].xyz[1]);
-        }
-        gl2ps->streamlength += gl2psPrintf("Q\n");
-      }
-      /* Variable color and no alpha: Shader Object for the colored
-         triangle(s) */
-      else if(t.prop & T_VAR_COLOR && t.prop & T_ALPHA_1){
-        gl2ps->streamlength += gl2psPrintf("/Sh%d sh\n", gro->shno);
-      }
-      /* Variable color and const alpha < 1: Shader Object for the
-         colored triangle(s) and an extra extended Graphics State
-         for the alpha const */
-      else if(t.prop & T_VAR_COLOR && t.prop & T_ALPHA_LESS_1){
-        gl2ps->streamlength += gl2psPrintf("q\n"
-                                           "/GS%d gs\n"
-                                           "/Sh%d sh\n"
-                                           "Q\n",
-                                           gro->gsno, gro->shno);
-      }
-      /* Variable alpha and color: Shader Object for the colored
-         triangle(s) and an extra extended Graphics State
-         + Xobject + Shader object for the alpha mask */
-      else if(t.prop & T_VAR_COLOR && t.prop & T_VAR_ALPHA){
-        gl2ps->streamlength += gl2psPrintf("q\n"
-                                           "/GS%d gs\n"
-                                           "/TrG%d Do\n"
-                                           "/Sh%d sh\n"
-                                           "Q\n",
-                                           gro->gsno, gro->trgroupno, gro->shno);
-      }
-      break;
-    case GL2PS_PIXMAP:
-      for(j = 0; j <= lastel; ++j){
-        prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
-        gl2psPutPDFImage(prim->data.image, gro->imno, prim->verts[0].xyz[0],
-                         prim->verts[0].xyz[1]);
-      }
-      break;
-    case GL2PS_TEXT:
-      for(j = 0; j <= lastel; ++j){
-        prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
-        gl2ps->streamlength += gl2psPrintPDFFillColor(prim->verts[0].rgba);
-        gl2psPutPDFText(prim->data.text, gro->fontno, prim->verts[0].xyz[0],
-                        prim->verts[0].xyz[1]);
-      }
-      break;
-    default:
-      break;
-    }
-  }
-}
-
-/* Graphics State names */
-
-static int gl2psPDFgroupListWriteGStateResources(void)
-{
-  GL2PSpdfgroup *gro;
-  int offs = 0;
-  int i;
-
-  offs += fprintf(gl2ps->stream,
-                  "/ExtGState\n"
-                  "<<\n"
-                  "/GSa 7 0 R\n");
-  for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){
-    gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i);
-    if(gro->gsno >= 0)
-      offs += fprintf(gl2ps->stream, "/GS%d %d 0 R\n", gro->gsno, gro->gsobjno);
-  }
-  offs += fprintf(gl2ps->stream, ">>\n");
-  return offs;
-}
-
-/* Main Shader names */
-
-static int gl2psPDFgroupListWriteShaderResources(void)
-{
-  GL2PSpdfgroup *gro;
-  int offs = 0;
-  int i;
-
-  offs += fprintf(gl2ps->stream,
-                  "/Shading\n"
-                  "<<\n");
-  for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){
-    gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i);
-    if(gro->shno >= 0)
-      offs += fprintf(gl2ps->stream, "/Sh%d %d 0 R\n", gro->shno, gro->shobjno);
-    if(gro->maskshno >= 0)
-      offs += fprintf(gl2ps->stream, "/TrSh%d %d 0 R\n", gro->maskshno, gro->maskshobjno);
-  }
-  offs += fprintf(gl2ps->stream,">>\n");
-  return offs;
-}
-
-/* Images & Mask Shader XObject names */
-
-static int gl2psPDFgroupListWriteXObjectResources(void)
-{
-  int i;
-  GL2PSprimitive *p = NULL;
-  GL2PSpdfgroup *gro;
-  int offs = 0;
-
-  offs += fprintf(gl2ps->stream,
-                  "/XObject\n"
-                  "<<\n");
-
-  for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){
-    gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i);
-    if(!gl2psListNbr(gro->ptrlist))
-      continue;
-    p = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, 0);
-    switch(p->type){
-    case GL2PS_PIXMAP:
-      gro->imobjno = gl2ps->objects_stack++;
-      if(GL_RGBA == p->data.image->format)  /* reserve one object for image mask */
-        gl2ps->objects_stack++;
-      offs += fprintf(gl2ps->stream, "/Im%d %d 0 R\n", gro->imno, gro->imobjno);
-    case GL2PS_TRIANGLE:
-      if(gro->trgroupno >=0)
-        offs += fprintf(gl2ps->stream, "/TrG%d %d 0 R\n", gro->trgroupno, gro->trgroupobjno);
-      break;
-    default:
-      break;
-    }
-  }
-  offs += fprintf(gl2ps->stream,">>\n");
-  return offs;
-}
-
-/* Font names */
-
-static int gl2psPDFgroupListWriteFontResources(void)
-{
-  int i;
-  GL2PSpdfgroup *gro;
-  int offs = 0;
-
-  offs += fprintf(gl2ps->stream, "/Font\n<<\n");
-
-  for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){
-    gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i);
-    if(gro->fontno < 0)
-      continue;
-    gro->fontobjno = gl2ps->objects_stack++;
-    offs += fprintf(gl2ps->stream, "/F%d %d 0 R\n", gro->fontno, gro->fontobjno);
-  }
-  offs += fprintf(gl2ps->stream, ">>\n");
-
-  return offs;
-}
-
-static void gl2psPDFgroupListDelete(void)
-{
-  int i;
-  GL2PSpdfgroup *gro = NULL;
-
-  if(!gl2ps->pdfgrouplist)
-    return;
-
-  for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){
-    gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist,i);
-    gl2psListDelete(gro->ptrlist);
-  }
-
-  gl2psListDelete(gl2ps->pdfgrouplist);
-  gl2ps->pdfgrouplist = NULL;
-}
-
-/* Print 1st PDF object - file info */
-
-static int gl2psPrintPDFInfo(void)
-{
-  int offs;
-  time_t now;
-  struct tm *newtime;
-
-  time(&now);
-  newtime = gmtime(&now);
-
-  offs = fprintf(gl2ps->stream,
-                 "1 0 obj\n"
-                 "<<\n"
-                 "/Title (%s)\n"
-                 "/Creator (GL2PS %d.%d.%d%s, %s)\n"
-                 "/Producer (%s)\n",
-                 gl2ps->title, GL2PS_MAJOR_VERSION, GL2PS_MINOR_VERSION,
-                 GL2PS_PATCH_VERSION, GL2PS_EXTRA_VERSION, GL2PS_COPYRIGHT,
-                 gl2ps->producer);
-
-  if(!newtime){
-    offs += fprintf(gl2ps->stream,
-                    ">>\n"
-                    "endobj\n");
-    return offs;
-  }
-
-  offs += fprintf(gl2ps->stream,
-                  "/CreationDate (D:%d%02d%02d%02d%02d%02d)\n"
-                  ">>\n"
-                  "endobj\n",
-                  newtime->tm_year+1900,
-                  newtime->tm_mon+1,
-                  newtime->tm_mday,
-                  newtime->tm_hour,
-                  newtime->tm_min,
-                  newtime->tm_sec);
-  return offs;
-}
-
-/* Create catalog and page structure - 2nd and 3th PDF object */
-
-static int gl2psPrintPDFCatalog(void)
-{
-  return fprintf(gl2ps->stream,
-                 "2 0 obj\n"
-                 "<<\n"
-                 "/Type /Catalog\n"
-                 "/Pages 3 0 R\n"
-                 ">>\n"
-                 "endobj\n");
-}
-
-static int gl2psPrintPDFPages(void)
-{
-  return fprintf(gl2ps->stream,
-                 "3 0 obj\n"
-                 "<<\n"
-                 "/Type /Pages\n"
-                 "/Kids [6 0 R]\n"
-                 "/Count 1\n"
-                 ">>\n"
-                 "endobj\n");
-}
-
-/* Open stream for data - graphical objects, fonts etc. PDF object 4 */
-
-static int gl2psOpenPDFDataStream(void)
-{
-  int offs = 0;
-
-  offs += fprintf(gl2ps->stream,
-                  "4 0 obj\n"
-                  "<<\n"
-                  "/Length 5 0 R\n" );
-  offs += gl2psPrintPDFCompressorType();
-  offs += fprintf(gl2ps->stream,
-                  ">>\n"
-                  "stream\n");
-  return offs;
-}
-
-/* Stream setup - Graphics state, fill background if allowed */
-
-static int gl2psOpenPDFDataStreamWritePreface(void)
-{
-  int offs;
-
-  offs = gl2psPrintf("/GSa gs\n");
-
-  if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
-    offs += gl2psPrintPDFFillColor(gl2ps->bgcolor);
-    offs += gl2psPrintf("%d %d %d %d re\n",
-                        (int)gl2ps->viewport[0], (int)gl2ps->viewport[1],
-                        (int)gl2ps->viewport[2], (int)gl2ps->viewport[3]);
-    offs += gl2psPrintf("f\n");
-  }
-  return offs;
-}
-
-/* Use the functions above to create the first part of the PDF*/
-
-static void gl2psPrintPDFHeader(void)
-{
-  int offs = 0;
-  gl2ps->pdfprimlist = gl2psListCreate(500, 500, sizeof(GL2PSprimitive*));
-  gl2psPDFstacksInit();
-
-  gl2ps->xreflist = (int*)gl2psMalloc(sizeof(int) * gl2ps->objects_stack);
-
-#if defined(GL2PS_HAVE_ZLIB)
-  if(gl2ps->options & GL2PS_COMPRESS){
-    gl2psSetupCompress();
-  }
-#endif
-  gl2ps->xreflist[0] = 0;
-  offs += fprintf(gl2ps->stream, "%%PDF-1.4\n");
-  gl2ps->xreflist[1] = offs;
-
-  offs += gl2psPrintPDFInfo();
-  gl2ps->xreflist[2] = offs;
-
-  offs += gl2psPrintPDFCatalog();
-  gl2ps->xreflist[3] = offs;
-
-  offs += gl2psPrintPDFPages();
-  gl2ps->xreflist[4] = offs;
-
-  offs += gl2psOpenPDFDataStream();
-  gl2ps->xreflist[5] = offs; /* finished in gl2psPrintPDFFooter */
-  gl2ps->streamlength = gl2psOpenPDFDataStreamWritePreface();
-}
-
-/* The central primitive drawing */
-
-static void gl2psPrintPDFPrimitive(void *data)
-{
-  GL2PSprimitive *prim = *(GL2PSprimitive**)data;
-
-  if((gl2ps->options & GL2PS_OCCLUSION_CULL) && prim->culled)
-    return;
-
-  prim = gl2psCopyPrimitive(prim); /* deep copy */
-  gl2psListAdd(gl2ps->pdfprimlist, &prim);
-}
-
-/* close stream and ... */
-
-static int gl2psClosePDFDataStream(void)
-{
-  int offs = 0;
-
-#if defined(GL2PS_HAVE_ZLIB)
-  if(gl2ps->options & GL2PS_COMPRESS){
-    if(Z_OK != gl2psDeflate())
-      gl2psMsg(GL2PS_ERROR, "Zlib deflate error");
-    else
-      fwrite(gl2ps->compress->dest, gl2ps->compress->destLen, 1, gl2ps->stream);
-    gl2ps->streamlength += gl2ps->compress->destLen;
-
-    offs += gl2ps->streamlength;
-    gl2psFreeCompress();
-  }
-#endif
-
-  offs += fprintf(gl2ps->stream,
-                  "endstream\n"
-                  "endobj\n");
-  return offs;
-}
-
-/* ... write the now known length object */
-
-static int gl2psPrintPDFDataStreamLength(int val)
-{
-  return fprintf(gl2ps->stream,
-                 "5 0 obj\n"
-                 "%d\n"
-                 "endobj\n", val);
-}
-
-/* Put the info created before in PDF objects */
-
-static int gl2psPrintPDFOpenPage(void)
-{
-  int offs;
-
-  /* Write fixed part */
-
-  offs = fprintf(gl2ps->stream,
-                 "6 0 obj\n"
-                 "<<\n"
-                 "/Type /Page\n"
-                 "/Parent 3 0 R\n"
-                 "/MediaBox [%d %d %d %d]\n",
-                 (int)gl2ps->viewport[0], (int)gl2ps->viewport[1],
-                 (int)gl2ps->viewport[2], (int)gl2ps->viewport[3]);
-
-  if(gl2ps->options & GL2PS_LANDSCAPE)
-    offs += fprintf(gl2ps->stream, "/Rotate -90\n");
-
-  offs += fprintf(gl2ps->stream,
-                  "/Contents 4 0 R\n"
-                  "/Resources\n"
-                  "<<\n"
-                  "/ProcSet [/PDF /Text /ImageB /ImageC]  %%/ImageI\n");
-
-  return offs;
-
-  /* End fixed part, proceeds in gl2psPDFgroupListWriteVariableResources() */
-}
-
-static int gl2psPDFgroupListWriteVariableResources(void)
-{
-  int offs = 0;
-
-  /* a) Graphics States for shader alpha masks*/
-  offs += gl2psPDFgroupListWriteGStateResources();
-
-  /* b) Shader and shader masks */
-  offs += gl2psPDFgroupListWriteShaderResources();
-
-  /* c) XObjects (Images & Shader Masks) */
-  offs += gl2psPDFgroupListWriteXObjectResources();
-
-  /* d) Fonts */
-  offs += gl2psPDFgroupListWriteFontResources();
-
-  /* End resources and page */
-  offs += fprintf(gl2ps->stream,
-                  ">>\n"
-                  ">>\n"
-                  "endobj\n");
-  return offs;
-}
-
-/* Standard Graphics State */
-
-static int gl2psPrintPDFGSObject(void)
-{
-  return fprintf(gl2ps->stream,
-                 "7 0 obj\n"
-                 "<<\n"
-                 "/Type /ExtGState\n"
-                 "/SA false\n"
-                 "/SM 0.02\n"
-                 "/OP false\n"
-                 "/op false\n"
-                 "/OPM 0\n"
-                 "/BG2 /Default\n"
-                 "/UCR2 /Default\n"
-                 "/TR2 /Default\n"
-                 ">>\n"
-                 "endobj\n");
-}
-
-/* Put vertex' edge flag (8bit) and coordinates (32bit) in shader stream */
-
-static int gl2psPrintPDFShaderStreamDataCoord(GL2PSvertex *vertex,
-                                              int (*action)(unsigned long data, int size),
-                                              GLfloat dx, GLfloat dy,
-                                              GLfloat xmin, GLfloat ymin)
-{
-  int offs = 0;
-  unsigned long imap;
-  GLfloat diff;
-  double dmax = ~1UL;
-  char edgeflag = 0;
-
-  /* FIXME: temp bux fix for 64 bit archs: */
-  if(sizeof(unsigned long) == 8) dmax = dmax - 2048.;
-
-  offs += (*action)(edgeflag, 1);
-
-  /* The Shader stream in PDF requires to be in a 'big-endian'
-     order */
-
-  if(GL2PS_ZERO(dx * dy)){
-    offs += (*action)(0, 4);
-    offs += (*action)(0, 4);
-  }
-  else{
-    diff = (vertex->xyz[0] - xmin) / dx;
-    if(diff > 1)
-      diff = 1.0F;
-    else if(diff < 0)
-      diff = 0.0F;
-    imap = (unsigned long)(diff * dmax);
-    offs += (*action)(imap, 4);
-
-    diff = (vertex->xyz[1] - ymin) / dy;
-    if(diff > 1)
-      diff = 1.0F;
-    else if(diff < 0)
-      diff = 0.0F;
-    imap = (unsigned long)(diff * dmax);
-    offs += (*action)(imap, 4);
-  }
-
-  return offs;
-}
-
-/* Put vertex' rgb value (8bit for every component) in shader stream */
-
-static int gl2psPrintPDFShaderStreamDataRGB(GL2PSvertex *vertex,
-                                            int (*action)(unsigned long data, int size))
-{
-  int offs = 0;
-  unsigned long imap;
-  double dmax = ~1UL;
-
-  /* FIXME: temp bux fix for 64 bit archs: */
-  if(sizeof(unsigned long) == 8) dmax = dmax - 2048.;
-
-  imap = (unsigned long)((vertex->rgba[0]) * dmax);
-  offs += (*action)(imap, 1);
-
-  imap = (unsigned long)((vertex->rgba[1]) * dmax);
-  offs += (*action)(imap, 1);
-
-  imap = (unsigned long)((vertex->rgba[2]) * dmax);
-  offs += (*action)(imap, 1);
-
-  return offs;
-}
-
-/* Put vertex' alpha (8/16bit) in shader stream */
-
-static int gl2psPrintPDFShaderStreamDataAlpha(GL2PSvertex *vertex,
-                                              int (*action)(unsigned long data, int size),
-                                              int sigbyte)
-{
-  int offs = 0;
-  unsigned long imap;
-  double dmax = ~1UL;
-
-  /* FIXME: temp bux fix for 64 bit archs: */
-  if(sizeof(unsigned long) == 8) dmax = dmax - 2048.;
-
-  if(sigbyte != 8 && sigbyte != 16)
-    sigbyte = 8;
-
-  sigbyte /= 8;
-
-  imap = (unsigned long)((vertex->rgba[3]) * dmax);
-
-  offs += (*action)(imap, sigbyte);
-
-  return offs;
-}
-
-/* Put a triangles raw data in shader stream */
-
-static int gl2psPrintPDFShaderStreamData(GL2PStriangle *triangle,
-                                         GLfloat dx, GLfloat dy,
-                                         GLfloat xmin, GLfloat ymin,
-                                         int (*action)(unsigned long data, int size),
-                                         int gray)
-{
-  int i, offs = 0;
-  GL2PSvertex v;
-
-  if(gray && gray != 8 && gray != 16)
-    gray = 8;
-
-  for(i = 0; i < 3; ++i){
-    offs += gl2psPrintPDFShaderStreamDataCoord(&triangle->vertex[i], action,
-                                               dx, dy, xmin, ymin);
-    if(gray){
-      v = triangle->vertex[i];
-      offs += gl2psPrintPDFShaderStreamDataAlpha(&v, action, gray);
-    }
-    else{
-      offs += gl2psPrintPDFShaderStreamDataRGB(&triangle->vertex[i], action);
-    }
-  }
-
-  return offs;
-}
-
-static void gl2psPDFRectHull(GLfloat *xmin, GLfloat *xmax,
-                             GLfloat *ymin, GLfloat *ymax,
-                             GL2PStriangle *triangles, int cnt)
-{
-  int i, j;
-
-  *xmin = triangles[0].vertex[0].xyz[0];
-  *xmax = triangles[0].vertex[0].xyz[0];
-  *ymin = triangles[0].vertex[0].xyz[1];
-  *ymax = triangles[0].vertex[0].xyz[1];
-
-  for(i = 0; i < cnt; ++i){
-    for(j = 0; j < 3; ++j){
-      if(*xmin > triangles[i].vertex[j].xyz[0])
-        *xmin = triangles[i].vertex[j].xyz[0];
-      if(*xmax < triangles[i].vertex[j].xyz[0])
-        *xmax = triangles[i].vertex[j].xyz[0];
-      if(*ymin > triangles[i].vertex[j].xyz[1])
-        *ymin = triangles[i].vertex[j].xyz[1];
-      if(*ymax < triangles[i].vertex[j].xyz[1])
-        *ymax = triangles[i].vertex[j].xyz[1];
-    }
-  }
-}
-
-/* Writes shaded triangle
-   gray == 0 means write RGB triangles
-   gray == 8             8bit-grayscale (for alpha masks)
-   gray == 16            16bit-grayscale (for alpha masks) */
-
-static int gl2psPrintPDFShader(int obj, GL2PStriangle *triangles,
-                               int size, int gray)
-{
-  int i, offs = 0, vertexbytes, done = 0;
-  GLfloat xmin, xmax, ymin, ymax;
-
-  switch(gray){
-  case 0:
-    vertexbytes = 1+4+4+1+1+1;
-    break;
-  case 8:
-    vertexbytes = 1+4+4+1;
-    break;
-  case 16:
-    vertexbytes = 1+4+4+2;
-    break;
-  default:
-    gray = 8;
-    vertexbytes = 1+4+4+1;
-    break;
-  }
-
-  gl2psPDFRectHull(&xmin, &xmax, &ymin, &ymax, triangles, size);
-
-  offs += fprintf(gl2ps->stream,
-                  "%d 0 obj\n"
-                  "<< "
-                  "/ShadingType 4 "
-                  "/ColorSpace %s "
-                  "/BitsPerCoordinate 32 "
-                  "/BitsPerComponent %d "
-                  "/BitsPerFlag 8 "
-                  "/Decode [%f %f %f %f 0 1 %s] ",
-                  obj,
-                  (gray) ? "/DeviceGray" : "/DeviceRGB",
-                  (gray) ? gray : 8,
-                  xmin, xmax, ymin, ymax,
-                  (gray) ? "" : "0 1 0 1");
-
-#if defined(GL2PS_HAVE_ZLIB)
-  if(gl2ps->options & GL2PS_COMPRESS){
-    gl2psAllocCompress(vertexbytes * size * 3);
-
-    for(i = 0; i < size; ++i)
-      gl2psPrintPDFShaderStreamData(&triangles[i],
-                                    xmax-xmin, ymax-ymin, xmin, ymin,
-                                    gl2psWriteBigEndianCompress, gray);
-
-    if(Z_OK == gl2psDeflate() && 23 + gl2ps->compress->destLen < gl2ps->compress->srcLen){
-      offs += gl2psPrintPDFCompressorType();
-      offs += fprintf(gl2ps->stream,
-                      "/Length %d "
-                      ">>\n"
-                      "stream\n",
-                      (int)gl2ps->compress->destLen);
-      offs += gl2ps->compress->destLen * fwrite(gl2ps->compress->dest,
-                                                gl2ps->compress->destLen,
-                                                1, gl2ps->stream);
-      done = 1;
-    }
-    gl2psFreeCompress();
-  }
-#endif
-
-  if(!done){
-    /* no compression, or too long after compression, or compress error
-       -> write non-compressed entry */
-    offs += fprintf(gl2ps->stream,
-                    "/Length %d "
-                    ">>\n"
-                    "stream\n",
-                    vertexbytes * 3 * size);
-    for(i = 0; i < size; ++i)
-      offs += gl2psPrintPDFShaderStreamData(&triangles[i],
-                                            xmax-xmin, ymax-ymin, xmin, ymin,
-                                            gl2psWriteBigEndian, gray);
-  }
-
-  offs += fprintf(gl2ps->stream,
-                  "\nendstream\n"
-                  "endobj\n");
-
-  return offs;
-}
-
-/* Writes a XObject for a shaded triangle mask */
-
-static int gl2psPrintPDFShaderMask(int obj, int childobj)
-{
-  int offs = 0, len;
-
-  offs += fprintf(gl2ps->stream,
-                  "%d 0 obj\n"
-                  "<<\n"
-                  "/Type /XObject\n"
-                  "/Subtype /Form\n"
-                  "/BBox [ %d %d %d %d ]\n"
-                  "/Group \n<<\n/S /Transparency /CS /DeviceRGB\n"
-                  ">>\n",
-                  obj,
-                  (int)gl2ps->viewport[0], (int)gl2ps->viewport[1],
-                  (int)gl2ps->viewport[2], (int)gl2ps->viewport[3]);
-
-  len = (childobj>0)
-    ? strlen("/TrSh sh\n") + (int)log10((double)childobj)+1
-    : strlen("/TrSh0 sh\n");
-
-  offs += fprintf(gl2ps->stream,
-                  "/Length %d\n"
-                  ">>\n"
-                  "stream\n",
-                  len);
-  offs += fprintf(gl2ps->stream,
-                  "/TrSh%d sh\n",
-                  childobj);
-  offs += fprintf(gl2ps->stream,
-                  "endstream\n"
-                  "endobj\n");
-
-  return offs;
-}
-
-/* Writes a Extended graphics state for a shaded triangle mask if
-   simplealpha ist true the childobj argument is ignored and a /ca
-   statement will be written instead */
-
-static int gl2psPrintPDFShaderExtGS(int obj, int childobj)
-{
-  int offs = 0;
-
-  offs += fprintf(gl2ps->stream,
-                  "%d 0 obj\n"
-                  "<<\n",
-                  obj);
-
-  offs += fprintf(gl2ps->stream,
-                  "/SMask << /S /Alpha /G %d 0 R >> ",
-                  childobj);
-
-  offs += fprintf(gl2ps->stream,
-                  ">>\n"
-                  "endobj\n");
-  return offs;
-}
-
-/* a simple graphics state */
-
-static int gl2psPrintPDFShaderSimpleExtGS(int obj, GLfloat alpha)
-{
-  int offs = 0;
-
-  offs += fprintf(gl2ps->stream,
-                  "%d 0 obj\n"
-                  "<<\n"
-                  "/ca %g"
-                  ">>\n"
-                  "endobj\n",
-                  obj, alpha);
-  return offs;
-}
-
-/* Similar groups of functions for pixmaps and text */
-
-static int gl2psPrintPDFPixmapStreamData(GL2PSimage *im,
-                                         int (*action)(unsigned long data, int size),
-                                         int gray)
-{
-  int x, y, shift;
-  GLfloat r, g, b, a;
-
-  if(im->format != GL_RGBA && gray)
-    return 0;
-
-  if(gray && gray != 8 && gray != 16)
-    gray = 8;
-
-  gray /= 8;
-
-  shift = (sizeof(unsigned long) - 1) * 8;
-
-  for(y = 0; y < im->height; ++y){
-    for(x = 0; x < im->width; ++x){
-      a = gl2psGetRGB(im, x, y, &r, &g, &b);
-      if(im->format == GL_RGBA && gray){
-        (*action)((unsigned long)(a * 255) << shift, gray);
-      }
-      else{
-        (*action)((unsigned long)(r * 255) << shift, 1);
-        (*action)((unsigned long)(g * 255) << shift, 1);
-        (*action)((unsigned long)(b * 255) << shift, 1);
-      }
-    }
-  }
-
-  switch(gray){
-  case 0: return 3 * im->width * im->height;
-  case 1: return im->width * im->height;
-  case 2: return 2 * im->width * im->height;
-  default: return 3 * im->width * im->height;
-  }
-}
-
-static int gl2psPrintPDFPixmap(int obj, int childobj, GL2PSimage *im, int gray)
-{
-  int offs = 0, done = 0, sigbytes = 3;
-
-  if(gray && gray !=8 && gray != 16)
-    gray = 8;
-
-  if(gray)
-    sigbytes = gray / 8;
-
-  offs += fprintf(gl2ps->stream,
-                  "%d 0 obj\n"
-                  "<<\n"
-                  "/Type /XObject\n"
-                  "/Subtype /Image\n"
-                  "/Width %d\n"
-                  "/Height %d\n"
-                  "/ColorSpace %s \n"
-                  "/BitsPerComponent 8\n",
-                  obj,
-                  (int)im->width, (int)im->height,
-                  (gray) ? "/DeviceGray" : "/DeviceRGB" );
-  if(GL_RGBA == im->format && gray == 0){
-    offs += fprintf(gl2ps->stream,
-                    "/SMask %d 0 R\n",
-                    childobj);
-  }
-
-#if defined(GL2PS_HAVE_ZLIB)
-  if(gl2ps->options & GL2PS_COMPRESS){
-    gl2psAllocCompress((int)(im->width * im->height * sigbytes));
-
-    gl2psPrintPDFPixmapStreamData(im, gl2psWriteBigEndianCompress, gray);
-
-    if(Z_OK == gl2psDeflate() && 23 + gl2ps->compress->destLen < gl2ps->compress->srcLen){
-      offs += gl2psPrintPDFCompressorType();
-      offs += fprintf(gl2ps->stream,
-                      "/Length %d "
-                      ">>\n"
-                      "stream\n",
-                      (int)gl2ps->compress->destLen);
-      offs += gl2ps->compress->destLen * fwrite(gl2ps->compress->dest, gl2ps->compress->destLen,
-                                                1, gl2ps->stream);
-      done = 1;
-    }
-    gl2psFreeCompress();
-  }
-#endif
-
-  if(!done){
-    /* no compression, or too long after compression, or compress error
-       -> write non-compressed entry */
-    offs += fprintf(gl2ps->stream,
-                    "/Length %d "
-                    ">>\n"
-                    "stream\n",
-                    (int)(im->width * im->height * sigbytes));
-    offs += gl2psPrintPDFPixmapStreamData(im, gl2psWriteBigEndian, gray);
-  }
-
-  offs += fprintf(gl2ps->stream,
-                  "\nendstream\n"
-                  "endobj\n");
-
-  return offs;
-}
-
-static int gl2psPrintPDFText(int obj, GL2PSstring *s, int fontnumber)
-{
-  int offs = 0;
-
-  offs += fprintf(gl2ps->stream,
-                  "%d 0 obj\n"
-                  "<<\n"
-                  "/Type /Font\n"
-                  "/Subtype /Type1\n"
-                  "/Name /F%d\n"
-                  "/BaseFont /%s\n"
-                  "/Encoding /MacRomanEncoding\n"
-                  ">>\n"
-                  "endobj\n",
-                  obj, fontnumber, s->fontname);
-  return offs;
-}
-
-/* Write the physical objects */
-
-static int gl2psPDFgroupListWriteObjects(int entryoffs)
-{
-  int i,j;
-  GL2PSprimitive *p = NULL;
-  GL2PSpdfgroup *gro;
-  int offs = entryoffs;
-  GL2PStriangle *triangles;
-  int size = 0;
-
-  if(!gl2ps->pdfgrouplist)
-    return offs;
-
-  for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){
-    gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i);
-    if(!gl2psListNbr(gro->ptrlist))
-      continue;
-    p = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, 0);
-    switch(p->type){
-    case GL2PS_POINT:
-      break;
-    case GL2PS_LINE:
-      break;
-    case GL2PS_TRIANGLE:
-      size = gl2psListNbr(gro->ptrlist);
-      triangles = (GL2PStriangle*)gl2psMalloc(sizeof(GL2PStriangle) * size);
-      for(j = 0; j < size; ++j){
-        p = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
-        gl2psFillTriangleFromPrimitive(&triangles[j], p, GL_TRUE);
-      }
-      if(triangles[0].prop & T_VAR_COLOR){
-        gl2ps->xreflist[gro->shobjno] = offs;
-        offs += gl2psPrintPDFShader(gro->shobjno, triangles, size, 0);
-      }
-      if(triangles[0].prop & T_ALPHA_LESS_1){
-        gl2ps->xreflist[gro->gsobjno] = offs;
-        offs += gl2psPrintPDFShaderSimpleExtGS(gro->gsobjno, triangles[0].vertex[0].rgba[3]);
-      }
-      if(triangles[0].prop & T_VAR_ALPHA){
-        gl2ps->xreflist[gro->gsobjno] = offs;
-        offs += gl2psPrintPDFShaderExtGS(gro->gsobjno, gro->trgroupobjno);
-        gl2ps->xreflist[gro->trgroupobjno] = offs;
-        offs += gl2psPrintPDFShaderMask(gro->trgroupobjno, gro->maskshno);
-        gl2ps->xreflist[gro->maskshobjno] = offs;
-        offs += gl2psPrintPDFShader(gro->maskshobjno, triangles, size, 8);
-      }
-      gl2psFree(triangles);
-      break;
-    case GL2PS_PIXMAP:
-      gl2ps->xreflist[gro->imobjno] = offs;
-      offs += gl2psPrintPDFPixmap(gro->imobjno, gro->imobjno+1, p->data.image, 0);
-      if(p->data.image->format == GL_RGBA){
-        gl2ps->xreflist[gro->imobjno+1] = offs;
-        offs += gl2psPrintPDFPixmap(gro->imobjno+1, -1, p->data.image, 8);
-      }
-      break;
-    case GL2PS_TEXT:
-      gl2ps->xreflist[gro->fontobjno] = offs;
-      offs += gl2psPrintPDFText(gro->fontobjno,p->data.text,gro->fontno);
-      break;
-    case GL2PS_SPECIAL :
-      /* alignment contains the format for which the special output text
-         is intended */
-      if(p->data.text->alignment == GL2PS_PDF)
-        offs += fprintf(gl2ps->stream, "%s\n", p->data.text->str);
-      break;
-    default:
-      break;
-    }
-  }
-  return offs;
-}
-
-/* All variable data has been written at this point and all required
-   functioninality has been gathered, so we can write now file footer
-   with cross reference table and trailer */
-
-static void gl2psPrintPDFFooter(void)
-{
-  int i, offs;
-
-  gl2psPDFgroupListInit();
-  gl2psPDFgroupListWriteMainStream();
-
-  offs = gl2ps->xreflist[5] + gl2ps->streamlength;
-  offs += gl2psClosePDFDataStream();
-  gl2ps->xreflist[5] = offs;
-
-  offs += gl2psPrintPDFDataStreamLength(gl2ps->streamlength);
-  gl2ps->xreflist[6] = offs;
-  gl2ps->streamlength = 0;
-
-  offs += gl2psPrintPDFOpenPage();
-  offs += gl2psPDFgroupListWriteVariableResources();
-  gl2ps->xreflist = (int*)gl2psRealloc(gl2ps->xreflist,
-                                       sizeof(int) * (gl2ps->objects_stack + 1));
-  gl2ps->xreflist[7] = offs;
-
-  offs += gl2psPrintPDFGSObject();
-  gl2ps->xreflist[8] = offs;
-
-  gl2ps->xreflist[gl2ps->objects_stack] =
-    gl2psPDFgroupListWriteObjects(gl2ps->xreflist[8]);
-
-  /* Start cross reference table. The file has to been opened in
-     binary mode to preserve the 20 digit string length! */
-  fprintf(gl2ps->stream,
-          "xref\n"
-          "0 %d\n"
-          "%010d 65535 f \n", gl2ps->objects_stack, 0);
-
-  for(i = 1; i < gl2ps->objects_stack; ++i)
-    fprintf(gl2ps->stream, "%010d 00000 n \n", gl2ps->xreflist[i]);
-
-  fprintf(gl2ps->stream,
-          "trailer\n"
-          "<<\n"
-          "/Size %d\n"
-          "/Info 1 0 R\n"
-          "/Root 2 0 R\n"
-          ">>\n"
-          "startxref\n%d\n"
-          "%%%%EOF\n",
-          gl2ps->objects_stack, gl2ps->xreflist[gl2ps->objects_stack]);
-
-  /* Free auxiliary lists and arrays */
-  gl2psFree(gl2ps->xreflist);
-  gl2psListAction(gl2ps->pdfprimlist, gl2psFreePrimitive);
-  gl2psListDelete(gl2ps->pdfprimlist);
-  gl2psPDFgroupListDelete();
-
-#if defined(GL2PS_HAVE_ZLIB)
-  if(gl2ps->options & GL2PS_COMPRESS){
-    gl2psFreeCompress();
-    gl2psFree(gl2ps->compress);
-    gl2ps->compress = NULL;
-  }
-#endif
-}
-
-/* PDF begin viewport */
-
-static void gl2psPrintPDFBeginViewport(GLint viewport[4])
-{
-  int offs = 0;
-  GLint index;
-  GLfloat rgba[4];
-  int x = viewport[0], y = viewport[1], w = viewport[2], h = viewport[3];
-
-  glRenderMode(GL_FEEDBACK);
-
-  if(gl2ps->header){
-    gl2psPrintPDFHeader();
-    gl2ps->header = GL_FALSE;
-  }
-
-  offs += gl2psPrintf("q\n");
-
-  if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
-    if(gl2ps->colormode == GL_RGBA || gl2ps->colorsize == 0){
-      glGetFloatv(GL_COLOR_CLEAR_VALUE, rgba);
-    }
-    else{
-      glGetIntegerv(GL_INDEX_CLEAR_VALUE, &index);
-      rgba[0] = gl2ps->colormap[index][0];
-      rgba[1] = gl2ps->colormap[index][1];
-      rgba[2] = gl2ps->colormap[index][2];
-      rgba[3] = 1.0F;
-    }
-    offs += gl2psPrintPDFFillColor(rgba);
-    offs += gl2psPrintf("%d %d %d %d re\n"
-                        "W\n"
-                        "f\n",
-                        x, y, w, h);
-  }
-  else{
-    offs += gl2psPrintf("%d %d %d %d re\n"
-                        "W\n"
-                        "n\n",
-                        x, y, w, h);
-  }
-
-  gl2ps->streamlength += offs;
-}
-
-static GLint gl2psPrintPDFEndViewport(void)
-{
-  GLint res;
-
-  res = gl2psPrintPrimitives();
-  gl2ps->streamlength += gl2psPrintf("Q\n");
-  return res;
-}
-
-static void gl2psPrintPDFFinalPrimitive(void)
-{
-}
-
-/* definition of the PDF backend */
-
-static GL2PSbackend gl2psPDF = {
-  gl2psPrintPDFHeader,
-  gl2psPrintPDFFooter,
-  gl2psPrintPDFBeginViewport,
-  gl2psPrintPDFEndViewport,
-  gl2psPrintPDFPrimitive,
-  gl2psPrintPDFFinalPrimitive,
-  "pdf",
-  "Portable Document Format"
-};
-
-/*********************************************************************
- *
- * SVG routines
- *
- *********************************************************************/
-
-static void gl2psSVGGetCoordsAndColors(int n, GL2PSvertex *verts,
-                                       GL2PSxyz *xyz, GL2PSrgba *rgba)
-{
-  int i, j;
-
-  for(i = 0; i < n; i++){
-    xyz[i][0] = verts[i].xyz[0];
-    xyz[i][1] = gl2ps->viewport[3] - verts[i].xyz[1];
-    xyz[i][2] = 0.0F;
-    for(j = 0; j < 4; j++)
-      rgba[i][j] = verts[i].rgba[j];
-  }
-}
-
-static void gl2psSVGGetColorString(GL2PSrgba rgba, char str[32])
-{
-  int r = (int)(255. * rgba[0]);
-  int g = (int)(255. * rgba[1]);
-  int b = (int)(255. * rgba[2]);
-  int rc = (r < 0) ? 0 : (r > 255) ? 255 : r;
-  int gc = (g < 0) ? 0 : (g > 255) ? 255 : g;
-  int bc = (b < 0) ? 0 : (b > 255) ? 255 : b;
-  sprintf(str, "#%2.2x%2.2x%2.2x", rc, gc, bc);
-}
-
-static void gl2psPrintSVGHeader(void)
-{
-  int x, y, width, height;
-  char col[32];
-  time_t now;
-
-  time(&now);
-
-  if (gl2ps->options & GL2PS_LANDSCAPE){
-    x = (int)gl2ps->viewport[1];
-    y = (int)gl2ps->viewport[0];
-    width = (int)gl2ps->viewport[3];
-    height = (int)gl2ps->viewport[2];
-  }
-  else{
-    x = (int)gl2ps->viewport[0];
-    y = (int)gl2ps->viewport[1];
-    width = (int)gl2ps->viewport[2];
-    height = (int)gl2ps->viewport[3];
-  }
-
-  /* Compressed SVG files (.svgz) are simply gzipped SVG files */
-  gl2psPrintGzipHeader();
-
-  gl2psPrintf("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n");
-  gl2psPrintf("<svg xmlns=\"http://www.w3.org/2000/svg\"\n");
-  gl2psPrintf("     xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n"
-              "     width=\"%dpx\" height=\"%dpx\" viewBox=\"%d %d %d %d\">\n",
-              width, height, x, y, width, height);
-  gl2psPrintf("<title>%s</title>\n", gl2ps->title);
-  gl2psPrintf("<desc>\n");
-  gl2psPrintf("Creator: GL2PS %d.%d.%d%s, %s\n"
-              "For: %s\n"
-              "CreationDate: %s",
-              GL2PS_MAJOR_VERSION, GL2PS_MINOR_VERSION, GL2PS_PATCH_VERSION,
-              GL2PS_EXTRA_VERSION, GL2PS_COPYRIGHT, gl2ps->producer, ctime(&now));
-  gl2psPrintf("</desc>\n");
-  gl2psPrintf("<defs>\n");
-  gl2psPrintf("</defs>\n");
-
-  if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
-    gl2psSVGGetColorString(gl2ps->bgcolor, col);
-    gl2psPrintf("<polygon fill=\"%s\" points=\"%d,%d %d,%d %d,%d %d,%d\"/>\n", col,
-                (int)gl2ps->viewport[0], (int)gl2ps->viewport[1],
-                (int)gl2ps->viewport[2], (int)gl2ps->viewport[1],
-                (int)gl2ps->viewport[2], (int)gl2ps->viewport[3],
-                (int)gl2ps->viewport[0], (int)gl2ps->viewport[3]);
-  }
-
-  /* group all the primitives and disable antialiasing */
-  gl2psPrintf("<g shape-rendering=\"crispEdges\">\n");
-}
-
-static void gl2psPrintSVGSmoothTriangle(GL2PSxyz xyz[3], GL2PSrgba rgba[3])
-{
-  int i;
-  GL2PSxyz xyz2[3];
-  GL2PSrgba rgba2[3];
-  char col[32];
-
-  /* Apparently there is no easy way to do Gouraud shading in SVG
-     without explicitly pre-defining gradients, so for now we just do
-     recursive subdivision */
-
-  if(gl2psSameColorThreshold(3, rgba, gl2ps->threshold)){
-    gl2psSVGGetColorString(rgba[0], col);
-    gl2psPrintf("<polygon fill=\"%s\" ", col);
-    if(rgba[0][3] < 1.0F) gl2psPrintf("fill-opacity=\"%g\" ", rgba[0][3]);
-    gl2psPrintf("points=\"%g,%g %g,%g %g,%g\"/>\n", xyz[0][0], xyz[0][1],
-                xyz[1][0], xyz[1][1], xyz[2][0], xyz[2][1]);
-  }
-  else{
-    /* subdivide into 4 subtriangles */
-    for(i = 0; i < 3; i++){
-      xyz2[0][i] = xyz[0][i];
-      xyz2[1][i] = 0.5F * (xyz[0][i] + xyz[1][i]);
-      xyz2[2][i] = 0.5F * (xyz[0][i] + xyz[2][i]);
-    }
-    for(i = 0; i < 4; i++){
-      rgba2[0][i] = rgba[0][i];
-      rgba2[1][i] = 0.5F * (rgba[0][i] + rgba[1][i]);
-      rgba2[2][i] = 0.5F * (rgba[0][i] + rgba[2][i]);
-    }
-    gl2psPrintSVGSmoothTriangle(xyz2, rgba2);
-    for(i = 0; i < 3; i++){
-      xyz2[0][i] = 0.5F * (xyz[0][i] + xyz[1][i]);
-      xyz2[1][i] = xyz[1][i];
-      xyz2[2][i] = 0.5F * (xyz[1][i] + xyz[2][i]);
-    }
-    for(i = 0; i < 4; i++){
-      rgba2[0][i] = 0.5F * (rgba[0][i] + rgba[1][i]);
-      rgba2[1][i] = rgba[1][i];
-      rgba2[2][i] = 0.5F * (rgba[1][i] + rgba[2][i]);
-    }
-    gl2psPrintSVGSmoothTriangle(xyz2, rgba2);
-    for(i = 0; i < 3; i++){
-      xyz2[0][i] = 0.5F * (xyz[0][i] + xyz[2][i]);
-      xyz2[1][i] = xyz[2][i];
-      xyz2[2][i] = 0.5F * (xyz[1][i] + xyz[2][i]);
-    }
-    for(i = 0; i < 4; i++){
-      rgba2[0][i] = 0.5F * (rgba[0][i] + rgba[2][i]);
-      rgba2[1][i] = rgba[2][i];
-      rgba2[2][i] = 0.5F * (rgba[1][i] + rgba[2][i]);
-    }
-    gl2psPrintSVGSmoothTriangle(xyz2, rgba2);
-    for(i = 0; i < 3; i++){
-      xyz2[0][i] = 0.5F * (xyz[0][i] + xyz[1][i]);
-      xyz2[1][i] = 0.5F * (xyz[1][i] + xyz[2][i]);
-      xyz2[2][i] = 0.5F * (xyz[0][i] + xyz[2][i]);
-    }
-    for(i = 0; i < 4; i++){
-      rgba2[0][i] = 0.5F * (rgba[0][i] + rgba[1][i]);
-      rgba2[1][i] = 0.5F * (rgba[1][i] + rgba[2][i]);
-      rgba2[2][i] = 0.5F * (rgba[0][i] + rgba[2][i]);
-    }
-    gl2psPrintSVGSmoothTriangle(xyz2, rgba2);
-  }
-}
-
-static void gl2psPrintSVGDash(GLushort pattern, GLint factor)
-{
-  int i, n, array[10];
-
-  if(!pattern || !factor) return; /* solid line */
-
-  gl2psParseStipplePattern(pattern, factor, &n, array);
-  gl2psPrintf("stroke-dasharray=\"");
-  for(i = 0; i < n; i++){
-    if(i) gl2psPrintf(",");
-    gl2psPrintf("%d", array[i]);
-  }
-  gl2psPrintf("\" ");
-}
-
-static void gl2psEndSVGLine(void)
-{
-  int i;
-  if(gl2ps->lastvertex.rgba[0] >= 0.){
-    gl2psPrintf("%g,%g\"/>\n", gl2ps->lastvertex.xyz[0],
-                gl2ps->viewport[3] - gl2ps->lastvertex.xyz[1]);
-    for(i = 0; i < 3; i++)
-      gl2ps->lastvertex.xyz[i] = -1.;
-    for(i = 0; i < 4; i++)
-      gl2ps->lastvertex.rgba[i] = -1.;
-  }
-}
-
-static void gl2psPrintSVGPixmap(GLfloat x, GLfloat y, GL2PSimage *pixmap)
-{
-#if defined(GL2PS_HAVE_LIBPNG)
-  GL2PSlist *png;
-  unsigned char c;
-  int i;
-
-  /* The only image types supported by the SVG standard are JPEG, PNG
-     and SVG. Here we choose PNG, and since we want to embed the image
-     directly in the SVG stream (and not link to an external image
-     file), we need to encode the pixmap into PNG in memory, then
-     encode it into base64. */
-
-  png = gl2psListCreate(pixmap->width * pixmap->height * 3, 1000,
-                        sizeof(unsigned char));
-  gl2psConvertPixmapToPNG(pixmap, png);
-  gl2psListEncodeBase64(png);
-  gl2psPrintf("<image x=\"%g\" y=\"%g\" width=\"%d\" height=\"%d\"\n",
-              x, y - pixmap->height, pixmap->width, pixmap->height);
-  gl2psPrintf("xlink:href=\"data:image/png;base64,");
-  for(i = 0; i < gl2psListNbr(png); i++){
-    gl2psListRead(png, i, &c);
-    gl2psPrintf("%c", c);
-  }
-  gl2psPrintf("\"/>\n");
-  gl2psListDelete(png);
-#else
-  (void) x; (void) y; (void) pixmap;  /* not used */
-  gl2psMsg(GL2PS_WARNING, "GL2PS must be compiled with PNG support in "
-           "order to embed images in SVG streams");
-#endif
-}
-
-static void gl2psPrintSVGPrimitive(void *data)
-{
-  GL2PSprimitive *prim;
-  GL2PSxyz xyz[4];
-  GL2PSrgba rgba[4];
-  char col[32];
-  int newline;
-
-  prim = *(GL2PSprimitive**)data;
-
-  if((gl2ps->options & GL2PS_OCCLUSION_CULL) && prim->culled) return;
-
-  /* We try to draw connected lines as a single path to get nice line
-     joins and correct stippling. So if the primitive to print is not
-     a line we must first finish the current line (if any): */
-  if(prim->type != GL2PS_LINE) gl2psEndSVGLine();
-
-  gl2psSVGGetCoordsAndColors(prim->numverts, prim->verts, xyz, rgba);
-
-  switch(prim->type){
-  case GL2PS_POINT :
-    gl2psSVGGetColorString(rgba[0], col);
-    gl2psPrintf("<circle fill=\"%s\" ", col);
-    if(rgba[0][3] < 1.0F) gl2psPrintf("fill-opacity=\"%g\" ", rgba[0][3]);
-    gl2psPrintf("cx=\"%g\" cy=\"%g\" r=\"%g\"/>\n",
-                xyz[0][0], xyz[0][1], 0.5 * prim->width);
-    break;
-  case GL2PS_LINE :
-    if(!gl2psSamePosition(gl2ps->lastvertex.xyz, prim->verts[0].xyz) ||
-       !gl2psSameColor(gl2ps->lastrgba, prim->verts[0].rgba) ||
-       gl2ps->lastlinewidth != prim->width ||
-       gl2ps->lastpattern != prim->pattern ||
-       gl2ps->lastfactor != prim->factor){
-      /* End the current line if the new segment does not start where
-         the last one ended, or if the color, the width or the
-         stippling have changed (we will need to use multi-point
-         gradients for smooth-shaded lines) */
-      gl2psEndSVGLine();
-      newline = 1;
-    }
-    else{
-      newline = 0;
-    }
-    gl2ps->lastvertex = prim->verts[1];
-    gl2psSetLastColor(prim->verts[0].rgba);
-    gl2ps->lastlinewidth = prim->width;
-    gl2ps->lastpattern = prim->pattern;
-    gl2ps->lastfactor = prim->factor;
-    if(newline){
-      gl2psSVGGetColorString(rgba[0], col);
-      gl2psPrintf("<polyline fill=\"none\" stroke=\"%s\" stroke-width=\"%g\" ",
-                  col, prim->width);
-      if(rgba[0][3] < 1.0F) gl2psPrintf("stroke-opacity=\"%g\" ", rgba[0][3]);
-      gl2psPrintSVGDash(prim->pattern, prim->factor);
-      gl2psPrintf("points=\"%g,%g ", xyz[0][0], xyz[0][1]);
-    }
-    else{
-      gl2psPrintf("%g,%g ", xyz[0][0], xyz[0][1]);
-    }
-    break;
-  case GL2PS_TRIANGLE :
-    gl2psPrintSVGSmoothTriangle(xyz, rgba);
-    break;
-  case GL2PS_QUADRANGLE :
-    gl2psMsg(GL2PS_WARNING, "There should not be any quad left to print");
-    break;
-  case GL2PS_PIXMAP :
-    gl2psPrintSVGPixmap(xyz[0][0], xyz[0][1], prim->data.image);
-    break;
-  case GL2PS_TEXT :
-    gl2psSVGGetColorString(prim->verts[0].rgba, col);
-    gl2psPrintf("<text fill=\"%s\" x=\"%g\" y=\"%g\" font-size=\"%d\" ",
-                col, xyz[0][0], xyz[0][1], prim->data.text->fontsize);
-    if(prim->data.text->angle)
-      gl2psPrintf("transform=\"rotate(%g, %g, %g)\" ",
-                  -prim->data.text->angle, xyz[0][0], xyz[0][1]);
-    switch(prim->data.text->alignment){
-    case GL2PS_TEXT_C:
-      gl2psPrintf("text-anchor=\"middle\" baseline-shift=\"%d\" ",
-                  -prim->data.text->fontsize / 2);
-      break;
-    case GL2PS_TEXT_CL:
-      gl2psPrintf("text-anchor=\"start\" baseline-shift=\"%d\" ",
-                  -prim->data.text->fontsize / 2);
-      break;
-    case GL2PS_TEXT_CR:
-      gl2psPrintf("text-anchor=\"end\" baseline-shift=\"%d\" ",
-                  -prim->data.text->fontsize / 2);
-      break;
-    case GL2PS_TEXT_B:
-      gl2psPrintf("text-anchor=\"middle\" baseline-shift=\"0\" ");
-      break;
-    case GL2PS_TEXT_BR:
-      gl2psPrintf("text-anchor=\"end\" baseline-shift=\"0\" ");
-      break;
-    case GL2PS_TEXT_T:
-      gl2psPrintf("text-anchor=\"middle\" baseline-shift=\"%d\" ",
-                  -prim->data.text->fontsize);
-      break;
-    case GL2PS_TEXT_TL:
-      gl2psPrintf("text-anchor=\"start\" baseline-shift=\"%d\" ",
-                  -prim->data.text->fontsize);
-      break;
-    case GL2PS_TEXT_TR:
-      gl2psPrintf("text-anchor=\"end\" baseline-shift=\"%d\" ",
-                  -prim->data.text->fontsize);
-      break;
-    case GL2PS_TEXT_BL:
-    default: /* same as GL2PS_TEXT_BL */
-      gl2psPrintf("text-anchor=\"start\" baseline-shift=\"0\" ");
-      break;
-    }
-    if(!strcmp(prim->data.text->fontname, "Times-Roman"))
-      gl2psPrintf("font-family=\"Times\">");
-    else if(!strcmp(prim->data.text->fontname, "Times-Bold"))
-      gl2psPrintf("font-family=\"Times\" font-weight=\"bold\">");
-    else if(!strcmp(prim->data.text->fontname, "Times-Italic"))
-      gl2psPrintf("font-family=\"Times\" font-style=\"italic\">");
-    else if(!strcmp(prim->data.text->fontname, "Times-BoldItalic"))
-      gl2psPrintf("font-family=\"Times\" font-style=\"italic\" font-weight=\"bold\">");
-    else if(!strcmp(prim->data.text->fontname, "Helvetica-Bold"))
-      gl2psPrintf("font-family=\"Helvetica\" font-weight=\"bold\">");
-    else if(!strcmp(prim->data.text->fontname, "Helvetica-Oblique"))
-      gl2psPrintf("font-family=\"Helvetica\" font-style=\"oblique\">");
-    else if(!strcmp(prim->data.text->fontname, "Helvetica-BoldOblique"))
-      gl2psPrintf("font-family=\"Helvetica\" font-style=\"oblique\" font-weight=\"bold\">");
-    else if(!strcmp(prim->data.text->fontname, "Courier-Bold"))
-      gl2psPrintf("font-family=\"Courier\" font-weight=\"bold\">");
-    else if(!strcmp(prim->data.text->fontname, "Courier-Oblique"))
-      gl2psPrintf("font-family=\"Courier\" font-style=\"oblique\">");
-    else if(!strcmp(prim->data.text->fontname, "Courier-BoldOblique"))
-      gl2psPrintf("font-family=\"Courier\" font-style=\"oblique\" font-weight=\"bold\">");
-    else
-      gl2psPrintf("font-family=\"%s\">", prim->data.text->fontname);
-    gl2psPrintf("%s</text>\n", prim->data.text->str);
-    break;
-  case GL2PS_SPECIAL :
-    /* alignment contains the format for which the special output text
-       is intended */
-    if(prim->data.text->alignment == GL2PS_SVG)
-      gl2psPrintf("%s\n", prim->data.text->str);
-    break;
-  default :
-    break;
-  }
-}
-
-static void gl2psPrintSVGFooter(void)
-{
-  gl2psPrintf("</g>\n");
-  gl2psPrintf("</svg>\n");
-
-  gl2psPrintGzipFooter();
-}
-
-static void gl2psPrintSVGBeginViewport(GLint viewport[4])
-{
-  GLint index;
-  char col[32];
-  GLfloat rgba[4];
-  int x = viewport[0], y = viewport[1], w = viewport[2], h = viewport[3];
-
-  glRenderMode(GL_FEEDBACK);
-
-  if(gl2ps->header){
-    gl2psPrintSVGHeader();
-    gl2ps->header = GL_FALSE;
-  }
-
-  if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
-    if(gl2ps->colormode == GL_RGBA || gl2ps->colorsize == 0){
-      glGetFloatv(GL_COLOR_CLEAR_VALUE, rgba);
-    }
-    else{
-      glGetIntegerv(GL_INDEX_CLEAR_VALUE, &index);
-      rgba[0] = gl2ps->colormap[index][0];
-      rgba[1] = gl2ps->colormap[index][1];
-      rgba[2] = gl2ps->colormap[index][2];
-      rgba[3] = 1.0F;
-    }
-    gl2psSVGGetColorString(rgba, col);
-    gl2psPrintf("<polygon fill=\"%s\" points=\"%d,%d %d,%d %d,%d %d,%d\"/>\n", col,
-                x, gl2ps->viewport[3] - y,
-                x + w, gl2ps->viewport[3] - y,
-                x + w, gl2ps->viewport[3] - (y + h),
-                x, gl2ps->viewport[3] - (y + h));
-  }
-
-  gl2psPrintf("<clipPath id=\"cp%d%d%d%d\">\n", x, y, w, h);
-  gl2psPrintf("  <polygon points=\"%d,%d %d,%d %d,%d %d,%d\"/>\n",
-              x, gl2ps->viewport[3] - y,
-              x + w, gl2ps->viewport[3] - y,
-              x + w, gl2ps->viewport[3] - (y + h),
-              x, gl2ps->viewport[3] - (y + h));
-  gl2psPrintf("</clipPath>\n");
-  gl2psPrintf("<g clip-path=\"url(#cp%d%d%d%d)\">\n", x, y, w, h);
-}
-
-static GLint gl2psPrintSVGEndViewport(void)
-{
-  GLint res;
-
-  res = gl2psPrintPrimitives();
-  gl2psPrintf("</g>\n");
-  return res;
-}
-
-static void gl2psPrintSVGFinalPrimitive(void)
-{
-  /* End any remaining line, if any */
-  gl2psEndSVGLine();
-}
-
-/* definition of the SVG backend */
-
-static GL2PSbackend gl2psSVG = {
-  gl2psPrintSVGHeader,
-  gl2psPrintSVGFooter,
-  gl2psPrintSVGBeginViewport,
-  gl2psPrintSVGEndViewport,
-  gl2psPrintSVGPrimitive,
-  gl2psPrintSVGFinalPrimitive,
-  "svg",
-  "Scalable Vector Graphics"
-};
-
-/*********************************************************************
- *
- * PGF routines
- *
- *********************************************************************/
-
-static void gl2psPrintPGFColor(GL2PSrgba rgba)
-{
-  if(!gl2psSameColor(gl2ps->lastrgba, rgba)){
-    gl2psSetLastColor(rgba);
-    fprintf(gl2ps->stream, "\\color[rgb]{%f,%f,%f}\n", rgba[0], rgba[1], rgba[2]);
-  }
-}
-
-static void gl2psPrintPGFHeader(void)
-{
-  time_t now;
-
-  time(&now);
-
-  fprintf(gl2ps->stream,
-          "%% Title: %s\n"
-          "%% Creator: GL2PS %d.%d.%d%s, %s\n"
-          "%% For: %s\n"
-          "%% CreationDate: %s",
-          gl2ps->title, GL2PS_MAJOR_VERSION, GL2PS_MINOR_VERSION,
-          GL2PS_PATCH_VERSION, GL2PS_EXTRA_VERSION, GL2PS_COPYRIGHT,
-          gl2ps->producer, ctime(&now));
-
-  fprintf(gl2ps->stream, "\\begin{pgfpicture}\n");
-  if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
-    gl2psPrintPGFColor(gl2ps->bgcolor);
-    fprintf(gl2ps->stream,
-            "\\pgfpathrectanglecorners{"
-            "\\pgfpoint{%dpt}{%dpt}}{\\pgfpoint{%dpt}{%dpt}}\n"
-            "\\pgfusepath{fill}\n",
-            (int)gl2ps->viewport[0], (int)gl2ps->viewport[1],
-            (int)gl2ps->viewport[2], (int)gl2ps->viewport[3]);
-  }
-}
-
-static void gl2psPrintPGFDash(GLushort pattern, GLint factor)
-{
-  int i, n, array[10];
-
-  if(pattern == gl2ps->lastpattern && factor == gl2ps->lastfactor)
-    return;
-
-  gl2ps->lastpattern = pattern;
-  gl2ps->lastfactor = factor;
-
-  if(!pattern || !factor){
-    /* solid line */
-    fprintf(gl2ps->stream, "\\pgfsetdash{}{0pt}\n");
-  }
-  else{
-    gl2psParseStipplePattern(pattern, factor, &n, array);
-    fprintf(gl2ps->stream, "\\pgfsetdash{");
-    for(i = 0; i < n; i++) fprintf(gl2ps->stream, "{%dpt}", array[i]);
-    fprintf(gl2ps->stream, "}{0pt}\n");
-  }
-}
-
-static const char *gl2psPGFTextAlignment(int align)
-{
-  switch(align){
-  case GL2PS_TEXT_C  : return "center";
-  case GL2PS_TEXT_CL : return "west";
-  case GL2PS_TEXT_CR : return "east";
-  case GL2PS_TEXT_B  : return "south";
-  case GL2PS_TEXT_BR : return "south east";
-  case GL2PS_TEXT_T  : return "north";
-  case GL2PS_TEXT_TL : return "north west";
-  case GL2PS_TEXT_TR : return "north east";
-  case GL2PS_TEXT_BL :
-  default            : return "south west";
-  }
-}
-
-static void gl2psPrintPGFPrimitive(void *data)
-{
-  GL2PSprimitive *prim;
-
-  prim = *(GL2PSprimitive**)data;
-
-  switch(prim->type){
-  case GL2PS_POINT :
-    /* Points in openGL are rectangular */
-    gl2psPrintPGFColor(prim->verts[0].rgba);
-    fprintf(gl2ps->stream,
-            "\\pgfpathrectangle{\\pgfpoint{%fpt}{%fpt}}"
-            "{\\pgfpoint{%fpt}{%fpt}}\n\\pgfusepath{fill}\n",
-            prim->verts[0].xyz[0]-0.5*prim->width,
-            prim->verts[0].xyz[1]-0.5*prim->width,
-            prim->width,prim->width);
-    break;
-  case GL2PS_LINE :
-    gl2psPrintPGFColor(prim->verts[0].rgba);
-    if(gl2ps->lastlinewidth != prim->width){
-      gl2ps->lastlinewidth = prim->width;
-      fprintf(gl2ps->stream, "\\pgfsetlinewidth{%fpt}\n", gl2ps->lastlinewidth);
-    }
-    gl2psPrintPGFDash(prim->pattern, prim->factor);
-    fprintf(gl2ps->stream,
-            "\\pgfpathmoveto{\\pgfpoint{%fpt}{%fpt}}\n"
-            "\\pgflineto{\\pgfpoint{%fpt}{%fpt}}\n"
-            "\\pgfusepath{stroke}\n",
-            prim->verts[1].xyz[0], prim->verts[1].xyz[1],
-            prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
-    break;
-  case GL2PS_TRIANGLE :
-    if(gl2ps->lastlinewidth != 0){
-      gl2ps->lastlinewidth = 0;
-      fprintf(gl2ps->stream, "\\pgfsetlinewidth{0.01pt}\n");
-    }
-    gl2psPrintPGFColor(prim->verts[0].rgba);
-    fprintf(gl2ps->stream,
-            "\\pgfpathmoveto{\\pgfpoint{%fpt}{%fpt}}\n"
-            "\\pgflineto{\\pgfpoint{%fpt}{%fpt}}\n"
-            "\\pgflineto{\\pgfpoint{%fpt}{%fpt}}\n"
-            "\\pgfpathclose\n"
-            "\\pgfusepath{fill,stroke}\n",
-            prim->verts[2].xyz[0], prim->verts[2].xyz[1],
-            prim->verts[1].xyz[0], prim->verts[1].xyz[1],
-            prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
-    break;
-  case GL2PS_TEXT :
-    fprintf(gl2ps->stream, "{\n\\pgftransformshift{\\pgfpoint{%fpt}{%fpt}}\n",
-            prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
-
-    if(prim->data.text->angle)
-      fprintf(gl2ps->stream, "\\pgftransformrotate{%f}{", prim->data.text->angle);
-
-    fprintf(gl2ps->stream, "\\pgfnode{rectangle}{%s}{\\fontsize{%d}{0}\\selectfont",
-            gl2psPGFTextAlignment(prim->data.text->alignment),
-            prim->data.text->fontsize);
-
-    fprintf(gl2ps->stream, "\\textcolor[rgb]{%g,%g,%g}{{%s}}",
-            prim->verts[0].rgba[0], prim->verts[0].rgba[1],
-            prim->verts[0].rgba[2], prim->data.text->str);
-
-    fprintf(gl2ps->stream, "}{}{\\pgfusepath{discard}}}\n");
-    break;
-  case GL2PS_SPECIAL :
-    /* alignment contains the format for which the special output text
-       is intended */
-    if (prim->data.text->alignment == GL2PS_PGF)
-      fprintf(gl2ps->stream, "%s\n", prim->data.text->str);
-    break;
-  default :
-    break;
-  }
-}
-
-static void gl2psPrintPGFFooter(void)
-{
-  fprintf(gl2ps->stream, "\\end{pgfpicture}\n");
-}
-
-static void gl2psPrintPGFBeginViewport(GLint viewport[4])
-{
-  GLint index;
-  GLfloat rgba[4];
-  int x = viewport[0], y = viewport[1], w = viewport[2], h = viewport[3];
-
-  glRenderMode(GL_FEEDBACK);
-
-  if(gl2ps->header){
-    gl2psPrintPGFHeader();
-    gl2ps->header = GL_FALSE;
-  }
-
-  fprintf(gl2ps->stream, "\\begin{pgfscope}\n");
-  if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
-    if(gl2ps->colormode == GL_RGBA || gl2ps->colorsize == 0){
-      glGetFloatv(GL_COLOR_CLEAR_VALUE, rgba);
-    }
-    else{
-      glGetIntegerv(GL_INDEX_CLEAR_VALUE, &index);
-      rgba[0] = gl2ps->colormap[index][0];
-      rgba[1] = gl2ps->colormap[index][1];
-      rgba[2] = gl2ps->colormap[index][2];
-      rgba[3] = 1.0F;
-    }
-    gl2psPrintPGFColor(rgba);
-    fprintf(gl2ps->stream,
-            "\\pgfpathrectangle{\\pgfpoint{%dpt}{%dpt}}"
-            "{\\pgfpoint{%dpt}{%dpt}}\n"
-            "\\pgfusepath{fill}\n",
-            x, y, w, h);
-  }
-
-  fprintf(gl2ps->stream,
-          "\\pgfpathrectangle{\\pgfpoint{%dpt}{%dpt}}"
-          "{\\pgfpoint{%dpt}{%dpt}}\n"
-          "\\pgfusepath{clip}\n",
-          x, y, w, h);
-}
-
-static GLint gl2psPrintPGFEndViewport(void)
-{
-  GLint res;
-  res = gl2psPrintPrimitives();
-  fprintf(gl2ps->stream, "\\end{pgfscope}\n");
-  return res;
-}
-
-static void gl2psPrintPGFFinalPrimitive(void)
-{
-}
-
-/* definition of the PGF backend */
-
-static GL2PSbackend gl2psPGF = {
-  gl2psPrintPGFHeader,
-  gl2psPrintPGFFooter,
-  gl2psPrintPGFBeginViewport,
-  gl2psPrintPGFEndViewport,
-  gl2psPrintPGFPrimitive,
-  gl2psPrintPGFFinalPrimitive,
-  "tex",
-  "PGF Latex Graphics"
-};
-
-/*********************************************************************
- *
- * General primitive printing routine
- *
- *********************************************************************/
-
-/* Warning: the ordering of the backends must match the format
-   #defines in gl2ps.h */
-
-static GL2PSbackend *gl2psbackends[] = {
-  &gl2psPS,  /* 0 */
-  &gl2psEPS, /* 1 */
-  &gl2psTEX, /* 2 */
-  &gl2psPDF, /* 3 */
-  &gl2psSVG, /* 4 */
-  &gl2psPGF  /* 5 */
-};
-
-static void gl2psComputeTightBoundingBox(void *data)
-{
-  GL2PSprimitive *prim;
-  int i;
-
-  prim = *(GL2PSprimitive**)data;
-
-  for(i = 0; i < prim->numverts; i++){
-    if(prim->verts[i].xyz[0] < gl2ps->viewport[0])
-      gl2ps->viewport[0] = (GLint)prim->verts[i].xyz[0];
-    if(prim->verts[i].xyz[0] > gl2ps->viewport[2])
-      gl2ps->viewport[2] = (GLint)(prim->verts[i].xyz[0] + 0.5F);
-    if(prim->verts[i].xyz[1] < gl2ps->viewport[1])
-      gl2ps->viewport[1] = (GLint)prim->verts[i].xyz[1];
-    if(prim->verts[i].xyz[1] > gl2ps->viewport[3])
-      gl2ps->viewport[3] = (GLint)(prim->verts[i].xyz[1] + 0.5F);
-  }
-}
-
-static GLint gl2psPrintPrimitives(void)
-{
-  GL2PSbsptree *root;
-  GL2PSxyz eye = {0.0F, 0.0F, 100.0F * GL2PS_ZSCALE};
-  GLint used;
-
-  used = glRenderMode(GL_RENDER);
-
-  if(used < 0){
-    gl2psMsg(GL2PS_INFO, "OpenGL feedback buffer overflow");
-    return GL2PS_OVERFLOW;
-  }
-
-  if(used > 0)
-    gl2psParseFeedbackBuffer(used);
-
-  gl2psRescaleAndOffset();
-
-  if(gl2ps->header){
-    if(gl2psListNbr(gl2ps->primitives) &&
-       (gl2ps->options & GL2PS_TIGHT_BOUNDING_BOX)){
-      gl2ps->viewport[0] = gl2ps->viewport[1] = 100000;
-      gl2ps->viewport[2] = gl2ps->viewport[3] = -100000;
-      gl2psListAction(gl2ps->primitives, gl2psComputeTightBoundingBox);
-    }
-    (gl2psbackends[gl2ps->format]->printHeader)();
-    gl2ps->header = GL_FALSE;
-  }
-
-  if(!gl2psListNbr(gl2ps->primitives)){
-    /* empty feedback buffer and/or nothing else to print */
-    return GL2PS_NO_FEEDBACK;
-  }
-
-  switch(gl2ps->sort){
-  case GL2PS_NO_SORT :
-    gl2psListAction(gl2ps->primitives, gl2psbackends[gl2ps->format]->printPrimitive);
-    gl2psListAction(gl2ps->primitives, gl2psFreePrimitive);
-    /* reset the primitive list, waiting for the next viewport */
-    gl2psListReset(gl2ps->primitives);
-    break;
-  case GL2PS_SIMPLE_SORT :
-    gl2psListSort(gl2ps->primitives, gl2psCompareDepth);
-    if(gl2ps->options & GL2PS_OCCLUSION_CULL){
-      gl2psListActionInverse(gl2ps->primitives, gl2psAddInImageTree);
-      gl2psFreeBspImageTree(&gl2ps->imagetree);
-    }
-    gl2psListAction(gl2ps->primitives, gl2psbackends[gl2ps->format]->printPrimitive);
-    gl2psListAction(gl2ps->primitives, gl2psFreePrimitive);
-    /* reset the primitive list, waiting for the next viewport */
-    gl2psListReset(gl2ps->primitives);
-    break;
-  case GL2PS_BSP_SORT :
-    root = (GL2PSbsptree*)gl2psMalloc(sizeof(GL2PSbsptree));
-    gl2psBuildBspTree(root, gl2ps->primitives);
-    if(GL_TRUE == gl2ps->boundary) gl2psBuildPolygonBoundary(root);
-    if(gl2ps->options & GL2PS_OCCLUSION_CULL){
-      gl2psTraverseBspTree(root, eye, -GL2PS_EPSILON, gl2psLess,
-                           gl2psAddInImageTree, 1);
-      gl2psFreeBspImageTree(&gl2ps->imagetree);
-    }
-    gl2psTraverseBspTree(root, eye, GL2PS_EPSILON, gl2psGreater,
-                         gl2psbackends[gl2ps->format]->printPrimitive, 0);
-    gl2psFreeBspTree(&root);
-    /* reallocate the primitive list (it's been deleted by
-       gl2psBuildBspTree) in case there is another viewport */
-    gl2ps->primitives = gl2psListCreate(500, 500, sizeof(GL2PSprimitive*));
-    break;
-  }
-  gl2psbackends[gl2ps->format]->printFinalPrimitive();
-
-  return GL2PS_SUCCESS;
-}
-
-/*********************************************************************
- *
- * Public routines
- *
- *********************************************************************/
-
-GL2PSDLL_API GLint gl2psBeginPage(const char *title, const char *producer,
-                                  GLint viewport[4], GLint format, GLint sort,
-                                  GLint options, GLint colormode,
-                                  GLint colorsize, GL2PSrgba *colormap,
-                                  GLint nr, GLint ng, GLint nb, GLint buffersize,
-                                  FILE *stream, const char *filename)
-{
-  GLint index;
-  int i;
-
-  if(gl2ps){
-    gl2psMsg(GL2PS_ERROR, "gl2psBeginPage called in wrong program state");
-    return GL2PS_ERROR;
-  }
-
-  gl2ps = (GL2PScontext*)gl2psMalloc(sizeof(GL2PScontext));
-
-  if(format >= 0 && format < (GLint)(sizeof(gl2psbackends) / sizeof(gl2psbackends[0]))){
-    gl2ps->format = format;
-  }
-  else {
-    gl2psMsg(GL2PS_ERROR, "Unknown output format: %d", format);
-    gl2psFree(gl2ps);
-    gl2ps = NULL;
-    return GL2PS_ERROR;
-  }
-
-  switch(sort){
-  case GL2PS_NO_SORT :
-  case GL2PS_SIMPLE_SORT :
-  case GL2PS_BSP_SORT :
-    gl2ps->sort = sort;
-    break;
-  default :
-    gl2psMsg(GL2PS_ERROR, "Unknown sorting algorithm: %d", sort);
-    gl2psFree(gl2ps);
-    gl2ps = NULL;
-    return GL2PS_ERROR;
-  }
-
-  if(stream){
-    gl2ps->stream = stream;
-  }
-  else{
-    gl2psMsg(GL2PS_ERROR, "Bad file pointer");
-    gl2psFree(gl2ps);
-    gl2ps = NULL;
-    return GL2PS_ERROR;
-  }
-
-  gl2ps->header = GL_TRUE;
-  gl2ps->maxbestroot = 10;
-  gl2ps->options = options;
-  gl2ps->compress = NULL;
-  gl2ps->imagemap_head = NULL;
-  gl2ps->imagemap_tail = NULL;
-
-  if(gl2ps->options & GL2PS_USE_CURRENT_VIEWPORT){
-    glGetIntegerv(GL_VIEWPORT, gl2ps->viewport);
-  }
-  else{
-    for(i = 0; i < 4; i++){
-      gl2ps->viewport[i] = viewport[i];
-    }
-  }
-
-  if(!gl2ps->viewport[2] || !gl2ps->viewport[3]){
-    gl2psMsg(GL2PS_ERROR, "Incorrect viewport (x=%d, y=%d, width=%d, height=%d)",
-             gl2ps->viewport[0], gl2ps->viewport[1],
-             gl2ps->viewport[2], gl2ps->viewport[3]);
-    gl2psFree(gl2ps);
-    gl2ps = NULL;
-    return GL2PS_ERROR;
-  }
-
-  gl2ps->threshold[0] = nr ? 1.0F / (GLfloat)nr : 0.064F;
-  gl2ps->threshold[1] = ng ? 1.0F / (GLfloat)ng : 0.034F;
-  gl2ps->threshold[2] = nb ? 1.0F / (GLfloat)nb : 0.100F;
-  gl2ps->colormode = colormode;
-  gl2ps->buffersize = buffersize > 0 ? buffersize : 2048 * 2048;
-  for(i = 0; i < 3; i++){
-    gl2ps->lastvertex.xyz[i] = -1.0F;
-  }
-  for(i = 0; i < 4; i++){
-    gl2ps->lastvertex.rgba[i] = -1.0F;
-    gl2ps->lastrgba[i] = -1.0F;
-  }
-  gl2ps->lastlinewidth = -1.0F;
-  gl2ps->lastpattern = 0;
-  gl2ps->lastfactor = 0;
-  gl2ps->imagetree = NULL;
-  gl2ps->primitivetoadd = NULL;
-  gl2ps->zerosurfacearea = GL_FALSE;
-  gl2ps->pdfprimlist = NULL;
-  gl2ps->pdfgrouplist = NULL;
-  gl2ps->xreflist = NULL;
-
-  /* get default blending mode from current OpenGL state (enabled by
-     default for SVG) */
-  gl2ps->blending = (gl2ps->format == GL2PS_SVG) ? GL_TRUE : glIsEnabled(GL_BLEND);
-  glGetIntegerv(GL_BLEND_SRC, &gl2ps->blendfunc[0]);
-  glGetIntegerv(GL_BLEND_DST, &gl2ps->blendfunc[1]);
-
-  if(gl2ps->colormode == GL_RGBA){
-    gl2ps->colorsize = 0;
-    gl2ps->colormap = NULL;
-    glGetFloatv(GL_COLOR_CLEAR_VALUE, gl2ps->bgcolor);
-  }
-  else if(gl2ps->colormode == GL_COLOR_INDEX){
-    if(!colorsize || !colormap){
-      gl2psMsg(GL2PS_ERROR, "Missing colormap for GL_COLOR_INDEX rendering");
-      gl2psFree(gl2ps);
-      gl2ps = NULL;
-      return GL2PS_ERROR;
-    }
-    gl2ps->colorsize = colorsize;
-    gl2ps->colormap = (GL2PSrgba*)gl2psMalloc(gl2ps->colorsize * sizeof(GL2PSrgba));
-    memcpy(gl2ps->colormap, colormap, gl2ps->colorsize * sizeof(GL2PSrgba));
-    glGetIntegerv(GL_INDEX_CLEAR_VALUE, &index);
-    gl2ps->bgcolor[0] = gl2ps->colormap[index][0];
-    gl2ps->bgcolor[1] = gl2ps->colormap[index][1];
-    gl2ps->bgcolor[2] = gl2ps->colormap[index][2];
-    gl2ps->bgcolor[3] = 1.0F;
-  }
-  else{
-    gl2psMsg(GL2PS_ERROR, "Unknown color mode in gl2psBeginPage");
-    gl2psFree(gl2ps);
-    gl2ps = NULL;
-    return GL2PS_ERROR;
-  }
-
-  if(!title){
-    gl2ps->title = (char*)gl2psMalloc(sizeof(char));
-    gl2ps->title[0] = '\0';
-  }
-  else{
-    gl2ps->title = (char*)gl2psMalloc((strlen(title)+1)*sizeof(char));
-    strcpy(gl2ps->title, title);
-  }
-
-  if(!producer){
-    gl2ps->producer = (char*)gl2psMalloc(sizeof(char));
-    gl2ps->producer[0] = '\0';
-  }
-  else{
-    gl2ps->producer = (char*)gl2psMalloc((strlen(producer)+1)*sizeof(char));
-    strcpy(gl2ps->producer, producer);
-  }
-
-  if(!filename){
-    gl2ps->filename = (char*)gl2psMalloc(sizeof(char));
-    gl2ps->filename[0] = '\0';
-  }
-  else{
-    gl2ps->filename = (char*)gl2psMalloc((strlen(filename)+1)*sizeof(char));
-    strcpy(gl2ps->filename, filename);
-  }
-
-  gl2ps->primitives = gl2psListCreate(500, 500, sizeof(GL2PSprimitive*));
-  gl2ps->auxprimitives = gl2psListCreate(100, 100, sizeof(GL2PSprimitive*));
-  gl2ps->feedback = (GLfloat*)gl2psMalloc(gl2ps->buffersize * sizeof(GLfloat));
-  glFeedbackBuffer(gl2ps->buffersize, GL_3D_COLOR, gl2ps->feedback);
-  glRenderMode(GL_FEEDBACK);
-
-  return GL2PS_SUCCESS;
-}
-
-GL2PSDLL_API GLint gl2psEndPage(void)
-{
-  GLint res;
-
-  if(!gl2ps) return GL2PS_UNINITIALIZED;
-
-  res = gl2psPrintPrimitives();
-
-  if(res != GL2PS_OVERFLOW)
-    (gl2psbackends[gl2ps->format]->printFooter)();
-
-  fflush(gl2ps->stream);
-
-  gl2psListDelete(gl2ps->primitives);
-  gl2psListDelete(gl2ps->auxprimitives);
-  gl2psFreeImagemap(gl2ps->imagemap_head);
-  gl2psFree(gl2ps->colormap);
-  gl2psFree(gl2ps->title);
-  gl2psFree(gl2ps->producer);
-  gl2psFree(gl2ps->filename);
-  gl2psFree(gl2ps->feedback);
-  gl2psFree(gl2ps);
-  gl2ps = NULL;
-
-  return res;
-}
-
-GL2PSDLL_API GLint gl2psBeginViewport(GLint viewport[4])
-{
-  if(!gl2ps) return GL2PS_UNINITIALIZED;
-
-  (gl2psbackends[gl2ps->format]->beginViewport)(viewport);
-
-  return GL2PS_SUCCESS;
-}
-
-GL2PSDLL_API GLint gl2psEndViewport(void)
-{
-  GLint res;
-
-  if(!gl2ps) return GL2PS_UNINITIALIZED;
-
-  res = (gl2psbackends[gl2ps->format]->endViewport)();
-
-  /* reset last used colors, line widths */
-  gl2ps->lastlinewidth = -1.0F;
-
-  return res;
-}
-
-GL2PSDLL_API GLint gl2psTextOpt(const char *str, const char *fontname,
-                                GLshort fontsize, GLint alignment, GLfloat angle)
-{
-  return gl2psAddText(GL2PS_TEXT, str, fontname, fontsize, alignment, angle);
-}
-
-GL2PSDLL_API GLint gl2psText(const char *str, const char *fontname, GLshort fontsize)
-{
-  return gl2psAddText(GL2PS_TEXT, str, fontname, fontsize, GL2PS_TEXT_BL, 0.0F);
-}
-
-GL2PSDLL_API GLint gl2psSpecial(GLint format, const char *str)
-{
-  return gl2psAddText(GL2PS_SPECIAL, str, "", 0, format, 0.0F);
-}
-
-GL2PSDLL_API GLint gl2psDrawPixels(GLsizei width, GLsizei height,
-                                   GLint xorig, GLint yorig,
-                                   GLenum format, GLenum type,
-                                   const void *pixels)
-{
-  int size, i;
-  const GLfloat *piv;
-  GLfloat pos[4], zoom_x, zoom_y;
-  GL2PSprimitive *prim;
-  GLboolean valid;
-
-  if(!gl2ps || !pixels) return GL2PS_UNINITIALIZED;
-
-  if((width <= 0) || (height <= 0)) return GL2PS_ERROR;
-
-  if(gl2ps->options & GL2PS_NO_PIXMAP) return GL2PS_SUCCESS;
-
-  if((format != GL_RGB && format != GL_RGBA) || type != GL_FLOAT){
-    gl2psMsg(GL2PS_ERROR, "gl2psDrawPixels only implemented for "
-             "GL_RGB/GL_RGBA, GL_FLOAT pixels");
-    return GL2PS_ERROR;
-  }
-
-  glGetBooleanv(GL_CURRENT_RASTER_POSITION_VALID, &valid);
-  if(GL_FALSE == valid) return GL2PS_SUCCESS; /* the primitive is culled */
-
-  glGetFloatv(GL_CURRENT_RASTER_POSITION, pos);
-  glGetFloatv(GL_ZOOM_X, &zoom_x);
-  glGetFloatv(GL_ZOOM_Y, &zoom_y);
-
-  prim = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
-  prim->type = GL2PS_PIXMAP;
-  prim->boundary = 0;
-  prim->numverts = 1;
-  prim->verts = (GL2PSvertex*)gl2psMalloc(sizeof(GL2PSvertex));
-  prim->verts[0].xyz[0] = pos[0] + xorig;
-  prim->verts[0].xyz[1] = pos[1] + yorig;
-  prim->verts[0].xyz[2] = pos[2];
-  prim->culled = 0;
-  prim->offset = 0;
-  prim->pattern = 0;
-  prim->factor = 0;
-  prim->width = 1;
-  glGetFloatv(GL_CURRENT_RASTER_COLOR, prim->verts[0].rgba);
-  prim->data.image = (GL2PSimage*)gl2psMalloc(sizeof(GL2PSimage));
-  prim->data.image->width = width;
-  prim->data.image->height = height;
-  prim->data.image->zoom_x = zoom_x;
-  prim->data.image->zoom_y = zoom_y;
-  prim->data.image->format = format;
-  prim->data.image->type = type;
-
-  switch(format){
-  case GL_RGBA:
-    if(gl2ps->options & GL2PS_NO_BLENDING || !gl2ps->blending){
-      /* special case: blending turned off */
-      prim->data.image->format = GL_RGB;
-      size = height * width * 3;
-      prim->data.image->pixels = (GLfloat*)gl2psMalloc(size * sizeof(GLfloat));
-      piv = (const GLfloat*)pixels;
-      for(i = 0; i < size; ++i, ++piv){
-        prim->data.image->pixels[i] = *piv;
-        if(!((i + 1) % 3))
-          ++piv;
-      }
-    }
-    else{
-      size = height * width * 4;
-      prim->data.image->pixels = (GLfloat*)gl2psMalloc(size * sizeof(GLfloat));
-      memcpy(prim->data.image->pixels, pixels, size * sizeof(GLfloat));
-    }
-    break;
-  case GL_RGB:
-  default:
-    size = height * width * 3;
-    prim->data.image->pixels = (GLfloat*)gl2psMalloc(size * sizeof(GLfloat));
-    memcpy(prim->data.image->pixels, pixels, size * sizeof(GLfloat));
-    break;
-  }
-
-  gl2psListAdd(gl2ps->auxprimitives, &prim);
-  glPassThrough(GL2PS_DRAW_PIXELS_TOKEN);
-
-  return GL2PS_SUCCESS;
-}
-
-GL2PSDLL_API GLint gl2psDrawImageMap(GLsizei width, GLsizei height,
-                                     const GLfloat position[3],
-                                     const unsigned char *imagemap){
-  int size, i;
-  int sizeoffloat = sizeof(GLfloat);
-
-  if(!gl2ps || !imagemap) return GL2PS_UNINITIALIZED;
-
-  if((width <= 0) || (height <= 0)) return GL2PS_ERROR;
-
-  size = height + height * ((width - 1) / 8);
-  glPassThrough(GL2PS_IMAGEMAP_TOKEN);
-  glBegin(GL_POINTS);
-  glVertex3f(position[0], position[1],position[2]);
-  glEnd();
-  glPassThrough((GLfloat)width);
-  glPassThrough((GLfloat)height);
-  for(i = 0; i < size; i += sizeoffloat){
-    const float *value = (const float*)imagemap;
-    glPassThrough(*value);
-    imagemap += sizeoffloat;
-  }
-  return GL2PS_SUCCESS;
-}
-
-GL2PSDLL_API GLint gl2psEnable(GLint mode)
-{
-  GLint tmp;
-
-  if(!gl2ps) return GL2PS_UNINITIALIZED;
-
-  switch(mode){
-  case GL2PS_POLYGON_OFFSET_FILL :
-    glPassThrough(GL2PS_BEGIN_OFFSET_TOKEN);
-    glGetFloatv(GL_POLYGON_OFFSET_FACTOR, &gl2ps->offset[0]);
-    glGetFloatv(GL_POLYGON_OFFSET_UNITS, &gl2ps->offset[1]);
-    break;
-  case GL2PS_POLYGON_BOUNDARY :
-    glPassThrough(GL2PS_BEGIN_BOUNDARY_TOKEN);
-    break;
-  case GL2PS_LINE_STIPPLE :
-    glPassThrough(GL2PS_BEGIN_STIPPLE_TOKEN);
-    glGetIntegerv(GL_LINE_STIPPLE_PATTERN, &tmp);
-    glPassThrough((GLfloat)tmp);
-    glGetIntegerv(GL_LINE_STIPPLE_REPEAT, &tmp);
-    glPassThrough((GLfloat)tmp);
-    break;
-  case GL2PS_BLEND :
-    glPassThrough(GL2PS_BEGIN_BLEND_TOKEN);
-    break;
-  default :
-    gl2psMsg(GL2PS_WARNING, "Unknown mode in gl2psEnable: %d", mode);
-    return GL2PS_WARNING;
-  }
-
-  return GL2PS_SUCCESS;
-}
-
-GL2PSDLL_API GLint gl2psDisable(GLint mode)
-{
-  if(!gl2ps) return GL2PS_UNINITIALIZED;
-
-  switch(mode){
-  case GL2PS_POLYGON_OFFSET_FILL :
-    glPassThrough(GL2PS_END_OFFSET_TOKEN);
-    break;
-  case GL2PS_POLYGON_BOUNDARY :
-    glPassThrough(GL2PS_END_BOUNDARY_TOKEN);
-    break;
-  case GL2PS_LINE_STIPPLE :
-    glPassThrough(GL2PS_END_STIPPLE_TOKEN);
-    break;
-  case GL2PS_BLEND :
-    glPassThrough(GL2PS_END_BLEND_TOKEN);
-    break;
-  default :
-    gl2psMsg(GL2PS_WARNING, "Unknown mode in gl2psDisable: %d", mode);
-    return GL2PS_WARNING;
-  }
-
-  return GL2PS_SUCCESS;
-}
-
-GL2PSDLL_API GLint gl2psPointSize(GLfloat value)
-{
-  if(!gl2ps) return GL2PS_UNINITIALIZED;
-
-  glPassThrough(GL2PS_POINT_SIZE_TOKEN);
-  glPassThrough(value);
-
-  return GL2PS_SUCCESS;
-}
-
-GL2PSDLL_API GLint gl2psLineWidth(GLfloat value)
-{
-  if(!gl2ps) return GL2PS_UNINITIALIZED;
-
-  glPassThrough(GL2PS_LINE_WIDTH_TOKEN);
-  glPassThrough(value);
-
-  return GL2PS_SUCCESS;
-}
-
-GL2PSDLL_API GLint gl2psBlendFunc(GLenum sfactor, GLenum dfactor)
-{
-  if(!gl2ps) return GL2PS_UNINITIALIZED;
-
-  if(GL_FALSE == gl2psSupportedBlendMode(sfactor, dfactor))
-    return GL2PS_WARNING;
-
-  glPassThrough(GL2PS_SRC_BLEND_TOKEN);
-  glPassThrough((GLfloat)sfactor);
-  glPassThrough(GL2PS_DST_BLEND_TOKEN);
-  glPassThrough((GLfloat)dfactor);
-
-  return GL2PS_SUCCESS;
-}
-
-GL2PSDLL_API GLint gl2psSetOptions(GLint options)
-{
-  if(!gl2ps) return GL2PS_UNINITIALIZED;
-
-  gl2ps->options = options;
-
-  return GL2PS_SUCCESS;
-}
-
-GL2PSDLL_API GLint gl2psGetOptions(GLint *options)
-{
-  if(!gl2ps) {
-    *options = 0;
-    return GL2PS_UNINITIALIZED;
-  }
-
-  *options = gl2ps->options;
-
-  return GL2PS_SUCCESS;
-}
-
-GL2PSDLL_API const char *gl2psGetFileExtension(GLint format)
-{
-  if(format >= 0 && format < (GLint)(sizeof(gl2psbackends) / sizeof(gl2psbackends[0])))
-    return gl2psbackends[format]->file_extension;
-  else
-    return "Unknown format";
-}
-
-GL2PSDLL_API const char *gl2psGetFormatDescription(GLint format)
-{
-  if(format >= 0 && format < (GLint)(sizeof(gl2psbackends) / sizeof(gl2psbackends[0])))
-    return gl2psbackends[format]->description;
-  else
-    return "Unknown format";
-}
--- a/src/gl2ps.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,200 +0,0 @@
-/*
- * GL2PS, an OpenGL to PostScript Printing Library
- * Copyright (C) 1999-2011 C. Geuzaine
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of either:
- *
- * a) the GNU Library General Public License as published by the Free
- * Software Foundation, either version 2 of the License, or (at your
- * option) any later version; or
- *
- * b) the GL2PS License as published by Christophe Geuzaine, either
- * version 2 of the License, or (at your option) any later version.
- *
- * This program 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 either
- * the GNU Library General Public License or the GL2PS License for
- * more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library in the file named "COPYING.LGPL";
- * if not, write to the Free Software Foundation, Inc., 675 Mass Ave,
- * Cambridge, MA 02139, USA.
- *
- * You should have received a copy of the GL2PS License with this
- * library in the file named "COPYING.GL2PS"; if not, I will be glad
- * to provide one.
- *
- * For the latest info about gl2ps and a full list of contributors,
- * see http://www.geuz.org/gl2ps/.
- *
- * Please report all bugs and problems to <gl2ps@geuz.org>.
- */
-
-#ifndef __GL2PS_H__
-#define __GL2PS_H__
-
-#include <stdio.h>
-#include <stdlib.h>
-
-/* Define GL2PSDLL at compile time to build a Windows DLL */
-
-#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
-#  if defined(_MSC_VER)
-#    pragma warning(disable:4115)
-#    pragma warning(disable:4996)
-#  endif
-#  define WIN32_LEAN_AND_MEAN
-#  include <windows.h>
-#  if defined(GL2PSDLL)
-#    if defined(GL2PSDLL_EXPORTS)
-#      define GL2PSDLL_API __declspec(dllexport)
-#    else
-#      define GL2PSDLL_API __declspec(dllimport)
-#    endif
-#  else
-#    define GL2PSDLL_API
-#  endif
-#else
-#  define GL2PSDLL_API
-#endif
-
-#if defined(__APPLE__) || defined(HAVE_OPENGL_GL_H)
-#  include <OpenGL/gl.h>
-#else
-#  include <GL/gl.h>
-#endif
-
-/* Support for compressed PostScript/PDF/SVG and for embedded PNG
-   images in SVG */
-
-#if defined(HAVE_ZLIB) || defined(HAVE_LIBZ)
-#  define GL2PS_HAVE_ZLIB
-#  if defined(HAVE_LIBPNG) || defined(HAVE_PNG)
-#    define GL2PS_HAVE_LIBPNG
-#  endif
-#endif
-
-/* Version number */
-
-#define GL2PS_MAJOR_VERSION 1
-#define GL2PS_MINOR_VERSION 3
-#define GL2PS_PATCH_VERSION 6
-#define GL2PS_EXTRA_VERSION ""
-
-#define GL2PS_VERSION (GL2PS_MAJOR_VERSION + \
-                       0.01 * GL2PS_MINOR_VERSION + \
-                       0.0001 * GL2PS_PATCH_VERSION)
-
-#define GL2PS_COPYRIGHT "(C) 1999-2011 C. Geuzaine"
-
-/* Output file formats (the values and the ordering are important!) */
-
-#define GL2PS_PS  0
-#define GL2PS_EPS 1
-#define GL2PS_TEX 2
-#define GL2PS_PDF 3
-#define GL2PS_SVG 4
-#define GL2PS_PGF 5
-
-/* Sorting algorithms */
-
-#define GL2PS_NO_SORT     1
-#define GL2PS_SIMPLE_SORT 2
-#define GL2PS_BSP_SORT    3
-
-/* Message levels and error codes */
-
-#define GL2PS_SUCCESS       0
-#define GL2PS_INFO          1
-#define GL2PS_WARNING       2
-#define GL2PS_ERROR         3
-#define GL2PS_NO_FEEDBACK   4
-#define GL2PS_OVERFLOW      5
-#define GL2PS_UNINITIALIZED 6
-
-/* Options for gl2psBeginPage */
-
-#define GL2PS_NONE                 0
-#define GL2PS_DRAW_BACKGROUND      (1<<0)
-#define GL2PS_SIMPLE_LINE_OFFSET   (1<<1)
-#define GL2PS_SILENT               (1<<2)
-#define GL2PS_BEST_ROOT            (1<<3)
-#define GL2PS_OCCLUSION_CULL       (1<<4)
-#define GL2PS_NO_TEXT              (1<<5)
-#define GL2PS_LANDSCAPE            (1<<6)
-#define GL2PS_NO_PS3_SHADING       (1<<7)
-#define GL2PS_NO_PIXMAP            (1<<8)
-#define GL2PS_USE_CURRENT_VIEWPORT (1<<9)
-#define GL2PS_COMPRESS             (1<<10)
-#define GL2PS_NO_BLENDING          (1<<11)
-#define GL2PS_TIGHT_BOUNDING_BOX   (1<<12)
-
-/* Arguments for gl2psEnable/gl2psDisable */
-
-#define GL2PS_POLYGON_OFFSET_FILL 1
-#define GL2PS_POLYGON_BOUNDARY    2
-#define GL2PS_LINE_STIPPLE        3
-#define GL2PS_BLEND               4
-
-/* Text alignment (o=raster position; default mode is BL):
-   +---+ +---+ +---+ +---+ +---+ +---+ +-o-+ o---+ +---o
-   | o | o   | |   o |   | |   | |   | |   | |   | |   |
-   +---+ +---+ +---+ +-o-+ o---+ +---o +---+ +---+ +---+
-    C     CL    CR    B     BL    BR    T     TL    TR */
-
-#define GL2PS_TEXT_C  1
-#define GL2PS_TEXT_CL 2
-#define GL2PS_TEXT_CR 3
-#define GL2PS_TEXT_B  4
-#define GL2PS_TEXT_BL 5
-#define GL2PS_TEXT_BR 6
-#define GL2PS_TEXT_T  7
-#define GL2PS_TEXT_TL 8
-#define GL2PS_TEXT_TR 9
-
-typedef GLfloat GL2PSrgba[4];
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-GL2PSDLL_API GLint gl2psBeginPage(const char *title, const char *producer,
-                                  GLint viewport[4], GLint format, GLint sort,
-                                  GLint options, GLint colormode,
-                                  GLint colorsize, GL2PSrgba *colormap,
-                                  GLint nr, GLint ng, GLint nb, GLint buffersize,
-                                  FILE *stream, const char *filename);
-GL2PSDLL_API GLint gl2psEndPage(void);
-GL2PSDLL_API GLint gl2psSetOptions(GLint options);
-GL2PSDLL_API GLint gl2psGetOptions(GLint *options);
-GL2PSDLL_API GLint gl2psBeginViewport(GLint viewport[4]);
-GL2PSDLL_API GLint gl2psEndViewport(void);
-GL2PSDLL_API GLint gl2psText(const char *str, const char *fontname,
-                             GLshort fontsize);
-GL2PSDLL_API GLint gl2psTextOpt(const char *str, const char *fontname,
-                                GLshort fontsize, GLint align, GLfloat angle);
-GL2PSDLL_API GLint gl2psSpecial(GLint format, const char *str);
-GL2PSDLL_API GLint gl2psDrawPixels(GLsizei width, GLsizei height,
-                                   GLint xorig, GLint yorig,
-                                   GLenum format, GLenum type, const void *pixels);
-GL2PSDLL_API GLint gl2psEnable(GLint mode);
-GL2PSDLL_API GLint gl2psDisable(GLint mode);
-GL2PSDLL_API GLint gl2psPointSize(GLfloat value);
-GL2PSDLL_API GLint gl2psLineWidth(GLfloat value);
-GL2PSDLL_API GLint gl2psBlendFunc(GLenum sfactor, GLenum dfactor);
-
-/* undocumented */
-GL2PSDLL_API GLint gl2psDrawImageMap(GLsizei width, GLsizei height,
-                                     const GLfloat position[3],
-                                     const unsigned char *imagemap);
-GL2PSDLL_API const char *gl2psGetFileExtension(GLint format);
-GL2PSDLL_API const char *gl2psGetFormatDescription(GLint format);
-
-#if defined(__cplusplus)
-}
-#endif
-
-#endif /* __GL2PS_H__ */
--- a/src/gripes.cc	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,238 +0,0 @@
-/*
-
-Copyright (C) 1993-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "defun.h"
-#include "error.h"
-#include "gripes.h"
-#include "oct-obj.h"
-#include "utils.h"
-
-void
-gripe_not_supported (const char *fcn)
-{
-  error ("%s: not supported on this system", fcn);
-}
-
-void
-gripe_not_implemented (const char *fcn)
-{
-  error ("%s: not implemented", fcn);
-}
-
-void
-gripe_string_invalid (void)
-{
-  error ("std::string constant used in invalid context");
-}
-
-void
-gripe_range_invalid (void)
-{
-  error ("range constant used in invalid context");
-}
-
-void
-gripe_nonconformant (void)
-{
-  error ("nonconformant matrices");
-}
-
-void
-gripe_nonconformant (octave_idx_type r1, octave_idx_type c1, octave_idx_type r2, octave_idx_type c2)
-{
-  error ("nonconformant matrices (op1 is %dx%d, op2 is %dx%d)",
-         r1, c1, r2, c2);
-}
-
-void
-gripe_empty_arg (const char *name, bool is_error)
-{
-  if (is_error)
-    error ("%s: empty matrix is invalid as an argument", name);
-  else
-    warning ("%s: argument is empty matrix", name);
-}
-
-void
-gripe_square_matrix_required (const char *name)
-{
-  error ("%s: argument must be a square matrix", name);
-}
-
-void
-gripe_user_supplied_eval (const char *name)
-{
-  error ("%s: evaluation of user-supplied function failed", name);
-}
-
-void
-gripe_user_returned_invalid (const char *name)
-{
-  error ("%s: user-supplied function returned invalid value", name);
-}
-
-void
-gripe_invalid_conversion (const std::string& from, const std::string& to)
-{
-  error ("invalid conversion from %s to %s", from.c_str (), to.c_str ());
-}
-
-void
-gripe_invalid_value_specified (const char *name)
-{
-  warning ("invalid value specified for `%s'", name);
-}
-
-void
-gripe_2_or_3_dim_plot (void)
-{
-  error ("plot: can only plot in 2 or 3 dimensions");
-}
-
-void
-gripe_unrecognized_float_fmt (void)
-{
-  error ("unrecognized floating point format requested");
-}
-
-void
-gripe_unrecognized_data_fmt (const char *warn_for)
-{
-  error ("%s: unrecognized data format requested", warn_for);
-}
-
-void
-gripe_data_conversion (const char *from, const char *to)
-{
-  error ("unable to convert from %s to %s format", from, to);
-}
-
-void
-gripe_wrong_type_arg (const char *name, const char *s, bool is_error)
-{
-  if (is_error)
-    error ("%s: wrong type argument `%s'", name, s);
-  else
-    warning ("%s: wrong type argument `%s'", name, s);
-}
-
-void
-gripe_wrong_type_arg (const char *name, const std::string& s, bool is_error)
-{
-  gripe_wrong_type_arg (name, s.c_str (), is_error);
-}
-
-void
-gripe_wrong_type_arg (const char *name, const octave_value& tc,
-                      bool is_error)
-{
-  std::string type = tc.type_name ();
-
-  gripe_wrong_type_arg (name, type, is_error);
-}
-
-void
-gripe_wrong_type_arg (const std::string& name, const octave_value& tc,
-                      bool is_error)
-{
-  gripe_wrong_type_arg (name.c_str (), tc, is_error);
-}
-
-void
-gripe_wrong_type_arg_for_unary_op (const octave_value& op)
-{
-  std::string type = op.type_name ();
-  error ("invalid operand `%s' for unary operator", type.c_str ());
-}
-
-void
-gripe_wrong_type_arg_for_binary_op (const octave_value& op)
-{
-  std::string type = op.type_name ();
-  error ("invalid operand `%s' for binary operator", type.c_str ());
-}
-
-void
-gripe_implicit_conversion (const char *id, const char *from, const char *to)
-{
-  warning_with_id (id, "implicit conversion from %s to %s", from, to);
-}
-
-void
-gripe_implicit_conversion (const std::string& id,
-                           const std::string& from, const std::string& to)
-{
-  warning_with_id (id.c_str (),
-                   "implicit conversion from %s to %s",
-                   from.c_str (), to.c_str ());
-}
-
-void
-gripe_divide_by_zero (void)
-{
-  warning_with_id ("Octave:divide-by-zero", "division by zero");
-}
-
-void
-gripe_logical_conversion (void)
-{
-  warning_with_id ("Octave:logical-conversion",
-                   "value not equal to 1 or 0 converted to logical 1");
-}
-
-void
-gripe_library_execution_error (void)
-{
-  octave_exception_state = octave_no_exception;
-
-  if (! error_state)
-    error ("caught execution error in library function");
-}
-
-void
-gripe_invalid_inquiry_subscript (void)
-{
-  error ("invalid dimension inquiry of a non-existent value");
-}
-
-void
-gripe_indexed_cs_list (void)
-{
-  error ("a cs-list cannot be further indexed");
-}
-
-void
-gripe_nonbraced_cs_list_assignment (void)
-{
-  error ("invalid assignment to cs-list outside multiple assignment");
-}
-
-void
-gripe_warn_complex_cmp (void)
-{
-  warning_with_id ("Octave:matlab-incompatible",
-                   "potential Matlab compatibility problem: comparing complex numbers");
-}
--- a/src/gripes.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,130 +0,0 @@
-/*
-
-Copyright (C) 1993-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#if !defined (octave_gripes_h)
-#define octave_gripes_h 1
-
-#include <string>
-
-#include "lo-array-gripes.h"
-
-class octave_value;
-
-extern OCTINTERP_API void
-gripe_not_supported (const char *);
-
-extern OCTINTERP_API void
-gripe_not_implemented (const char *);
-
-extern OCTINTERP_API void
-gripe_string_invalid (void);
-
-extern OCTINTERP_API void
-gripe_range_invalid (void);
-
-extern OCTINTERP_API void
-gripe_nonconformant (void);
-
-extern OCTINTERP_API void
-gripe_nonconformant (octave_idx_type r1, octave_idx_type c1, octave_idx_type r2, octave_idx_type c2);
-
-extern OCTINTERP_API void
-gripe_empty_arg (const char *name, bool is_error);
-
-extern OCTINTERP_API void
-gripe_square_matrix_required (const char *name);
-
-extern OCTINTERP_API void
-gripe_user_supplied_eval (const char *name);
-
-extern OCTINTERP_API void
-gripe_user_returned_invalid (const char *name);
-
-extern OCTINTERP_API void
-gripe_invalid_conversion (const std::string& from, const std::string& to);
-
-extern OCTINTERP_API void
-gripe_invalid_value_specified (const char *name);
-
-extern OCTINTERP_API void
-gripe_2_or_3_dim_plot (void);
-
-extern OCTINTERP_API void
-gripe_unrecognized_float_fmt (void);
-
-extern OCTINTERP_API void
-gripe_unrecognized_data_fmt (const char *warn_for);
-
-extern OCTINTERP_API void
-gripe_data_conversion (const char *from, const char *to);
-
-extern OCTINTERP_API void
-gripe_wrong_type_arg (const char *name, const char *s,
-                      bool is_error = true);
-
-extern OCTINTERP_API void
-gripe_wrong_type_arg (const char *name, const std::string& s,
-                      bool is_error = true);
-
-extern OCTINTERP_API void
-gripe_wrong_type_arg (const char *name, const octave_value& tc,
-                      bool is_error = true);
-
-extern OCTINTERP_API void
-gripe_wrong_type_arg (const std::string& name, const octave_value& tc,
-                      bool is_error = true);
-
-extern OCTINTERP_API void
-gripe_wrong_type_arg_for_unary_op (const octave_value& op);
-
-extern OCTINTERP_API void
-gripe_wrong_type_arg_for_binary_op (const octave_value& op);
-
-extern OCTINTERP_API void
-gripe_implicit_conversion (const char *id, const char *from, const char *to);
-
-extern OCTINTERP_API void
-gripe_implicit_conversion (const std::string& id, const std::string& from,
-                           const std::string& to);
-
-extern OCTINTERP_API void
-gripe_divide_by_zero (void);
-
-extern OCTINTERP_API void
-gripe_logical_conversion (void);
-
-extern OCTINTERP_API void
-gripe_library_execution_error (void);
-
-extern OCTINTERP_API void
-gripe_invalid_inquiry_subscript (void);
-
-extern OCTINTERP_API void
-gripe_indexed_cs_list (void);
-
-extern OCTINTERP_API void
-gripe_nonbraced_cs_list_assignment (void);
-
-extern OCTINTERP_API void
-gripe_warn_complex_cmp (void);
-
-#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/Cell.cc	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,320 @@
+/*
+
+Copyright (C) 1999-2012 John W. Eaton
+Copyright (C) 2009-2010 VZLU Prague
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "idx-vector.h"
+
+#include "Cell.h"
+#include "error.h"
+#include "gripes.h"
+#include "oct-obj.h"
+
+Cell::Cell (const octave_value_list& ovl)
+  : Array<octave_value> (ovl.cell_value ())
+{
+}
+
+Cell::Cell (const string_vector& sv, bool trim)
+  : Array<octave_value> ()
+{
+  octave_idx_type n = sv.length ();
+
+  if (n > 0)
+    {
+      resize (dim_vector (n, 1));
+
+      for (octave_idx_type i = 0; i < n; i++)
+        {
+          std::string s = sv[i];
+
+          if (trim)
+            {
+              size_t pos = s.find_last_not_of (' ');
+
+              s = (pos == std::string::npos) ? "" : s.substr (0, pos+1);
+            }
+
+          elem(i,0) = s;
+        }
+    }
+}
+
+Cell::Cell (const std::list<std::string>& lst)
+  : Array<octave_value> ()
+{
+  size_t n = lst.size ();
+
+  if (n > 0)
+    {
+      resize (dim_vector (n, 1));
+
+      octave_idx_type i = 0;
+
+      for (std::list<std::string>::const_iterator it = lst.begin ();
+           it != lst.end (); it++)
+        {
+          elem(i++,0) = *it;
+        }
+    }
+}
+
+Cell::Cell (const Array<std::string>& sa)
+  : Array<octave_value> (sa.dims ())
+{
+  octave_idx_type n = sa.numel ();
+
+  octave_value *dst = fortran_vec ();
+  const std::string *src = sa.data ();
+
+  for (octave_idx_type i = 0; i < n; i++)
+    dst[i] = src[i];
+}
+
+// Set size to DV, filling with [].  Then fill with as many elements of
+// SV as possible.
+
+Cell::Cell (const dim_vector& dv, const string_vector& sv, bool trim)
+  : Array<octave_value> (dv, Matrix ())
+{
+  octave_idx_type n = sv.length ();
+
+  if (n > 0)
+    {
+      octave_idx_type m = numel ();
+
+      octave_idx_type len = n > m ? m : n;
+
+      for (octave_idx_type i = 0; i < len; i++)
+        {
+          std::string s = sv[i];
+
+          if (trim)
+            {
+              size_t pos = s.find_last_not_of (' ');
+
+              s = (pos == std::string::npos) ? "" : s.substr (0, pos+1);
+            }
+
+          elem(i) = s;
+        }
+    }
+}
+
+bool
+Cell::is_cellstr (void) const
+{
+  bool retval = true;
+
+  octave_idx_type n = numel ();
+
+  for (octave_idx_type i = 0; i < n; i++)
+    {
+      if (! elem(i).is_string ())
+        {
+          retval = false;
+          break;
+        }
+    }
+
+  return retval;
+}
+
+Array<std::string>
+Cell::cellstr_value (void) const
+{
+  Array<std::string> retval (dims ());
+
+  octave_idx_type n = numel ();
+
+  for (octave_idx_type i = 0; i < n; i++)
+    retval.xelem (i) = elem (i).string_value ();
+
+  return retval;
+}
+
+Cell
+Cell::index (const octave_value_list& idx_arg, bool resize_ok) const
+{
+  Cell retval;
+
+  octave_idx_type n = idx_arg.length ();
+
+  switch (n)
+    {
+    case 0:
+      retval = *this;
+      break;
+
+    case 1:
+      {
+        idx_vector i = idx_arg(0).index_vector ();
+
+        if (! error_state)
+          retval = Array<octave_value>::index (i, resize_ok, Matrix ());
+      }
+      break;
+
+    case 2:
+      {
+        idx_vector i = idx_arg(0).index_vector ();
+
+        if (! error_state)
+          {
+            idx_vector j = idx_arg(1).index_vector ();
+
+            if (! error_state)
+              retval = Array<octave_value>::index (i, j, resize_ok, Matrix ());
+          }
+      }
+      break;
+
+    default:
+      {
+        Array<idx_vector> iv (dim_vector (n, 1));
+
+        for (octave_idx_type i = 0; i < n; i++)
+          {
+            iv(i) = idx_arg(i).index_vector ();
+
+            if (error_state)
+              break;
+          }
+
+        if (!error_state)
+          retval = Array<octave_value>::index (iv, resize_ok, Matrix ());
+      }
+      break;
+    }
+
+  return retval;
+}
+
+void
+Cell::assign (const octave_value_list& idx_arg, const Cell& rhs,
+              const octave_value& fill_val)
+
+{
+  octave_idx_type len = idx_arg.length ();
+
+  Array<idx_vector> ra_idx (dim_vector (len, 1));
+
+  for (octave_idx_type i = 0; i < len; i++)
+    ra_idx(i) = idx_arg(i).index_vector ();
+
+  Array<octave_value>::assign (ra_idx, rhs, fill_val);
+}
+
+void
+Cell::delete_elements (const octave_value_list& idx_arg)
+
+{
+  octave_idx_type len = idx_arg.length ();
+
+  Array<idx_vector> ra_idx (dim_vector (len, 1));
+
+  for (octave_idx_type i = 0; i < len; i++)
+    ra_idx.xelem (i) = idx_arg(i).index_vector ();
+
+  Array<octave_value>::delete_elements (ra_idx);
+}
+
+octave_idx_type
+Cell::nnz (void) const
+{
+  gripe_wrong_type_arg ("nnz", "cell array");
+  return -1;
+}
+
+Cell
+Cell::column (octave_idx_type i) const
+{
+  Cell retval;
+
+  if (ndims () < 3)
+    {
+      if (i < 0 || i >= cols ())
+        error ("invalid column selection");
+      else
+        {
+          octave_idx_type nr = rows ();
+
+          retval.resize (dim_vector (nr, 1));
+
+          for (octave_idx_type j = 0; j < nr; j++)
+            retval.xelem (j) = elem (j, i);
+        }
+    }
+  else
+    error ("Cell::column: requires 2-d cell array");
+
+  return retval;
+}
+
+Cell
+Cell::concat (const Cell& rb, const Array<octave_idx_type>& ra_idx)
+{
+  return insert (rb, ra_idx);
+}
+
+Cell&
+Cell::insert (const Cell& a, octave_idx_type r, octave_idx_type c)
+{
+  Array<octave_value>::insert (a, r, c);
+  return *this;
+}
+
+Cell&
+Cell::insert (const Cell& a, const Array<octave_idx_type>& ra_idx)
+{
+  Array<octave_value>::insert (a, ra_idx);
+  return *this;
+}
+
+Cell
+Cell::map (ctype_mapper fcn) const
+{
+  Cell retval (dims ());
+  octave_value *r = retval.fortran_vec ();
+
+  const octave_value *p = data ();
+
+  for (octave_idx_type i = 0; i < numel (); i++)
+    r[i] = ((p++)->*fcn) ();
+
+  return retval;
+}
+
+Cell
+Cell::diag (octave_idx_type k) const
+{
+  return Array<octave_value>::diag (k);
+}
+
+Cell
+Cell::diag (octave_idx_type m, octave_idx_type n) const
+{
+  return Array<octave_value>::diag (m, n);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/Cell.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,150 @@
+/*
+
+Copyright (C) 1999-2012 John W. Eaton
+Copyright (C) 2009-2010 VZLU Prague
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if !defined (Cell_h)
+#define Cell_h 1
+
+#include <string>
+
+#include "Array.h"
+#include "oct-alloc.h"
+#include "str-vec.h"
+#include "ov.h"
+
+class octave_value_list;
+
+class
+OCTINTERP_API
+Cell : public Array<octave_value>
+{
+public:
+
+  Cell (void)
+    : Array<octave_value> (dim_vector (0, 0)) { }
+
+  Cell (const octave_value& val)
+    : Array<octave_value> (dim_vector (1, 1), val) { }
+
+  Cell (const octave_value_list& ovl);
+
+  Cell (octave_idx_type n, octave_idx_type m,
+        const octave_value& val = Matrix ())
+    : Array<octave_value> (dim_vector (n, m), val) { }
+
+  Cell (const dim_vector& dv, const octave_value& val = Matrix ())
+    : Array<octave_value> (dv, val) { }
+
+  Cell (const Array<octave_value>& c)
+    : Array<octave_value> (c) { }
+
+  Cell (const Array<octave_value>& c, octave_idx_type nr, octave_idx_type nc)
+    : Array<octave_value> (c, dim_vector (nr, nc)) { }
+
+  Cell (const string_vector& sv, bool trim = false);
+
+  Cell (const std::list<std::string>& lst);
+
+  Cell (const Array<std::string>& sa);
+
+  Cell (const dim_vector& dv, const string_vector& sv, bool trim = false);
+
+  Cell (const Cell& c)
+    : Array<octave_value> (c) { }
+
+  bool is_cellstr (void) const;
+
+  Array<std::string> cellstr_value (void) const;
+
+  using Array<octave_value>::index;
+
+  Cell index (const octave_value_list& idx, bool resize_ok = false) const;
+
+  using Array<octave_value>::delete_elements;
+
+  void delete_elements (const octave_value_list& idx);
+
+  using Array<octave_value>::assign;
+
+  void assign (const octave_value_list& idx, const Cell& rhs,
+               const octave_value& fill_val = Matrix ());
+
+  Cell reshape (const dim_vector& new_dims) const
+    { return Array<octave_value>::reshape (new_dims); }
+
+  octave_idx_type nnz (void) const;
+
+  Cell column (octave_idx_type i) const;
+
+  // FIXME
+  boolMatrix all (int /* dim */ = 0) const { return boolMatrix (); }
+
+  // FIXME
+  boolMatrix any (int /* dim */ = 0) const { return boolMatrix (); }
+
+  Cell concat (const Cell& rb, const Array<octave_idx_type>& ra_idx);
+
+  Cell& insert (const Cell& a, octave_idx_type r, octave_idx_type c);
+  Cell& insert (const Cell& a, const Array<octave_idx_type>& ra_idx);
+
+  // FIXME
+  bool any_element_is_nan (void) const { return false; }
+  bool is_true (void) const { return false; }
+
+  octave_value resize_fill_value (void) const
+  {
+    static Matrix rfv;
+    return rfv;
+  }
+
+  Cell diag (octave_idx_type k = 0) const;
+
+  Cell diag (octave_idx_type m, octave_idx_type n) const;
+
+  Cell xisalnum (void) const { return map (&octave_value::xisalnum); }
+  Cell xisalpha (void) const { return map (&octave_value::xisalpha); }
+  Cell xisascii (void) const { return map (&octave_value::xisascii); }
+  Cell xiscntrl (void) const { return map (&octave_value::xiscntrl); }
+  Cell xisdigit (void) const { return map (&octave_value::xisdigit); }
+  Cell xisgraph (void) const { return map (&octave_value::xisgraph); }
+  Cell xislower (void) const { return map (&octave_value::xislower); }
+  Cell xisprint (void) const { return map (&octave_value::xisprint); }
+  Cell xispunct (void) const { return map (&octave_value::xispunct); }
+  Cell xisspace (void) const { return map (&octave_value::xisspace); }
+  Cell xisupper (void) const { return map (&octave_value::xisupper); }
+  Cell xisxdigit (void) const { return map (&octave_value::xisxdigit); }
+  Cell xtoascii (void) const { return map (&octave_value::xtoascii); }
+  Cell xtolower (void) const { return map (&octave_value::xtolower); }
+  Cell xtoupper (void) const { return map (&octave_value::xtoupper); }
+
+private:
+
+  typedef octave_value (octave_value::*ctype_mapper) (void) const;
+
+  Cell map (ctype_mapper) const;
+};
+
+template<>
+inline Cell octave_value_extract<Cell> (const octave_value& v)
+  { return v.cell_value (); }
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/c-file-ptr-stream.cc	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,362 @@
+/*
+
+Copyright (C) 2000-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <iostream>
+
+#include "c-file-ptr-stream.h"
+
+#ifndef SEEK_SET
+#define SEEK_SET 0
+#endif
+
+#ifndef SEEK_CUR
+#define SEEK_CUR 1
+#endif
+
+#ifndef SEEK_END
+#define SEEK_END 2
+#endif
+
+c_file_ptr_buf::~c_file_ptr_buf (void)
+{
+  buf_close ();
+}
+
+// FIXME -- I'm sure there is room for improvement here...
+
+c_file_ptr_buf::int_type
+c_file_ptr_buf::overflow (int_type c)
+{
+#if defined (CXX_ISO_COMPLIANT_LIBRARY)
+  if (f)
+    return (c != traits_type::eof ()) ? gnulib::fputc (c, f) : flush ();
+  else
+    return traits_type::not_eof (c);
+#else
+  if (f)
+    return (c != EOF) ? gnulib::fputc (c, f) : flush ();
+  else
+    return EOF;
+#endif
+}
+
+c_file_ptr_buf::int_type
+c_file_ptr_buf::underflow_common (bool bump)
+{
+  if (f)
+    {
+      int_type c = gnulib::fgetc (f);
+
+      if (! bump
+#if defined (CXX_ISO_COMPLIANT_LIBRARY)
+          && c != traits_type::eof ())
+#else
+          && c != EOF)
+#endif
+        ungetc (c, f);
+
+      return c;
+    }
+  else
+#if defined (CXX_ISO_COMPLIANT_LIBRARY)
+    return traits_type::eof ();
+#else
+    return EOF;
+#endif
+}
+
+c_file_ptr_buf::int_type
+c_file_ptr_buf::pbackfail (int_type c)
+{
+#if defined (CXX_ISO_COMPLIANT_LIBRARY)
+  return (c != traits_type::eof () && f) ? ungetc (c, f) :
+    traits_type::not_eof (c);
+#else
+  return (c != EOF && f) ? ungetc (c, f) : EOF;
+#endif
+}
+
+std::streamsize
+c_file_ptr_buf::xsputn (const char* s, std::streamsize n)
+{
+  if (f)
+    return gnulib::fwrite (s, 1, n, f);
+  else
+    return 0;
+}
+
+std::streamsize
+c_file_ptr_buf::xsgetn (char *s, std::streamsize n)
+{
+  if (f)
+    return gnulib::fread (s, 1, n, f);
+  else
+    return 0;
+}
+
+static inline int
+seekdir_to_whence (std::ios::seekdir dir)
+{
+  return ((dir == std::ios::beg) ? SEEK_SET :
+          (dir == std::ios::cur) ? SEEK_CUR :
+          (dir == std::ios::end) ? SEEK_END :
+          dir);
+}
+
+std::streampos
+c_file_ptr_buf::seekoff (std::streamoff /* offset */,
+                         std::ios::seekdir /* dir */,
+                         std::ios::openmode)
+{
+  // FIXME
+#if 0
+  if (f)
+    {
+      fseek (f, offset, seekdir_to_whence (dir));
+
+      return ftell (f);
+    }
+  else
+    return 0;
+#endif
+  return -1;
+}
+
+std::streampos
+c_file_ptr_buf::seekpos (std::streampos /* offset */, std::ios::openmode)
+{
+  // FIXME
+#if 0
+  if (f)
+    {
+      fseek (f, offset, SEEK_SET);
+
+      return ftell (f);
+    }
+  else
+    return 0;
+#endif
+  return -1;
+}
+
+int
+c_file_ptr_buf::sync (void)
+{
+  flush ();
+
+  return 0;
+}
+
+int
+c_file_ptr_buf::flush (void)
+{
+  return f ? gnulib::fflush (f) : EOF;
+}
+
+int
+c_file_ptr_buf::buf_close (void)
+{
+  int retval = -1;
+
+  flush ();
+
+  if (f)
+    {
+      retval = cf (f);
+      f = 0;
+    }
+
+  return retval;
+}
+
+int
+c_file_ptr_buf::seek (long offset, int origin)
+{
+  return f ? gnulib::fseek (f, offset, origin) : -1;
+}
+
+long
+c_file_ptr_buf::tell (void)
+{
+  return f ? gnulib::ftell (f) : -1;
+}
+
+int
+c_file_ptr_buf::file_close (FILE *f)
+{
+  return gnulib::fclose (f);
+}
+
+#ifdef HAVE_ZLIB
+
+c_zfile_ptr_buf::~c_zfile_ptr_buf (void)
+{
+  buf_close ();
+}
+
+// FIXME -- I'm sure there is room for improvement here...
+
+c_zfile_ptr_buf::int_type
+c_zfile_ptr_buf::overflow (int_type c)
+{
+#if defined (CXX_ISO_COMPLIANT_LIBRARY)
+  if (f)
+    return (c != traits_type::eof ()) ? gzputc (f, c) : flush ();
+  else
+    return traits_type::not_eof (c);
+#else
+  if (f)
+    return (c != EOF) ? gzputc (f, c) : flush ();
+  else
+    return EOF;
+#endif
+}
+
+c_zfile_ptr_buf::int_type
+c_zfile_ptr_buf::underflow_common (bool bump)
+{
+  if (f)
+    {
+      int_type c = gzgetc (f);
+
+      if (! bump
+#if defined (CXX_ISO_COMPLIANT_LIBRARY)
+          && c != traits_type::eof ())
+#else
+          && c != EOF)
+#endif
+        gzungetc (c, f);
+
+      return c;
+    }
+  else
+#if defined (CXX_ISO_COMPLIANT_LIBRARY)
+    return traits_type::eof ();
+#else
+    return EOF;
+#endif
+}
+
+c_zfile_ptr_buf::int_type
+c_zfile_ptr_buf::pbackfail (int_type c)
+{
+#if defined (CXX_ISO_COMPLIANT_LIBRARY)
+  return (c != traits_type::eof () && f) ? gzungetc (c, f) :
+    traits_type::not_eof (c);
+#else
+  return (c != EOF && f) ? gzungetc (c, f) : EOF;
+#endif
+}
+
+std::streamsize
+c_zfile_ptr_buf::xsputn (const char* s, std::streamsize n)
+{
+  if (f)
+    return gzwrite (f, s, n);
+  else
+    return 0;
+}
+
+std::streamsize
+c_zfile_ptr_buf::xsgetn (char *s, std::streamsize n)
+{
+  if (f)
+    return gzread (f, s, n);
+  else
+    return 0;
+}
+
+std::streampos
+c_zfile_ptr_buf::seekoff (std::streamoff /* offset */,
+                          std::ios::seekdir /* dir */,
+                          std::ios::openmode)
+{
+  // FIXME
+#if 0
+  if (f)
+    {
+      gzseek (f, offset, seekdir_to_whence (dir));
+
+      return gztell (f);
+    }
+  else
+    return 0;
+#endif
+  return -1;
+}
+
+std::streampos
+c_zfile_ptr_buf::seekpos (std::streampos /* offset */, std::ios::openmode)
+{
+  // FIXME
+#if 0
+  if (f)
+    {
+      gzseek (f, offset, SEEK_SET);
+
+      return gztell (f);
+    }
+  else
+    return 0;
+#endif
+  return -1;
+}
+
+int
+c_zfile_ptr_buf::sync (void)
+{
+  flush ();
+
+  return 0;
+}
+
+int
+c_zfile_ptr_buf::flush (void)
+{
+  // FIXME -- do we need something more complex here, passing
+  // something other than 0 for the second argument to gzflush and
+  // checking the return value, etc.?
+
+  return f ? gzflush (f, 0) : EOF;
+}
+
+int
+c_zfile_ptr_buf::buf_close (void)
+{
+  int retval = -1;
+
+  flush ();
+
+  if (f)
+    {
+      retval = cf (f);
+      f = 0;
+    }
+
+  return retval;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/c-file-ptr-stream.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,227 @@
+/*
+
+Copyright (C) 2000-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if !defined (octave_c_file_ptr_stream_h)
+#define octave_c_file_ptr_stream_h 1
+
+#include <cstdio>
+
+#include <iosfwd>
+
+class
+c_file_ptr_buf : public std::streambuf
+{
+public:
+
+#if !defined (CXX_ISO_COMPLIANT_LIBRARY)
+  typedef int int_type;
+#else
+  typedef std::streambuf::int_type int_type;
+#endif
+
+  typedef int (*close_fcn) (FILE *);
+
+  FILE* stdiofile (void) { return f; }
+
+  c_file_ptr_buf (FILE *f_arg, close_fcn cf_arg = file_close)
+    : std::streambuf (), f (f_arg), cf (cf_arg)
+    { }
+
+  ~c_file_ptr_buf (void);
+
+  int_type overflow (int_type);
+
+  int_type underflow (void) { return underflow_common (false); }
+
+  int_type uflow (void) { return underflow_common (true); }
+
+  int_type pbackfail (int_type);
+
+  std::streamsize xsputn (const char*, std::streamsize);
+
+  std::streamsize xsgetn (char *, std::streamsize);
+
+  std::streampos seekoff (std::streamoff, std::ios::seekdir,
+                          std::ios::openmode = std::ios::in | std::ios::out);
+
+  std::streampos seekpos (std::streampos,
+                          std::ios::openmode = std::ios::in | std::ios::out);
+
+  int sync (void);
+
+  int flush (void);
+
+  int buf_close (void);
+
+  int file_number () const { return f ? fileno (f) : -1; }
+
+  int seek (long offset, int origin);
+
+  long tell (void);
+
+  void clear (void) { if (f) clearerr (f); }
+
+  static int file_close (FILE *f);
+
+protected:
+
+  FILE *f;
+
+  close_fcn cf;
+
+private:
+
+  int_type underflow_common (bool);
+
+  // No copying!
+
+  c_file_ptr_buf (const c_file_ptr_buf&);
+
+  c_file_ptr_buf& operator = (const c_file_ptr_buf&);
+};
+
+// FIXME -- the following three classes could probably share
+// some code...
+
+template <typename STREAM_T, typename FILE_T, typename BUF_T>
+class
+c_file_ptr_stream : public STREAM_T
+{
+public:
+
+  c_file_ptr_stream (FILE_T f, typename BUF_T::close_fcn cf = BUF_T::file_close)
+    : STREAM_T (0), buf (new BUF_T (f, cf)) { STREAM_T::init (buf); }
+
+  ~c_file_ptr_stream (void) { delete buf; buf = 0; }
+
+  BUF_T *rdbuf (void) { return buf; }
+
+  void stream_close (void) { if (buf) buf->buf_close (); }
+
+  int seek (long offset, int origin)
+    { return buf ? buf->seek (offset, origin) : -1; }
+
+  long tell (void) { return buf ? buf->tell () : -1; }
+
+  void clear (void) { if (buf) buf->clear (); STREAM_T::clear (); }
+
+private:
+
+  BUF_T *buf;
+
+  // No copying!
+
+  c_file_ptr_stream (const c_file_ptr_stream&);
+
+  c_file_ptr_stream& operator = (const c_file_ptr_stream&);
+};
+
+typedef c_file_ptr_stream<std::istream, FILE *, c_file_ptr_buf> i_c_file_ptr_stream;
+typedef c_file_ptr_stream<std::ostream, FILE *, c_file_ptr_buf> o_c_file_ptr_stream;
+typedef c_file_ptr_stream<std::iostream, FILE *, c_file_ptr_buf> io_c_file_ptr_stream;
+
+#ifdef HAVE_ZLIB
+
+#ifdef HAVE_ZLIB_H
+#include <zlib.h>
+#endif
+
+class
+c_zfile_ptr_buf : public std::streambuf
+{
+public:
+
+#if !defined (CXX_ISO_COMPLIANT_LIBRARY)
+  typedef int int_type;
+#else
+  typedef std::streambuf::int_type int_type;
+#endif
+
+  typedef int (*close_fcn) (gzFile);
+
+  gzFile stdiofile (void) { return f; }
+
+  c_zfile_ptr_buf (gzFile f_arg, close_fcn cf_arg = file_close)
+    : std::streambuf (), f (f_arg), cf (cf_arg)
+    { }
+
+  ~c_zfile_ptr_buf (void);
+
+  int_type overflow (int_type);
+
+  int_type underflow (void) { return underflow_common (false); }
+
+  int_type uflow (void) { return underflow_common (true); }
+
+  int_type pbackfail (int_type);
+
+  std::streamsize xsputn (const char*, std::streamsize);
+
+  std::streamsize xsgetn (char *, std::streamsize);
+
+  std::streampos seekoff (std::streamoff, std::ios::seekdir,
+                          std::ios::openmode = std::ios::in | std::ios::out);
+
+  std::streampos seekpos (std::streampos,
+                          std::ios::openmode = std::ios::in | std::ios::out);
+
+  int sync (void);
+
+  int flush (void);
+
+  int buf_close (void);
+
+  int file_number () const { return -1; }
+
+  int seek (long offset, int origin)
+    { return f ? gzseek (f, offset, origin) : -1; }
+
+  long tell (void) { return f ? gztell (f) : -1; }
+
+  void clear (void) { if (f) gzclearerr (f); }
+
+  static int file_close (gzFile f) { return ::gzclose (f); }
+
+protected:
+
+  gzFile f;
+
+  close_fcn cf;
+
+private:
+
+  int_type underflow_common (bool);
+
+  // No copying!
+
+  c_zfile_ptr_buf (const c_zfile_ptr_buf&);
+
+  c_zfile_ptr_buf& operator = (const c_zfile_ptr_buf&);
+};
+
+typedef c_file_ptr_stream<std::istream, gzFile, c_zfile_ptr_buf> i_c_zfile_ptr_stream;
+typedef c_file_ptr_stream<std::ostream, gzFile, c_zfile_ptr_buf> o_c_zfile_ptr_stream;
+typedef c_file_ptr_stream<std::iostream, gzFile, c_zfile_ptr_buf> io_c_zfile_ptr_stream;
+
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/comment-list.cc	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,106 @@
+/*
+
+Copyright (C) 2000-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "lo-utils.h"
+#include "singleton-cleanup.h"
+
+#include "comment-list.h"
+#include "error.h"
+
+octave_comment_buffer *octave_comment_buffer::instance = 0;
+
+octave_comment_list *
+octave_comment_list::dup (void) const
+{
+  octave_comment_list *new_cl = new octave_comment_list ();
+
+  for (const_iterator p = begin (); p != end (); p++)
+    {
+      const octave_comment_elt elt = *p;
+
+      new_cl->append (elt);
+    }
+
+  return new_cl;
+}
+
+bool
+octave_comment_buffer::instance_ok (void)
+{
+  bool retval = true;
+
+  if (! instance)
+    {
+      instance = new octave_comment_buffer ();
+
+      if (instance)
+        singleton_cleanup_list::add (cleanup_instance);
+    }
+
+  if (! instance)
+    {
+      ::error ("unable to create comment buffer object");
+
+      retval = false;
+    }
+
+  return retval;
+}
+
+void
+octave_comment_buffer::append (const std::string& s,
+                               octave_comment_elt::comment_type t)
+{
+  if (instance_ok ())
+    instance->do_append (s, t);
+}
+
+octave_comment_list *
+octave_comment_buffer::get_comment (void)
+{
+  return (instance_ok ()) ? instance->do_get_comment () : 0;
+}
+
+void
+octave_comment_buffer::do_append (const std::string& s,
+                                  octave_comment_elt::comment_type t)
+{
+  comment_list->append (s, t);
+}
+
+octave_comment_list *
+octave_comment_buffer::do_get_comment (void)
+{
+  octave_comment_list *retval = 0;
+
+  if (comment_list && comment_list->length () > 0)
+    {
+      retval = comment_list;
+      comment_list = new octave_comment_list ();
+    }
+
+  return retval;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/comment-list.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,131 @@
+/*
+
+Copyright (C) 2000-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if !defined (octave_comment_list_h)
+#define octave_comment_list_h 1
+
+#include <string>
+
+#include <base-list.h>
+
+extern std::string get_comment_text (void);
+
+extern char *get_comment_text_c_str (void);
+
+extern void save_comment_text (const std::string& text);
+
+class
+octave_comment_elt
+{
+public:
+
+  enum comment_type
+  {
+    unknown,
+    block,
+    end_of_line,
+    doc_string,
+    copyright
+  };
+
+  octave_comment_elt (const std::string& s = std::string (),
+                      comment_type t = unknown)
+    : txt (s), typ (t) { }
+
+  octave_comment_elt (const octave_comment_elt& oc)
+    : txt (oc.txt), typ (oc.typ) { }
+
+  octave_comment_elt& operator = (const octave_comment_elt& oc)
+    {
+      if (this != &oc)
+        {
+          txt = oc.txt;
+          typ = oc.typ;
+        }
+
+      return *this;
+    }
+
+  std::string text (void) const { return txt; }
+
+  comment_type type (void) const { return typ; }
+
+  ~octave_comment_elt (void) { }
+
+private:
+
+  // The text of the comment.
+  std::string txt;
+
+  // The type of comment.
+  comment_type typ;
+};
+
+class
+octave_comment_list : public octave_base_list<octave_comment_elt>
+{
+public:
+
+  octave_comment_list (void) { }
+
+  void append (const octave_comment_elt& elt)
+    { octave_base_list<octave_comment_elt>::append (elt); }
+
+  void append (const std::string& s,
+               octave_comment_elt::comment_type t = octave_comment_elt::unknown)
+    { append (octave_comment_elt (s, t)); }
+
+  octave_comment_list *dup (void) const;
+};
+
+class
+octave_comment_buffer
+{
+public:
+
+  octave_comment_buffer (void)
+    : comment_list (new octave_comment_list ()) { }
+
+  ~octave_comment_buffer (void) { delete comment_list; }
+
+  static bool instance_ok (void);
+
+  static void append
+    (const std::string& s,
+     octave_comment_elt::comment_type t = octave_comment_elt::unknown);
+
+  static octave_comment_list *get_comment (void);
+
+private:
+
+  void do_append (const std::string& s, octave_comment_elt::comment_type t);
+
+  octave_comment_list *do_get_comment (void);
+
+  octave_comment_list *comment_list;
+
+  static octave_comment_buffer *instance;
+
+  static void cleanup_instance (void) { delete instance; instance = 0; }
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/cutils.c	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,60 @@
+/*
+
+Copyright (C) 1999-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <time.h>
+
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "cutils.h"
+
+void
+octave_sleep (unsigned int seconds)
+{
+  sleep (seconds);
+}
+
+void
+octave_usleep (unsigned int useconds)
+{
+  struct timespec delay;
+  struct timespec remaining;
+
+  unsigned int sec = useconds / 1000000;
+  unsigned int usec = useconds % 1000000;
+
+  delay.tv_sec = sec;
+  delay.tv_nsec = usec * 1000;
+
+  nanosleep (&delay, &remaining);
+}
+
+int
+octave_raw_vsnprintf (char *buf, size_t n, const char *fmt, va_list args)
+{
+  return vsnprintf (buf, n, fmt, args);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/cutils.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,43 @@
+/*
+
+Copyright (C) 2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if !defined (octave_cutils_h)
+#define octave_cutils_h 1
+
+#include <stdarg.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+OCTINTERP_API void octave_sleep (unsigned int seconds);
+
+OCTINTERP_API void octave_usleep (unsigned int useconds);
+
+OCTINTERP_API int
+octave_raw_vsnprintf (char *buf, size_t n, const char *fmt, va_list args);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/defun-dld.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,71 @@
+/*
+
+Copyright (C) 1994-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if !defined (octave_defun_dld_h)
+#define octave_defun_dld_h 1
+
+#if defined (octave_defun_h)
+#error defun.h and defun-dld.h both included in same file!
+#endif
+
+#include "defun-int.h"
+
+// Define a builtin function that may be loaded dynamically at run
+// time.
+//
+// If Octave is not configured for dynamic linking of builtin
+// functions, this is the same as DEFUN, except that it will generate
+// an extra externally visible function.
+//
+// The first DECLARE_FUN is for the benefit of the installer function
+// and the second is for the definition of the function.
+
+#if defined (MAKE_BUILTINS)
+
+#define DEFUN_DLD(name, args_name, nargout_name, doc) \
+  DEFUN_DLD_INTERNAL (name, args_name, nargout_name, doc)
+
+// This one can be used when `name' cannot be used directly (if it is
+// already defined as a macro).  In that case, name is already a
+// quoted string, and the internal name of the function must be passed
+// too (the convention is to use a prefix of "F", so "foo" becomes
+// "Ffoo") as well as the name of the generated installer function
+// (the convention is to use a prefix of "G", so "foo" becomes "Gfoo").
+
+#define DEFUNX_DLD(name, fname, gname, args_name, nargout_name, doc) \
+  DEFUNX_DLD_INTERNAL (name, fname, args_name, nargout_name, doc)
+
+#else
+
+#define DEFUN_DLD(name, args_name, nargout_name, doc) \
+  DECLARE_FUN (name, args_name, nargout_name); \
+  DEFINE_FUN_INSTALLER_FUN (name, doc) \
+  DECLARE_FUN (name, args_name, nargout_name)
+
+#define DEFUNX_DLD(name, fname, gname, args_name, nargout_name, doc) \
+  DECLARE_FUNX (fname, args_name, nargout_name); \
+  DEFINE_FUNX_INSTALLER_FUN (name, fname, gname, doc) \
+  DECLARE_FUNX (fname, args_name, nargout_name)
+
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/defun-int.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,187 @@
+/*
+
+Copyright (C) 1994-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if !defined (octave_defun_int_h)
+#define octave_defun_int_h 1
+
+#include <string>
+
+#include "ov-builtin.h"
+#include "ov-dld-fcn.h"
+#include "symtab.h"
+#include "version.h"
+
+class octave_value;
+
+extern OCTINTERP_API void print_usage (void);
+extern OCTINTERP_API void print_usage (const std::string&);
+
+extern OCTINTERP_API void check_version (const std::string& version, const std::string& fcn);
+
+extern OCTINTERP_API void
+install_builtin_function (octave_builtin::fcn f, const std::string& name,
+                          const std::string& file, const std::string& doc,
+                          bool can_hide_function = true);
+
+extern OCTINTERP_API void
+install_dld_function (octave_dld_function::fcn f, const std::string& name,
+                      const octave_shlib& shl, const std::string& doc,
+                      bool relative = false);
+
+extern OCTINTERP_API void
+install_mex_function (void *fptr, bool fmex, const std::string& name,
+                      const octave_shlib& shl, bool relative = false);
+
+extern OCTINTERP_API void
+alias_builtin (const std::string& alias, const std::string& name);
+
+// Gets the shlib of the currently executing DLD function, if any.
+extern OCTINTERP_API octave_shlib
+get_current_shlib (void);
+
+// This is a convenience class that calls the above function automatically at
+// construction time. When deriving new classes, you can either use it as a field
+// or as a parent (with multiple inheritance).
+
+class octave_auto_shlib : public octave_shlib
+{
+public:
+  octave_auto_shlib (void)
+    : octave_shlib (get_current_shlib ()) { }
+  octave_auto_shlib (const octave_shlib& shl)
+    : octave_shlib (shl) { }
+};
+
+extern OCTINTERP_API bool
+defun_isargout (int, int);
+
+extern OCTINTERP_API void
+defun_isargout (int, int, bool *);
+
+#define DECLARE_FUNX(name, args_name, nargout_name) \
+  OCTAVE_EXPORT octave_value_list \
+  name (const octave_value_list& args_name, int nargout_name)
+
+#define DECLARE_FUN(name, args_name, nargout_name) \
+  DECLARE_FUNX (F ## name, args_name, nargout_name)
+
+// Define the code that will be used to insert the new function into
+// the symbol table.  We look for this name instead of the actual
+// function so that we can easily install the doc std::string too.
+
+typedef bool (*octave_dld_fcn_installer) (const octave_shlib&, bool relative);
+
+typedef octave_function * (*octave_dld_fcn_getter) (const octave_shlib&, bool relative);
+
+#define DEFINE_FUN_INSTALLER_FUN(name, doc) \
+  DEFINE_FUNX_INSTALLER_FUN(#name, F ## name, G ## name, doc)
+
+#define DEFINE_FUNX_INSTALLER_FUN(name, fname, gname, doc) \
+  extern "C" \
+  OCTAVE_EXPORT \
+  octave_function * \
+  gname (const octave_shlib& shl, bool relative) \
+  { \
+    octave_function *retval = 0; \
+ \
+    check_version (OCTAVE_API_VERSION, name); \
+ \
+    if (! error_state) \
+      { \
+        octave_dld_function *fcn = octave_dld_function::create (fname, shl, name, doc); \
+ \
+        if (relative) \
+          fcn->mark_relative (); \
+ \
+        retval = fcn; \
+      } \
+ \
+    return retval; \
+  }
+
+// MAKE_BUILTINS is defined to extract function names and related
+// information and create the *.df files that are eventually used to
+// create the builtins.cc file.
+
+#if defined (MAKE_BUILTINS)
+
+// Generate code to install name in the symbol table.  The script
+// mkdefs will create a .def file for every .cc file that uses DEFUN,
+// or DEFCMD.
+
+#define DEFUN_INTERNAL(name, args_name, nargout_name, doc) \
+  BEGIN_INSTALL_BUILTIN \
+    XDEFUN_INTERNAL (name, args_name, nargout_name, doc) \
+  END_INSTALL_BUILTIN
+
+#define DEFCONSTFUN_INTERNAL(name, args_name, nargout_name, doc) \
+  BEGIN_INSTALL_BUILTIN \
+    XDEFCONSTFUN_INTERNAL (name, args_name, nargout_name, doc) \
+  END_INSTALL_BUILTIN
+
+#define DEFUNX_INTERNAL(name, fname, args_name, nargout_name, doc) \
+  BEGIN_INSTALL_BUILTIN \
+    XDEFUNX_INTERNAL (name, fname, args_name, nargout_name, doc) \
+  END_INSTALL_BUILTIN
+
+// Generate code to install name in the symbol table.  The script
+// mkdefs will create a .def file for every .cc file that uses
+// DEFUN_DLD.
+
+#define DEFUN_DLD_INTERNAL(name, args_name, nargout_name, doc) \
+  BEGIN_INSTALL_BUILTIN \
+    XDEFUN_DLD_INTERNAL (name, args_name, nargout_name, doc) \
+  END_INSTALL_BUILTIN
+
+#define DEFUNX_DLD_INTERNAL(name, fname, args_name, nargout_name, doc) \
+  BEGIN_INSTALL_BUILTIN \
+    XDEFUNX_DLD_INTERNAL (name, fname, args_name, nargout_name, doc) \
+  END_INSTALL_BUILTIN
+
+// Generate code for making another name for an existing function.
+
+#define DEFALIAS_INTERNAL(alias, name) \
+  BEGIN_INSTALL_BUILTIN \
+    XDEFALIAS_INTERNAL(alias, name) \
+  END_INSTALL_BUILTIN
+
+#else /* ! MAKE_BUILTINS */
+
+// Generate the first line of the function definition.  This ensures
+// that the internal functions all have the same signature.
+
+#define DEFUN_INTERNAL(name, args_name, nargout_name, doc) \
+  DECLARE_FUN (name, args_name, nargout_name)
+
+#define DEFCONSTFUN_INTERNAL(name, args_name, nargout_name, doc) \
+  DECLARE_FUN (name, args_name, nargout_name)
+
+#define DEFUNX_INTERNAL(name, fname, args_name, nargout_name, doc) \
+  DECLARE_FUNX (fname, args_name, nargout_name)
+
+// No definition is required for an alias.
+
+#define DEFALIAS_INTERNAL(alias, name)
+
+#endif /* ! MAKE_BUILTINS */
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/display.cc	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,182 @@
+/*
+
+Copyright (C) 2009-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <cstdlib>
+
+#if defined (OCTAVE_USE_WINDOWS_API)
+#include <windows.h>
+#elif defined (HAVE_FRAMEWORK_CARBON)
+#include <Carbon/Carbon.h>
+#elif defined (HAVE_X_WINDOWS)
+#include <X11/Xlib.h>
+#endif
+
+#include "singleton-cleanup.h"
+
+#include "display.h"
+#include "error.h"
+
+display_info *display_info::instance = 0;
+
+#if defined (HAVE_FRAMEWORK_CARBON) && ! defined (HAVE_CARBON_CGDISPLAYBITSPERPIXEL)
+// FIXME - This will only work for MacOS > 10.5. For earlier versions
+// this code is not needed (use CGDisplayBitsPerPixel instead).
+size_t DisplayBitsPerPixel (CGDirectDisplayID display)
+{
+  CGDisplayModeRef mode = CGDisplayCopyDisplayMode (display);
+  CFStringRef pixelEncoding = CGDisplayModeCopyPixelEncoding (mode);
+
+  if (CFStringCompare (pixelEncoding, CFSTR (IO32BitDirectPixels), 0) == 0)
+    return 32;
+  else if (CFStringCompare (pixelEncoding, CFSTR (IO16BitDirectPixels), 0) == 0)
+    return 16;
+  else 
+    return 8;
+}
+#endif
+
+void
+display_info::init (bool query)
+{
+  if (query)
+    {
+#if defined (OCTAVE_USE_WINDOWS_API)
+
+      HDC hdc = GetDC (0);
+
+      if (hdc)
+        {
+          dp = GetDeviceCaps (hdc, BITSPIXEL);
+
+          ht = GetDeviceCaps (hdc, VERTRES);
+          wd = GetDeviceCaps (hdc, HORZRES);
+
+          double ht_mm = GetDeviceCaps (hdc, VERTSIZE);
+          double wd_mm = GetDeviceCaps (hdc, HORZSIZE);
+
+          rx = wd * 25.4 / wd_mm;
+          ry = ht * 25.4 / ht_mm;
+        }
+      else
+        warning ("no graphical display found");
+
+#elif defined (HAVE_FRAMEWORK_CARBON)
+
+      CGDirectDisplayID display = CGMainDisplayID ();
+
+      if (display)
+        {
+#  if defined (HAVE_CARBON_CGDISPLAYBITSPERPIXEL)
+          // For MacOS < 10.7 use the line below
+          dp = CGDisplayBitsPerPixel (display);
+#  else
+          // For MacOS > 10.5 use the line below
+          dp = DisplayBitsPerPixel (display);
+#  endif
+
+          ht = CGDisplayPixelsHigh (display);
+          wd = CGDisplayPixelsWide (display);
+
+          CGSize sz_mm = CGDisplayScreenSize (display);
+          // For MacOS >= 10.6, CGSize is a struct keeping 2 CGFloat values,
+          // but the CGFloat typedef is not present on older systems,
+          // so use double instead.
+          double ht_mm = sz_mm.height;
+          double wd_mm = sz_mm.width;
+
+          rx = wd * 25.4 / wd_mm;
+          ry = ht * 25.4 / ht_mm;
+        }
+      else
+        warning ("no graphical display found");
+
+#elif defined (HAVE_X_WINDOWS)
+
+      const char *display_name = getenv ("DISPLAY");
+
+      if (display_name && *display_name)
+        {
+          Display *display = XOpenDisplay (display_name);
+
+          if (display)
+            {
+              Screen *screen = DefaultScreenOfDisplay (display);
+
+              if (screen)
+                {
+                  dp = DefaultDepthOfScreen (screen);
+
+                  ht = HeightOfScreen (screen);
+                  wd = WidthOfScreen (screen);
+
+                  int screen_number = XScreenNumberOfScreen (screen);
+
+                  double ht_mm = DisplayHeightMM (display, screen_number);
+                  double wd_mm = DisplayWidthMM (display, screen_number);
+
+                  rx = wd * 25.4 / wd_mm;
+                  ry = ht * 25.4 / ht_mm;
+                }
+              else
+                warning ("X11 display has no default screen");
+
+              XCloseDisplay (display);
+            }
+          else
+            warning ("unable to open X11 DISPLAY");
+        }
+      else
+        warning ("X11 DISPLAY environment variable not set");
+#else
+
+      warning ("no graphical display found");
+
+#endif
+    }
+}
+
+bool
+display_info::instance_ok (bool query)
+{
+  bool retval = true;
+
+  if (! instance)
+    {
+      instance = new display_info (query);
+
+      if (instance)
+        singleton_cleanup_list::add (cleanup_instance);
+    }
+
+  if (! instance)
+    {
+      ::error ("unable to create display_info object!");
+
+      retval = false;
+    }
+
+  return retval;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/display.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,99 @@
+/*
+
+Copyright (C) 2009-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if !defined (octave_display_h)
+#define octave_display_h 1
+
+class Matrix;
+
+class display_info
+{
+protected:
+
+  display_info (bool query = true)
+    : ht (1), wd (1), dp (0), rx (72), ry (72)
+  {
+    init (query);
+  }
+
+public:
+
+  static int height (void)
+  {
+    return instance_ok () ? instance->do_height () : 0;
+  }
+
+  static int width (void)
+  {
+    return instance_ok () ? instance->do_width () : 0;
+  }
+
+  static int depth (void)
+  {
+    return instance_ok () ? instance->do_depth () : 0;
+  }
+
+  static double x_dpi (void)
+  {
+    return instance_ok () ? instance->do_x_dpi () : 0;
+  }
+
+  static double y_dpi (void)
+  {
+    return instance_ok () ? instance->do_y_dpi () : 0;
+  }
+
+  // To disable querying the window system for defaults, this function
+  // must be called before any other display_info function.
+  static void no_window_system (void)
+  {
+    instance_ok (false);
+  }
+
+private:
+
+  static display_info *instance;
+
+  static void cleanup_instance (void) { delete instance; instance = 0; }
+
+  // Height, width, and depth of the display.
+  int ht;
+  int wd;
+  int dp;
+
+  // X- and Y- Resolution of the display in dots (pixels) per inch.
+  double rx;
+  double ry;
+
+  int do_height (void) const { return ht; }
+  int do_width (void) const { return wd; }
+  int do_depth (void) const { return dp; }
+
+  double do_x_dpi (void) const { return rx; }
+  double do_y_dpi (void) const { return ry; }
+
+  void init (bool query = true);
+
+  static bool instance_ok (bool query = true);
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/dynamic-ld.cc	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,582 @@
+/*
+
+Copyright (C) 1993-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <iostream>
+#include <list>
+
+#include "file-stat.h"
+#include "oct-env.h"
+#include "oct-time.h"
+#include "singleton-cleanup.h"
+
+#include <defaults.h>
+
+#include "defun.h"
+#include "dynamic-ld.h"
+#include "ov-fcn.h"
+#include "ov-dld-fcn.h"
+#include "ov-mex-fcn.h"
+#include "parse.h"
+#include "unwind-prot.h"
+#include "utils.h"
+#include "variables.h"
+
+#define STRINGIFY(s) STRINGIFY1(s)
+#define STRINGIFY1(s) #s
+
+class
+octave_shlib_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);
+
+  static octave_shlib find_file (const std::string& file_name);
+
+  static void display (void);
+
+private:
+
+  octave_shlib_list (void) : lib_list () { }
+
+  ~octave_shlib_list (void) { }
+
+  void do_append (const octave_shlib& shl);
+
+  void do_remove (octave_shlib& shl, octave_shlib::close_hook cl_hook = 0);
+
+  octave_shlib do_find_file (const std::string& file_name) const;
+
+  void do_display (void) const;
+
+  static octave_shlib_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> lib_list;
+
+  // No copying!
+
+  octave_shlib_list (const octave_shlib_list&);
+
+  octave_shlib_list& operator = (const octave_shlib_list&);
+};
+
+octave_shlib_list *octave_shlib_list::instance = 0;
+
+void
+octave_shlib_list::do_append (const octave_shlib& shl)
+{
+  lib_list.push_back (shl);
+}
+
+void
+octave_shlib_list::do_remove (octave_shlib& shl,
+                              octave_shlib::close_hook cl_hook)
+{
+  for (iterator p = lib_list.begin (); p != lib_list.end (); p++)
+    {
+      if (*p == shl)
+        {
+          // Erase first to avoid potentially invalidating the pointer by the
+          // following hooks.
+          lib_list.erase (p);
+
+          shl.close (cl_hook);
+
+          break;
+        }
+    }
+}
+
+octave_shlib
+octave_shlib_list::do_find_file (const std::string& file_name) const
+{
+  octave_shlib retval;
+
+  for (const_iterator p = lib_list.begin (); p != lib_list.end (); p++)
+    {
+      if (p->file_name () == file_name)
+        {
+          retval = *p;
+          break;
+        }
+    }
+
+  return retval;
+}
+
+void
+octave_shlib_list::do_display (void) const
+{
+  std::cerr << "current shared libraries:" << std::endl;
+  for (const_iterator p = lib_list.begin (); p != lib_list.end (); p++)
+    std::cerr << "  " << p->file_name () << std::endl;
+}
+
+bool
+octave_shlib_list::instance_ok (void)
+{
+  bool retval = true;
+
+  if (! instance)
+    {
+      instance = new octave_shlib_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_shlib_list::append (const octave_shlib& shl)
+{
+  if (instance_ok ())
+    instance->do_append (shl);
+}
+
+void
+octave_shlib_list::remove (octave_shlib& shl,
+                           octave_shlib::close_hook cl_hook)
+{
+  if (instance_ok ())
+    instance->do_remove (shl, cl_hook);
+}
+
+octave_shlib
+octave_shlib_list::find_file (const std::string& file_name)
+{
+  return (instance_ok ())
+    ? instance->do_find_file (file_name) : octave_shlib ();
+}
+
+void
+octave_shlib_list::display (void)
+{
+  if (instance_ok ())
+    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;
+
+bool
+octave_dynamic_loader::instance_ok (void)
+{
+  bool retval = true;
+
+  if (! instance)
+    {
+      instance = new octave_dynamic_loader ();
+
+      if (instance)
+        singleton_cleanup_list::add (cleanup_instance);
+    }
+
+  if (! instance)
+    {
+      ::error ("unable to create dynamic loader object!");
+
+      retval = false;
+    }
+
+  return retval;
+}
+
+static void
+do_clear_function (const std::string& fcn_name)
+{
+  warning_with_id ("Octave:reload-forces-clear", "  %s", fcn_name.c_str ());
+
+  symbol_table::clear_dld_function (fcn_name);
+}
+
+static void
+clear (octave_shlib& oct_file)
+{
+  if (oct_file.number_of_functions_loaded () > 1)
+    {
+      warning_with_id ("Octave:reload-forces-clear",
+                       "reloading %s clears the following functions:",
+                       oct_file.file_name ().c_str ());
+
+      octave_shlib_list::remove (oct_file, do_clear_function);
+    }
+  else
+    octave_shlib_list::remove (oct_file, symbol_table::clear_dld_function);
+}
+
+octave_function *
+octave_dynamic_loader::do_load_oct (const std::string& fcn_name,
+                                    const std::string& file_name,
+                                    bool relative)
+{
+  octave_function *retval = 0;
+
+  unwind_protect frame;
+
+  frame.protect_var (octave_dynamic_loader::doing_load);
+
+  doing_load = true;
+
+  octave_shlib oct_file = octave_shlib_list::find_file (file_name);
+
+  if (oct_file && oct_file.is_out_of_date ())
+    clear (oct_file);
+
+  if (! oct_file)
+    {
+      oct_file.open (file_name);
+
+      if (! error_state && oct_file)
+        octave_shlib_list::append (oct_file);
+    }
+
+  if (! error_state)
+    {
+      if (oct_file)
+        {
+          void *function = oct_file.search (fcn_name, name_mangler);
+
+          if (! function)
+            {
+              // FIXME -- can we determine this C mangling scheme
+              // automatically at run time or configure time?
+
+              function = oct_file.search (fcn_name, name_uscore_mangler);
+            }
+
+          if (function)
+            {
+              octave_dld_fcn_getter f
+                = FCN_PTR_CAST (octave_dld_fcn_getter, function);
+
+              retval = f (oct_file, relative);
+
+              if (! retval)
+                ::error ("failed to install .oct file function `%s'",
+                         fcn_name.c_str ());
+            }
+        }
+      else
+        ::error ("%s is not a valid shared library",
+                 file_name.c_str ());
+    }
+
+  return retval;
+}
+
+octave_function *
+octave_dynamic_loader::do_load_mex (const std::string& fcn_name,
+                                    const std::string& file_name,
+                                    bool /*relative*/)
+{
+  octave_function *retval = 0;
+
+  unwind_protect frame;
+
+  frame.protect_var (octave_dynamic_loader::doing_load);
+
+  doing_load = true;
+
+  octave_shlib mex_file = octave_shlib_list::find_file (file_name);
+
+  if (mex_file && mex_file.is_out_of_date ())
+    clear (mex_file);
+
+  if (! mex_file)
+    {
+      mex_file.open (file_name);
+
+      if (! error_state && mex_file)
+        octave_shlib_list::append (mex_file);
+    }
+
+  if (! error_state)
+    {
+      if (mex_file)
+        {
+          void *function = 0;
+
+          bool have_fmex = false;
+
+          octave_mex_file_list::append (mex_file);
+
+          function = mex_file.search (fcn_name, mex_mangler);
+
+          if (! function)
+            {
+              // FIXME -- can we determine this C mangling scheme
+              // automatically at run time or configure time?
+
+              function = mex_file.search (fcn_name, mex_uscore_mangler);
+
+              if (! function)
+                {
+                  function = mex_file.search (fcn_name, mex_f77_mangler);
+
+                  if (function)
+                    have_fmex = true;
+                }
+            }
+
+          if (function)
+            retval = new octave_mex_function (function, have_fmex,
+                                              mex_file, fcn_name);
+          else
+            ::error ("failed to install .mex file function `%s'",
+                     fcn_name.c_str ());
+        }
+      else
+        ::error ("%s is not a valid shared library",
+                 file_name.c_str ());
+    }
+
+  return retval;
+}
+
+bool
+octave_dynamic_loader::do_remove_oct (const std::string& fcn_name,
+                                      octave_shlib& shl)
+{
+  bool retval = false;
+
+  // We don't need to do anything if this is called because we are in
+  // the process of reloading a .oct file that has changed.
+
+  if (! doing_load)
+    {
+      retval = shl.remove (fcn_name);
+
+      if (shl.number_of_functions_loaded () == 0)
+        octave_shlib_list::remove (shl);
+    }
+
+  return retval;
+}
+
+bool
+octave_dynamic_loader::do_remove_mex (const std::string& fcn_name,
+                                      octave_shlib& shl)
+{
+  bool retval = false;
+
+  // We don't need to do anything if this is called because we are in
+  // the process of reloading a .oct file that has changed.
+
+  if (! doing_load)
+    {
+      retval = shl.remove (fcn_name);
+
+      if (shl.number_of_functions_loaded () == 0)
+        octave_mex_file_list::remove (shl);
+    }
+
+  return retval;
+}
+
+octave_function *
+octave_dynamic_loader::load_oct (const std::string& fcn_name,
+                                  const std::string& file_name,
+                                  bool relative)
+{
+  return (instance_ok ())
+    ? instance->do_load_oct (fcn_name, file_name, relative) : 0;
+}
+
+octave_function *
+octave_dynamic_loader::load_mex (const std::string& fcn_name,
+                                  const std::string& file_name,
+                                  bool relative)
+{
+  return (instance_ok ())
+    ? instance->do_load_mex (fcn_name, file_name, relative) : 0;
+}
+
+bool
+octave_dynamic_loader::remove_oct (const std::string& fcn_name,
+                                   octave_shlib& shl)
+{
+  return (instance_ok ()) ? instance->do_remove_oct (fcn_name, shl) : false;
+}
+
+bool
+octave_dynamic_loader::remove_mex (const std::string& fcn_name,
+                                   octave_shlib& shl)
+{
+  return (instance_ok ()) ? instance->do_remove_mex (fcn_name, shl) : false;
+}
+
+std::string
+octave_dynamic_loader::name_mangler (const std::string& name)
+{
+  return "G" + name;
+}
+
+std::string
+octave_dynamic_loader::name_uscore_mangler (const std::string& name)
+{
+  return "_G" + name;
+}
+
+std::string
+octave_dynamic_loader::mex_mangler (const std::string&)
+{
+  return "mexFunction";
+}
+
+std::string
+octave_dynamic_loader::mex_uscore_mangler (const std::string&)
+{
+  return "_mexFunction";
+}
+
+std::string
+octave_dynamic_loader::mex_f77_mangler (const std::string&)
+{
+  return STRINGIFY (F77_FUNC (mexfunction, MEXFUNCTION));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/dynamic-ld.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,100 @@
+/*
+
+Copyright (C) 1993-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if !defined (octave_dynamic_ld_h)
+#define octave_dynamic_ld_h 1
+
+#include <string>
+
+#include "oct-shlib.h"
+
+class octave_function;
+
+class
+octave_dynamic_loader
+{
+protected:
+
+  octave_dynamic_loader (void) { }
+
+public:
+
+  virtual ~octave_dynamic_loader (void) { }
+
+  static octave_function *
+  load_oct (const std::string& fcn_name,
+             const std::string& file_name = std::string (),
+             bool relative = false);
+
+  static octave_function *
+  load_mex (const std::string& fcn_name,
+             const std::string& file_name = std::string (),
+             bool relative = false);
+
+  static bool remove_oct (const std::string& fcn_name, octave_shlib& shl);
+
+  static bool remove_mex (const std::string& fcn_name, octave_shlib& shl);
+
+private:
+
+  // No copying!
+
+  octave_dynamic_loader (const octave_dynamic_loader&);
+
+  octave_dynamic_loader& operator = (const octave_dynamic_loader&);
+
+  static octave_dynamic_loader *instance;
+
+  static void cleanup_instance (void) { delete instance; instance = 0; }
+
+  static bool instance_ok (void);
+
+  octave_function *
+  do_load_oct (const std::string& fcn_name,
+                const std::string& file_name = std::string (),
+                bool relative = false);
+
+  octave_function *
+  do_load_mex (const std::string& fcn_name,
+                const std::string& file_name = std::string (),
+                bool relative = false);
+
+  bool do_remove_oct (const std::string& fcn_name, octave_shlib& shl);
+
+  bool do_remove_mex (const std::string& fcn_name, octave_shlib& shl);
+
+  static bool doing_load;
+
+protected:
+
+  static std::string name_mangler (const std::string& name);
+
+  static std::string name_uscore_mangler (const std::string& name);
+
+  static std::string mex_mangler (const std::string& name);
+
+  static std::string mex_uscore_mangler (const std::string& name);
+
+  static std::string mex_f77_mangler (const std::string& name);
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/gl-render.cc	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,3039 @@
+/*
+
+Copyright (C) 2008-2012 Michael Goffioul
+
+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/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#if defined (HAVE_OPENGL)
+
+#include <iostream>
+
+#include <lo-mappers.h>
+#include "oct-locbuf.h"
+#include "oct-refcount.h"
+#include "gl-render.h"
+#include "txt-eng.h"
+#include "txt-eng-ft.h"
+
+#define LIGHT_MODE GL_FRONT_AND_BACK
+
+// Win32 API requires the CALLBACK attributes for
+// GLU callback functions. Define it to empty on
+// other platforms.
+#ifndef CALLBACK
+#define CALLBACK
+#endif
+
+static octave_idx_type
+xmin (octave_idx_type x, octave_idx_type y)
+{
+  return x < y ? x : y;
+}
+
+class
+opengl_texture
+{
+protected:
+  class texture_rep
+  {
+  public:
+    texture_rep (void)
+      : id (), w (), h (), tw (), th (), tx (), ty (),
+        valid (false), count (1)
+    { }
+
+    texture_rep (GLuint id_arg, int w_arg, int h_arg, int tw_arg, int th_arg)
+        : id (id_arg), w (w_arg), h (h_arg), tw (tw_arg), th (th_arg),
+          tx (double(w)/tw), ty (double(h)/th), valid (true),
+          count (1) { }
+
+    ~texture_rep (void)
+      {
+        if (valid)
+          glDeleteTextures (1, &id);
+      }
+
+    void bind (int mode) const
+      { if (valid) glBindTexture (mode, id); }
+
+    void tex_coord (double q, double r) const
+      { if (valid) glTexCoord2d (q*tx, r*ty); }
+
+    GLuint id;
+    int w, h;
+    int tw, th;
+    double tx, ty;
+    bool valid;
+    octave_refcount<int> count;
+  };
+
+  texture_rep *rep;
+
+private:
+  opengl_texture (texture_rep *_rep) : rep (_rep) { }
+
+public:
+  opengl_texture (void) : rep (new texture_rep ()) { }
+
+  opengl_texture (const opengl_texture& tx)
+      : rep (tx.rep)
+    {
+      rep->count++;
+    }
+
+  ~opengl_texture (void)
+    {
+      if (--rep->count == 0)
+        delete rep;
+    }
+
+  opengl_texture& operator = (const opengl_texture& tx)
+    {
+      if (--rep->count == 0)
+        delete rep;
+
+      rep = tx.rep;
+      rep->count++;
+
+      return *this;
+    }
+
+  static opengl_texture create (const octave_value& data);
+
+  void bind (int mode = GL_TEXTURE_2D) const
+    { rep->bind (mode); }
+
+  void tex_coord (double q, double r) const
+    { rep->tex_coord (q, r); }
+
+  bool is_valid (void) const
+    { return rep->valid; }
+};
+
+static int
+next_power_of_2 (int n)
+{
+  int m = 1;
+
+  while (m < n && m < INT_MAX)
+    m <<= 1;
+
+  return m;
+}
+
+opengl_texture
+opengl_texture::create (const octave_value& data)
+{
+  opengl_texture retval;
+
+  dim_vector dv (data.dims ());
+
+  // Expect RGB data
+  if (dv.length () == 3 && dv(2) == 3)
+    {
+      // FIXME -- dim_vectors hold octave_idx_type values.  Should we
+      // check for dimensions larger than intmax?
+      int h = dv(0), w = dv(1), tw, th;
+      GLuint id;
+      bool ok = true;
+
+      tw = next_power_of_2 (w);
+      th = next_power_of_2 (w);
+
+      glGenTextures (1, &id);
+      glBindTexture (GL_TEXTURE_2D, id);
+
+      if (data.is_double_type ())
+        {
+          const NDArray xdata = data.array_value ();
+
+          OCTAVE_LOCAL_BUFFER (float, a, (3*tw*th));
+
+          for (int i = 0; i < h; i++)
+            {
+              for (int j = 0, idx = i*tw*3; j < w; j++, idx += 3)
+                {
+                  a[idx]   = xdata(i,j,0);
+                  a[idx+1] = xdata(i,j,1);
+                  a[idx+2] = xdata(i,j,2);
+                }
+            }
+
+          glTexImage2D (GL_TEXTURE_2D, 0, 3, tw, th, 0,
+                        GL_RGB, GL_FLOAT, a);
+        }
+      else if (data.is_uint8_type ())
+        {
+          const uint8NDArray xdata = data.uint8_array_value ();
+
+          OCTAVE_LOCAL_BUFFER (octave_uint8, a, (3*tw*th));
+
+          for (int i = 0; i < h; i++)
+            {
+              for (int j = 0, idx = i*tw*3; j < w; j++, idx += 3)
+                {
+                  a[idx]   = xdata(i,j,0);
+                  a[idx+1] = xdata(i,j,1);
+                  a[idx+2] = xdata(i,j,2);
+                }
+            }
+
+          glTexImage2D (GL_TEXTURE_2D, 0, 3, tw, th, 0,
+                        GL_RGB, GL_UNSIGNED_BYTE, a);
+        }
+      else
+        {
+          ok = false;
+          warning ("opengl_texture::create: invalid texture data type (expected double or uint8)");
+        }
+
+      if (ok)
+        {
+          glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+          glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+          if (glGetError () != GL_NO_ERROR)
+            warning ("opengl_texture::create: OpenGL error while generating texture data");
+          else
+            retval = opengl_texture (new texture_rep (id, w, h, tw, th));
+        }
+    }
+  else
+    warning ("opengl_texture::create: invalid texture data size");
+
+  return retval;
+}
+
+class
+opengl_tesselator
+{
+public:
+#if defined (HAVE_FRAMEWORK_OPENGL) && defined (HAVE_GLUTESSCALLBACK_THREEDOTS)
+  typedef GLvoid (CALLBACK *fcn) (...);
+#else
+  typedef void (CALLBACK *fcn) (void);
+#endif
+
+public:
+
+  opengl_tesselator (void) : glu_tess (0), fill () { init (); }
+
+  virtual ~opengl_tesselator (void)
+    { if (glu_tess) gluDeleteTess (glu_tess); }
+
+  void begin_polygon (bool filled = true)
+    {
+      gluTessProperty (glu_tess, GLU_TESS_BOUNDARY_ONLY,
+                       (filled ? GL_FALSE : GL_TRUE));
+      fill = filled;
+      gluTessBeginPolygon (glu_tess, this);
+    }
+
+  void end_polygon (void) const
+    { gluTessEndPolygon (glu_tess); }
+
+  void begin_contour (void) const
+    { gluTessBeginContour (glu_tess); }
+
+  void end_contour (void) const
+    { gluTessEndContour (glu_tess); }
+
+  void add_vertex (double *loc, void *data) const
+    { gluTessVertex (glu_tess, loc, data); }
+
+protected:
+  virtual void begin (GLenum /*type*/) { }
+
+  virtual void end (void) { }
+
+  virtual void vertex (void */*data*/) { }
+
+  virtual void combine (GLdouble /*c*/[3], void */*data*/[4],
+                        GLfloat /*w*/[4], void **/*out_data*/) { }
+
+  virtual void edge_flag (GLboolean /*flag*/) { }
+
+  virtual void error (GLenum err)
+    { ::error ("OpenGL tesselation error (%d)", err); }
+
+  virtual void init (void)
+    {
+      glu_tess = gluNewTess ();
+
+      gluTessCallback (glu_tess, GLU_TESS_BEGIN_DATA,
+                       reinterpret_cast<fcn> (tess_begin));
+      gluTessCallback (glu_tess, GLU_TESS_END_DATA,
+                       reinterpret_cast<fcn> (tess_end));
+      gluTessCallback (glu_tess, GLU_TESS_VERTEX_DATA,
+                       reinterpret_cast<fcn> (tess_vertex));
+      gluTessCallback (glu_tess, GLU_TESS_COMBINE_DATA,
+                       reinterpret_cast<fcn> (tess_combine));
+      gluTessCallback (glu_tess, GLU_TESS_EDGE_FLAG_DATA,
+                       reinterpret_cast<fcn> (tess_edge_flag));
+      gluTessCallback (glu_tess, GLU_TESS_ERROR_DATA,
+                       reinterpret_cast<fcn> (tess_error));
+    }
+
+  bool is_filled (void) const { return fill; }
+
+private:
+  static void CALLBACK tess_begin (GLenum type, void *t)
+    { reinterpret_cast<opengl_tesselator *> (t)->begin (type); }
+
+  static void CALLBACK tess_end (void *t)
+    { reinterpret_cast<opengl_tesselator *> (t)->end (); }
+
+  static void CALLBACK tess_vertex (void *v, void *t)
+    { reinterpret_cast<opengl_tesselator *> (t)->vertex (v); }
+
+  static void CALLBACK tess_combine (GLdouble c[3], void *v[4], GLfloat w[4],
+                                     void **out,  void *t)
+    { reinterpret_cast<opengl_tesselator *> (t)->combine (c, v, w, out); }
+
+  static void CALLBACK tess_edge_flag (GLboolean flag, void *t)
+    { reinterpret_cast<opengl_tesselator *> (t)->edge_flag (flag); }
+
+  static void CALLBACK tess_error (GLenum err, void *t)
+    { reinterpret_cast<opengl_tesselator *> (t)->error (err); }
+
+private:
+
+  // No copying!
+
+  opengl_tesselator (const opengl_tesselator&);
+
+  opengl_tesselator operator = (const opengl_tesselator&);
+
+  GLUtesselator *glu_tess;
+  bool fill;
+};
+
+class
+vertex_data
+{
+public:
+  class vertex_data_rep
+  {
+  public:
+    Matrix coords;
+    Matrix color;
+    Matrix normal;
+    double alpha;
+    float ambient;
+    float diffuse;
+    float specular;
+    float specular_exp;
+
+    // reference counter
+    octave_refcount<int> count;
+
+    vertex_data_rep (void)
+      : coords (), color (), normal (), alpha (),
+        ambient (), diffuse (), specular (), specular_exp (),count (1) { }
+
+    vertex_data_rep (const Matrix& c, const Matrix& col, const Matrix& n,
+                     double a, float as, float ds, float ss, float se)
+        : coords (c), color (col), normal (n), alpha (a),
+          ambient (as), diffuse (ds), specular (ss), specular_exp (se),
+          count (1) { }
+  };
+
+private:
+  vertex_data_rep *rep;
+
+  vertex_data_rep *nil_rep (void) const
+    {
+      static vertex_data_rep *nr = new vertex_data_rep ();
+
+      return nr;
+    }
+
+public:
+  vertex_data (void) : rep (nil_rep ())
+    { rep->count++; }
+
+  vertex_data (const vertex_data& v) : rep (v.rep)
+    { rep->count++; }
+
+  vertex_data (const Matrix& c, const Matrix& col, const Matrix& n,
+               double a, float as, float ds, float ss, float se)
+      : rep (new vertex_data_rep (c, col, n, a, as, ds, ss, se))
+    { }
+
+  vertex_data (vertex_data_rep *new_rep)
+      : rep (new_rep) { }
+
+  ~vertex_data (void)
+    {
+      if (--rep->count == 0)
+        delete rep;
+    }
+
+  vertex_data& operator = (const vertex_data& v)
+    {
+      if (--rep->count == 0)
+        delete rep;
+
+      rep = v.rep;
+      rep->count++;
+
+      return *this;
+    }
+
+  vertex_data_rep *get_rep (void) const { return rep; }
+};
+
+class
+opengl_renderer::patch_tesselator : public opengl_tesselator
+{
+public:
+  patch_tesselator (opengl_renderer *r, int cmode, int lmode, int idx = 0)
+      : opengl_tesselator (), renderer (r),
+        color_mode (cmode), light_mode (lmode), index (idx),
+        first (true), tmp_vdata ()
+  { }
+
+protected:
+  void begin (GLenum type)
+    {
+      //printf ("patch_tesselator::begin (%d)\n", type);
+      first = true;
+
+      if (color_mode == 2 || light_mode == 2)
+        glShadeModel (GL_SMOOTH);
+      else
+        glShadeModel (GL_FLAT);
+
+      if (is_filled ())
+        renderer->set_polygon_offset (true, 1+index);
+
+      glBegin (type);
+    }
+
+  void end (void)
+    {
+      //printf ("patch_tesselator::end\n");
+      glEnd ();
+      renderer->set_polygon_offset (false);
+    }
+
+  void vertex (void *data)
+    {
+      vertex_data::vertex_data_rep *v
+          = reinterpret_cast<vertex_data::vertex_data_rep *> (data);
+      //printf ("patch_tesselator::vertex (%g, %g, %g)\n", v->coords(0), v->coords(1), v->coords(2));
+
+      // FIXME: why did I need to keep the first vertex of the face
+      // in JHandles? I think it's related to the fact that the
+      // tessellation process might re-order the vertices, such that
+      // the first one you get here might not be the first one of the face;
+      // but I can't figure out the actual reason.
+      if (color_mode > 0 && (first || color_mode == 2))
+        {
+          Matrix col = v->color;
+
+          if (col.numel () == 3)
+            {
+              glColor3dv (col.data ());
+              if (light_mode > 0)
+                {
+                  float buf[4] = { 0, 0, 0, 1 };
+
+                  for (int k = 0; k < 3; k++)
+                    buf[k] = (v->ambient * col(k));
+                  glMaterialfv (LIGHT_MODE, GL_AMBIENT, buf);
+
+                  for (int k = 0; k < 3; k++)
+                    buf[k] = (v->diffuse * col(k));
+                  glMaterialfv (LIGHT_MODE, GL_AMBIENT, buf);
+                }
+            }
+        }
+
+      if (light_mode > 0 && (first || light_mode == 2))
+        glNormal3dv (v->normal.data ());
+
+      glVertex3dv (v->coords.data ());
+
+      first = false;
+    }
+
+  void combine (GLdouble xyz[3], void *data[4], GLfloat w[4],
+                void **out_data)
+    {
+      //printf ("patch_tesselator::combine\n");
+
+      vertex_data::vertex_data_rep *v[4];
+      int vmax = 4;
+
+      for (int i = 0; i < 4; i++)
+        {
+          v[i] = reinterpret_cast<vertex_data::vertex_data_rep *> (data[i]);
+
+          if (vmax == 4 && ! v[i])
+            vmax = i;
+        }
+
+      Matrix vv (1, 3, 0.0);
+      Matrix cc;
+      Matrix nn (1, 3, 0.0);
+      double aa = 0.0;
+
+      vv(0) = xyz[0];
+      vv(1) = xyz[1];
+      vv(2) = xyz[2];
+
+      if (v[0]->color.numel ())
+        {
+          cc.resize (1, 3, 0.0);
+          for (int ic = 0; ic < 3; ic++)
+            for (int iv = 0; iv < vmax; iv++)
+              cc(ic) += (w[iv] * v[iv]->color (ic));
+        }
+
+      if (v[0]->normal.numel () > 0)
+        {
+          for (int in = 0; in < 3; in++)
+            for (int iv = 0; iv < vmax; iv++)
+              nn(in) += (w[iv] * v[iv]->normal (in));
+        }
+
+      for (int iv = 0; iv < vmax; iv++)
+        aa += (w[iv] * v[iv]->alpha);
+
+      vertex_data new_v (vv, cc, nn, aa, v[0]->ambient, v[0]->diffuse,
+                         v[0]->specular, v[0]->specular_exp);
+      tmp_vdata.push_back (new_v);
+
+      *out_data = new_v.get_rep ();
+    }
+
+private:
+
+  // No copying!
+
+  patch_tesselator (const patch_tesselator&);
+
+  patch_tesselator& operator = (const patch_tesselator&);
+
+  opengl_renderer *renderer;
+  int color_mode;       // 0: uni,  1: flat, 2: interp
+  int light_mode;       // 0: none, 1: flat, 2: gouraud
+  int index;
+  bool first;
+  std::list<vertex_data> tmp_vdata;
+};
+
+void
+opengl_renderer::draw (const graphics_object& go, bool toplevel)
+{
+  if (! go.valid_object ())
+    return;
+
+  const base_properties& props = go.get_properties ();
+
+  if (! toolkit)
+    toolkit = props.get_toolkit ();
+
+  if (go.isa ("figure"))
+    draw_figure (dynamic_cast<const figure::properties&> (props));
+  else if (go.isa ("axes"))
+    draw_axes (dynamic_cast<const axes::properties&> (props));
+  else if (go.isa ("line"))
+    draw_line (dynamic_cast<const line::properties&> (props));
+  else if (go.isa ("surface"))
+    draw_surface (dynamic_cast<const surface::properties&> (props));
+  else if (go.isa ("patch"))
+    draw_patch (dynamic_cast<const patch::properties&> (props));
+  else if (go.isa ("hggroup"))
+    draw_hggroup (dynamic_cast<const hggroup::properties&> (props));
+  else if (go.isa ("text"))
+    draw_text (dynamic_cast<const text::properties&> (props));
+  else if (go.isa ("image"))
+    draw_image (dynamic_cast<const image::properties&> (props));
+  else if (go.isa ("uimenu") || go.isa ("uicontrol")
+           || go.isa ("uicontextmenu") || go.isa ("uitoolbar")
+           || go.isa ("uipushtool") || go.isa ("uitoggletool"))
+    /* SKIP */;
+  else if (go.isa ("uipanel"))
+    {
+      if (toplevel)
+        draw_uipanel (dynamic_cast<const uipanel::properties&> (props), go);
+    }
+  else
+    {
+      warning ("opengl_renderer: cannot render object of type `%s'",
+               props.graphics_object_name ().c_str ());
+    }
+}
+
+void
+opengl_renderer::draw_figure (const figure::properties& props)
+{
+  // Initialize OpenGL context
+
+  init_gl_context (props.is___enhanced__ (), props.get_color_rgb ());
+
+  // Draw children
+
+  draw (props.get_all_children (), false);
+}
+
+void
+opengl_renderer::draw_uipanel (const uipanel::properties& props,
+                               const graphics_object& go)
+{
+  graphics_object fig = go.get_ancestor ("figure");
+  const figure::properties& figProps =
+    dynamic_cast<const figure::properties&> (fig.get_properties ());
+
+  // Initialize OpenGL context 
+
+  init_gl_context (figProps.is___enhanced__ (),
+                   props.get_backgroundcolor_rgb ());
+
+  // Draw children
+
+  draw (props.get_all_children (), false);
+}
+
+void
+opengl_renderer::init_gl_context (bool enhanced, const Matrix& c)
+{
+  // Initialize OpenGL context
+
+  glEnable (GL_DEPTH_TEST);
+  glDepthFunc (GL_LEQUAL);
+  glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+  glAlphaFunc (GL_GREATER, 0.0f);
+  glEnable (GL_NORMALIZE);
+
+  if (enhanced)
+    {
+      glEnable (GL_BLEND);
+      glEnable (GL_LINE_SMOOTH);
+    }
+  else
+    {
+      glDisable (GL_BLEND);
+      glDisable (GL_LINE_SMOOTH);
+    }
+
+  // Clear background
+
+  if (c.length () >= 3)
+    {
+      glClearColor (c(0), c(1), c(2), 1);
+      glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+    }
+}
+
+void
+opengl_renderer::render_grid (const std::string& gridstyle,
+                              const Matrix& ticks, double lim1, double lim2,
+                              double p1, double p1N, double p2, double p2N,
+                              int xyz, bool is_3D)
+{
+  set_linestyle (gridstyle, true);
+  glBegin (GL_LINES);
+  for (int i = 0; i < ticks.numel (); i++)
+    {
+      double val = ticks(i);
+      if (lim1 <= val && val <= lim2)
+        {
+          if (xyz == 0) // X
+            {
+              glVertex3d (val, p1N, p2);
+              glVertex3d (val, p1, p2);
+              if (is_3D)
+                {
+                  glVertex3d (val, p1, p2N);
+                  glVertex3d (val, p1, p2);
+                }
+            }
+          else if (xyz == 1) // Y
+            {
+              glVertex3d (p1N, val, p2);
+              glVertex3d (p1, val, p2);
+              if (is_3D)
+                {
+                  glVertex3d (p1, val, p2N);
+                  glVertex3d (p1, val, p2);
+                }
+            }
+          else if (xyz == 2) // Z
+            {
+              glVertex3d (p1N, p2, val);
+              glVertex3d (p1, p2, val);
+              glVertex3d (p1, p2N, val);
+              glVertex3d (p1, p2, val);
+            }
+        }
+    }
+  glEnd ();
+  set_linestyle ("-", true);
+}
+
+void
+opengl_renderer::render_tickmarks (const Matrix& ticks,
+                                   double lim1, double lim2,
+                                   double p1, double p1N,
+                                   double p2, double p2N,
+                                   double dx, double dy, double dz,
+                                   int xyz, bool mirror)
+{
+  glBegin (GL_LINES);
+
+  for (int i = 0; i < ticks.numel (); i++)
+    {
+      double val = ticks(i);
+
+      if (lim1 <= val && val <= lim2)
+        {
+          if (xyz == 0) // X
+            {
+              glVertex3d (val, p1, p2);
+              glVertex3d (val, p1+dy, p2+dz);
+              if (mirror)
+                {
+                  glVertex3d (val, p1N, p2N);
+                  glVertex3d (val, p1N-dy, p2N-dz);
+                }
+            }
+          else if (xyz == 1) // Y
+            {
+              glVertex3d (p1, val, p2);
+              glVertex3d (p1+dx, val, p2+dz);
+              if (mirror)
+                {
+                  glVertex3d (p1N, val, p2N);
+                  glVertex3d (p1N-dx, val, p2N-dz);
+                }
+            }
+          else if (xyz == 2) // Z
+            {
+              glVertex3d (p1, p2, val);
+              glVertex3d (p1+dx, p2+dy, val);
+              if (mirror)
+                {
+                  glVertex3d (p1N, p2N, val);
+                  glVertex3d (p1N-dx, p2N-dy, val);
+                }
+            }
+        }
+    }
+
+  glEnd ();
+}
+
+void
+opengl_renderer::render_ticktexts (const Matrix& ticks,
+                                   const string_vector& ticklabels,
+                                   double lim1, double lim2,
+                                   double p1, double p2,
+                                   int xyz, int ha, int va,
+                                   int& wmax, int& hmax)
+{
+  int n = std::min (ticklabels.numel (), ticks.numel ());
+
+  for (int i = 0; i < n; i++)
+    {
+      double val = ticks(i);
+
+      if (lim1 <= val && val <= lim2)
+        {
+          Matrix b;
+          // FIXME: as tick text is transparent, shouldn't be
+          //        drawn after axes object, for correct rendering?
+          if (xyz == 0) // X
+            {
+              b = render_text (ticklabels(i), val, p1, p2, ha, va);
+            }
+          else if (xyz == 1) // Y
+            {
+              b = render_text (ticklabels(i), p1, val, p2, ha, va);
+            }
+          else if (xyz == 2) // Z
+            {
+              b = render_text (ticklabels(i), p1, p2, val, ha, va);
+            }
+
+          wmax = std::max (wmax, static_cast<int> (b(2)));
+          hmax = std::max (hmax, static_cast<int> (b(3)));
+        }
+    }
+}
+
+void
+opengl_renderer::setup_opengl_transformation (const axes::properties& props)
+{
+  // setup OpenGL transformation
+
+  Matrix x_zlim = props.get_transform_zlim ();
+
+  xZ1 = x_zlim(0)-(x_zlim(1)-x_zlim(0))/2;
+  xZ2 = x_zlim(1)+(x_zlim(1)-x_zlim(0))/2;
+
+  Matrix x_mat1 = props.get_opengl_matrix_1 ();
+  Matrix x_mat2 = props.get_opengl_matrix_2 ();
+
+#if defined (HAVE_FRAMEWORK_OPENGL)
+  GLint vw[4];
+#else
+  int vw[4];
+#endif
+
+  glGetIntegerv (GL_VIEWPORT, vw);
+
+  glMatrixMode (GL_MODELVIEW);
+  glLoadIdentity ();
+  glScaled (1, 1, -1);
+  glMultMatrixd (x_mat1.data ());
+  glMatrixMode (GL_PROJECTION);
+  glLoadIdentity ();
+  glOrtho (0, vw[2], vw[3], 0, xZ1, xZ2);
+  glMultMatrixd (x_mat2.data ());
+  glMatrixMode (GL_MODELVIEW);
+
+  glClear (GL_DEPTH_BUFFER_BIT);
+
+  glDisable (GL_LINE_SMOOTH);
+
+  // store axes transformation data
+
+  xform = props.get_transform ();
+}
+
+void
+opengl_renderer::draw_axes_planes (const axes::properties& props)
+{
+  double xPlane = props.get_xPlane ();
+  double yPlane = props.get_yPlane ();
+  double zPlane = props.get_zPlane ();
+  double xPlaneN = props.get_xPlaneN ();
+  double yPlaneN = props.get_yPlaneN ();
+  double zPlaneN = props.get_zPlaneN ();
+
+  // Axes planes
+  Matrix axe_color = props.get_color_rgb ();
+  if (axe_color.numel () > 0 && props.is_visible ())
+    {
+      set_color (axe_color);
+      set_polygon_offset (true, 2.5);
+
+      glBegin (GL_QUADS);
+
+      // X plane
+      glVertex3d (xPlane, yPlaneN, zPlaneN);
+      glVertex3d (xPlane, yPlane, zPlaneN);
+      glVertex3d (xPlane, yPlane, zPlane);
+      glVertex3d (xPlane, yPlaneN, zPlane);
+
+      // Y plane
+      glVertex3d (xPlaneN, yPlane, zPlaneN);
+      glVertex3d (xPlane, yPlane, zPlaneN);
+      glVertex3d (xPlane, yPlane, zPlane);
+      glVertex3d (xPlaneN, yPlane, zPlane);
+
+      // Z plane
+      glVertex3d (xPlaneN, yPlaneN, zPlane);
+      glVertex3d (xPlane, yPlaneN, zPlane);
+      glVertex3d (xPlane, yPlane, zPlane);
+      glVertex3d (xPlaneN, yPlane, zPlane);
+
+      glEnd ();
+
+      set_polygon_offset (false);
+    }
+}
+
+void
+opengl_renderer::draw_axes_boxes (const axes::properties& props)
+{
+  bool xySym = props.get_xySym ();
+  double xPlane = props.get_xPlane ();
+  double yPlane = props.get_yPlane ();
+  double zPlane = props.get_zPlane ();
+  double xPlaneN = props.get_xPlaneN ();
+  double yPlaneN = props.get_yPlaneN ();
+  double zPlaneN = props.get_zPlaneN ();
+  double xpTick = props.get_xpTick ();
+  double ypTick = props.get_ypTick ();
+  double zpTick = props.get_zpTick ();
+  double xpTickN = props.get_xpTickN ();
+  double ypTickN = props.get_ypTickN ();
+  double zpTickN = props.get_zpTickN ();
+
+  bool plotyy = (props.has_property ("__plotyy_axes__"));
+
+  // Axes box
+
+  set_linestyle ("-", true);
+  set_linewidth (props.get_linewidth ());
+
+  if (props.is_visible ())
+    {
+      glBegin (GL_LINES);
+
+      // X box
+      set_color (props.get_xcolor_rgb ());
+      glVertex3d (xPlaneN, ypTick, zpTick);
+      glVertex3d (xPlane, ypTick, zpTick);
+
+      if (props.is_box ())
+        {
+          glVertex3d (xPlaneN, ypTickN, zpTick);
+          glVertex3d (xPlane, ypTickN, zpTick);
+          glVertex3d (xPlaneN, ypTickN, zpTickN);
+          glVertex3d (xPlane, ypTickN, zpTickN);
+          glVertex3d (xPlaneN, ypTick, zpTickN);
+          glVertex3d (xPlane, ypTick, zpTickN);
+        }
+
+      // Y box
+      set_color (props.get_ycolor_rgb ());
+      glVertex3d (xpTick, yPlaneN, zpTick);
+      glVertex3d (xpTick, yPlane, zpTick);
+
+      if (props.is_box () && ! plotyy)
+        {
+          glVertex3d (xpTickN, yPlaneN, zpTick);
+          glVertex3d (xpTickN, yPlane, zpTick);
+          glVertex3d (xpTickN, yPlaneN, zpTickN);
+          glVertex3d (xpTickN, yPlane, zpTickN);
+          glVertex3d (xpTick, yPlaneN, zpTickN);
+          glVertex3d (xpTick, yPlane, zpTickN);
+        }
+
+      // Z box
+      set_color (props.get_zcolor_rgb ());
+
+      if (xySym)
+        {
+          glVertex3d (xPlaneN, yPlane, zPlaneN);
+          glVertex3d (xPlaneN, yPlane, zPlane);
+        }
+      else
+        {
+          glVertex3d (xPlane, yPlaneN, zPlaneN);
+          glVertex3d (xPlane, yPlaneN, zPlane);
+        }
+
+      if (props.is_box ())
+        {
+          glVertex3d (xPlane, yPlane, zPlaneN);
+          glVertex3d (xPlane, yPlane, zPlane);
+
+          if (xySym)
+            {
+              glVertex3d (xPlane, yPlaneN, zPlaneN);
+              glVertex3d (xPlane, yPlaneN, zPlane);
+            }
+          else
+            {
+              glVertex3d (xPlaneN, yPlane, zPlaneN);
+              glVertex3d (xPlaneN, yPlane, zPlane);
+            }
+
+          glVertex3d (xPlaneN, yPlaneN, zPlaneN);
+          glVertex3d (xPlaneN, yPlaneN, zPlane);
+        }
+
+      glEnd ();
+    }
+}
+
+void
+opengl_renderer::draw_axes_x_grid (const axes::properties& props)
+{
+  int xstate = props.get_xstate ();
+  int zstate = props.get_zstate ();
+  bool x2Dtop = props.get_x2Dtop ();
+  bool layer2Dtop = props.get_layer2Dtop ();
+  bool xyzSym = props.get_xyzSym ();
+  bool nearhoriz = props.get_nearhoriz ();
+  double xticklen = props.get_xticklen ();
+  double xtickoffset = props.get_xtickoffset ();
+  double fy = props.get_fy ();
+  double fz = props.get_fz ();
+  double x_min = props.get_x_min ();
+  double x_max = props.get_x_max ();
+  double yPlane = props.get_yPlane ();
+  double yPlaneN = props.get_yPlaneN ();
+  double ypTick = props.get_ypTick ();
+  double ypTickN = props.get_ypTickN ();
+  double zPlane = props.get_zPlane ();
+  double zPlaneN = props.get_zPlaneN ();
+  double zpTick = props.get_zpTick ();
+  double zpTickN = props.get_zpTickN ();
+
+  // X grid
+
+  if (props.is_visible () && xstate != AXE_DEPTH_DIR)
+    {
+      std::string gridstyle = props.get_gridlinestyle ();
+      std::string minorgridstyle = props.get_minorgridlinestyle ();
+      bool do_xgrid = (props.is_xgrid () && (gridstyle != "none"));
+      bool do_xminorgrid = (props.is_xminorgrid () && (minorgridstyle != "none"));
+      bool do_xminortick = props.is_xminortick ();
+      Matrix xticks = xform.xscale (props.get_xtick ().matrix_value ());
+      Matrix xmticks = xform.xscale (props.get_xmtick ().matrix_value ());
+      string_vector xticklabels = props.get_xticklabel ().all_strings ();
+      int wmax = 0, hmax = 0;
+      bool tick_along_z = nearhoriz || xisinf (fy);
+      bool mirror = props.is_box () && xstate != AXE_ANY_DIR;
+
+      set_color (props.get_xcolor_rgb ());
+
+      // grid lines
+      if (do_xgrid)
+        render_grid (gridstyle, xticks, x_min, x_max,
+                     yPlane, yPlaneN, layer2Dtop ? zPlaneN : zPlane,
+                     zPlaneN, 0, (zstate != AXE_DEPTH_DIR));
+
+      // tick marks
+      if (tick_along_z)
+        {
+          render_tickmarks (xticks, x_min, x_max, ypTick, ypTick,
+                            zpTick, zpTickN, 0., 0.,
+                            signum (zpTick-zpTickN)*fz*xticklen,
+                            0, mirror);
+        }
+      else
+        {
+          render_tickmarks (xticks, x_min, x_max, ypTick, ypTickN,
+                            zpTick, zpTick, 0.,
+                            signum (ypTick-ypTickN)*fy*xticklen,
+                            0., 0, mirror);
+        }
+
+      // tick texts
+      if (xticklabels.numel () > 0)
+        {
+          int halign = (xstate == AXE_HORZ_DIR ? 1 : (xyzSym ? 0 : 2));
+          int valign = (xstate == AXE_VERT_DIR ? 1 : (x2Dtop ? 0 : 2));
+
+          if (tick_along_z)
+            render_ticktexts (xticks, xticklabels, x_min, x_max, ypTick,
+                              zpTick+signum (zpTick-zpTickN)*fz*xtickoffset,
+                              0, halign, valign, wmax, hmax);
+          else
+            render_ticktexts (xticks, xticklabels, x_min, x_max,
+                              ypTick+signum (ypTick-ypTickN)*fy*xtickoffset,
+                              zpTick, 0, halign, valign, wmax, hmax);
+        }
+
+      // minor grid lines
+      if (do_xminorgrid)
+        render_grid (minorgridstyle, xmticks, x_min, x_max,
+                     yPlane, yPlaneN, layer2Dtop ? zPlaneN : zPlane,
+                     zPlaneN, 0, (zstate != AXE_DEPTH_DIR));
+
+      // minor tick marks
+      if (do_xminortick)
+        {
+          if (tick_along_z)
+            render_tickmarks (xmticks, x_min, x_max, ypTick, ypTick,
+                              zpTick, zpTickN, 0., 0.,
+                              signum (zpTick-zpTickN)*fz*xticklen/2,
+                              0, mirror);
+          else
+            render_tickmarks (xmticks, x_min, x_max, ypTick, ypTickN,
+                              zpTick, zpTick, 0.,
+                              signum (ypTick-ypTickN)*fy*xticklen/2,
+                              0., 0, mirror);
+        }
+
+      gh_manager::get_object (props.get_xlabel ()).set ("visible", "on");
+    }
+  else
+    gh_manager::get_object (props.get_xlabel ()).set ("visible", "off");
+}
+
+void
+opengl_renderer::draw_axes_y_grid (const axes::properties& props)
+{
+  int ystate = props.get_ystate ();
+  int zstate = props.get_zstate ();
+  bool y2Dright = props.get_y2Dright ();
+  bool layer2Dtop = props.get_layer2Dtop ();
+  bool xyzSym = props.get_xyzSym ();
+  bool nearhoriz = props.get_nearhoriz ();
+  double yticklen = props.get_yticklen ();
+  double ytickoffset = props.get_ytickoffset ();
+  double fx = props.get_fx ();
+  double fz = props.get_fz ();
+  double xPlane = props.get_xPlane ();
+  double xPlaneN = props.get_xPlaneN ();
+  double xpTick = props.get_xpTick ();
+  double xpTickN = props.get_xpTickN ();
+  double y_min = props.get_y_min ();
+  double y_max = props.get_y_max ();
+  double zPlane = props.get_zPlane ();
+  double zPlaneN = props.get_zPlaneN ();
+  double zpTick = props.get_zpTick ();
+  double zpTickN = props.get_zpTickN ();
+
+  // Y grid
+
+  if (ystate != AXE_DEPTH_DIR && props.is_visible ())
+    {
+      std::string gridstyle = props.get_gridlinestyle ();
+      std::string minorgridstyle = props.get_minorgridlinestyle ();
+      bool do_ygrid = (props.is_ygrid () && (gridstyle != "none"));
+      bool do_yminorgrid = (props.is_yminorgrid () && (minorgridstyle != "none"));
+      bool do_yminortick = props.is_yminortick ();
+      Matrix yticks = xform.yscale (props.get_ytick ().matrix_value ());
+      Matrix ymticks = xform.yscale (props.get_ymtick ().matrix_value ());
+      string_vector yticklabels = props.get_yticklabel ().all_strings ();
+      int wmax = 0, hmax = 0;
+      bool tick_along_z = nearhoriz || xisinf (fx);
+      bool mirror = props.is_box () && ystate != AXE_ANY_DIR
+                    && (! props.has_property ("__plotyy_axes__"));
+
+      set_color (props.get_ycolor_rgb ());
+
+      // grid lines
+      if (do_ygrid)
+        render_grid (gridstyle, yticks, y_min, y_max,
+                     xPlane, xPlaneN, layer2Dtop ? zPlaneN : zPlane,
+                     zPlaneN, 1, (zstate != AXE_DEPTH_DIR));
+
+      // tick marks
+      if (tick_along_z)
+        render_tickmarks (yticks, y_min, y_max, xpTick, xpTick,
+                          zpTick, zpTickN, 0., 0.,
+                          signum (zpTick-zpTickN)*fz*yticklen,
+                          1, mirror);
+      else
+        render_tickmarks (yticks, y_min, y_max, xpTick, xpTickN,
+                          zpTick, zpTick,
+                          signum (xPlaneN-xPlane)*fx*yticklen,
+                          0., 0., 1, mirror);
+
+      // tick texts
+      if (yticklabels.numel () > 0)
+        {
+          int halign = (ystate == AXE_HORZ_DIR
+                        ? 1 : (!xyzSym || y2Dright ? 0 : 2));
+          int valign = (ystate == AXE_VERT_DIR ? 1 : 2);
+
+          if (tick_along_z)
+            render_ticktexts (yticks, yticklabels, y_min, y_max, xpTick,
+                              zpTick+signum (zpTick-zpTickN)*fz*ytickoffset,
+                              1, halign, valign, wmax, hmax);
+          else
+            render_ticktexts (yticks, yticklabels, y_min, y_max,
+                              xpTick+signum (xpTick-xpTickN)*fx*ytickoffset,
+                              zpTick, 1, halign, valign, wmax, hmax);
+        }
+
+      // minor grid lines
+      if (do_yminorgrid)
+        render_grid (minorgridstyle, ymticks, y_min, y_max,
+                     xPlane, xPlaneN, layer2Dtop ? zPlaneN : zPlane,
+                     zPlaneN, 1, (zstate != AXE_DEPTH_DIR));
+
+      // minor tick marks
+      if (do_yminortick)
+        {
+          if (tick_along_z)
+            render_tickmarks (ymticks, y_min, y_max, xpTick, xpTick,
+                              zpTick, zpTickN, 0., 0.,
+                              signum (zpTick-zpTickN)*fz*yticklen/2,
+                              1, mirror);
+          else
+            render_tickmarks (ymticks, y_min, y_max, xpTick, xpTickN,
+                              zpTick, zpTick,
+                              signum (xpTick-xpTickN)*fx*yticklen/2,
+                              0., 0., 1, mirror);
+        }
+
+      gh_manager::get_object (props.get_ylabel ()).set ("visible", "on");
+    }
+  else
+    gh_manager::get_object (props.get_ylabel ()).set ("visible", "off");
+}
+
+void
+opengl_renderer::draw_axes_z_grid (const axes::properties& props)
+{
+  int zstate = props.get_zstate ();
+  bool xySym = props.get_xySym ();
+  bool zSign = props.get_zSign ();
+  double zticklen = props.get_zticklen ();
+  double ztickoffset = props.get_ztickoffset ();
+  double fx = props.get_fx ();
+  double fy = props.get_fy ();
+  double xPlane = props.get_xPlane ();
+  double xPlaneN = props.get_xPlaneN ();
+  double yPlane = props.get_yPlane ();
+  double yPlaneN = props.get_yPlaneN ();
+  double z_min = props.get_z_min ();
+  double z_max = props.get_z_max ();
+
+  // Z Grid
+
+  if (zstate != AXE_DEPTH_DIR && props.is_visible ())
+    {
+      std::string gridstyle = props.get_gridlinestyle ();
+      std::string minorgridstyle = props.get_minorgridlinestyle ();
+      bool do_zgrid = (props.is_zgrid () && (gridstyle != "none"));
+      bool do_zminorgrid = (props.is_zminorgrid () && (minorgridstyle != "none"));
+      bool do_zminortick = props.is_zminortick ();
+      Matrix zticks = xform.zscale (props.get_ztick ().matrix_value ());
+      Matrix zmticks = xform.zscale (props.get_zmtick ().matrix_value ());
+      string_vector zticklabels = props.get_zticklabel ().all_strings ();
+      int wmax = 0, hmax = 0;
+      bool mirror = props.is_box () && zstate != AXE_ANY_DIR;
+
+      set_color (props.get_zcolor_rgb ());
+
+      // grid lines
+      if (do_zgrid)
+        render_grid (gridstyle, zticks, z_min, z_max,
+                     xPlane, xPlaneN, yPlane, yPlaneN, 2, true);
+
+      // tick marks
+      if (xySym)
+        {
+          if (xisinf (fy))
+            render_tickmarks (zticks, z_min, z_max, xPlaneN, xPlane,
+                              yPlane, yPlane,
+                              signum (xPlaneN-xPlane)*fx*zticklen,
+                              0., 0., 2, mirror);
+          else
+            render_tickmarks (zticks, z_min, z_max, xPlaneN, xPlaneN,
+                              yPlane, yPlane, 0.,
+                              signum (yPlane-yPlaneN)*fy*zticklen,
+                              0., 2, false);
+        }
+      else
+        {
+          if (xisinf (fx))
+            render_tickmarks (zticks, z_min, z_max, xPlaneN, xPlane,
+                              yPlaneN, yPlane, 0.,
+                              signum (yPlaneN-yPlane)*fy*zticklen,
+                              0., 2, mirror);
+          else
+            render_tickmarks (zticks, z_min, z_max, xPlane, xPlane,
+                              yPlaneN, yPlane,
+                              signum (xPlane-xPlaneN)*fx*zticklen,
+                              0., 0., 2, false);
+        }
+
+      // FIXME: tick texts
+      if (zticklabels.numel () > 0)
+        {
+          int halign = 2;
+          int valign = (zstate == AXE_VERT_DIR ? 1 : (zSign ? 3 : 2));
+
+          if (xySym)
+            {
+              if (xisinf (fy))
+                render_ticktexts (zticks, zticklabels, z_min, z_max,
+                                  xPlaneN+signum (xPlaneN-xPlane)*fx*ztickoffset,
+                                  yPlane, 2, halign, valign, wmax, hmax);
+              else
+                render_ticktexts (zticks, zticklabels, z_min, z_max, xPlaneN,
+                                  yPlane+signum (yPlane-yPlaneN)*fy*ztickoffset,
+                                  2, halign, valign, wmax, hmax);
+            }
+          else
+            {
+              if (xisinf (fx))
+                render_ticktexts (zticks, zticklabels, z_min, z_max, xPlane,
+                                  yPlaneN+signum (yPlaneN-yPlane)*fy*ztickoffset,
+                                  2, halign, valign, wmax, hmax);
+              else
+                render_ticktexts (zticks, zticklabels, z_min, z_max,
+                                  xPlane+signum (xPlane-xPlaneN)*fx*ztickoffset,
+                                  yPlaneN, 2, halign, valign, wmax, hmax);
+            }
+        }
+
+      // minor grid lines
+      if (do_zminorgrid)
+        render_grid (minorgridstyle, zmticks, z_min, z_max,
+                     xPlane, xPlaneN, yPlane, yPlaneN, 2, true);
+
+      // minor tick marks
+      if (do_zminortick)
+        {
+          if (xySym)
+            {
+              if (xisinf (fy))
+                render_tickmarks (zmticks, z_min, z_max, xPlaneN, xPlane,
+                                  yPlane, yPlane,
+                                  signum (xPlaneN-xPlane)*fx*zticklen/2,
+                                  0., 0., 2, mirror);
+              else
+                render_tickmarks (zmticks, z_min, z_max, xPlaneN, xPlaneN,
+                                  yPlane, yPlane, 0.,
+                                  signum (yPlane-yPlaneN)*fy*zticklen/2,
+                                  0., 2, false);
+            }
+          else
+            {
+              if (xisinf (fx))
+                render_tickmarks (zmticks, z_min, z_max, xPlane, xPlane,
+                                  yPlaneN, yPlane, 0.,
+                                  signum (yPlaneN-yPlane)*fy*zticklen/2,
+                                  0., 2, mirror);
+              else
+                render_tickmarks (zmticks, z_min, z_max, xPlane, xPlane,
+                                  yPlaneN, yPlaneN,
+                                  signum (xPlane-xPlaneN)*fx*zticklen/2,
+                                  0., 0., 2, false);
+            }
+        }
+
+      gh_manager::get_object (props.get_zlabel ()).set ("visible", "on");
+    }
+  else
+    gh_manager::get_object (props.get_zlabel ()).set ("visible", "off");
+}
+
+void
+opengl_renderer::draw_axes_children (const axes::properties& props)
+{
+  // Children
+
+  GLboolean antialias;
+  glGetBooleanv (GL_LINE_SMOOTH, &antialias);
+
+  if (antialias == GL_TRUE)
+    glEnable (GL_LINE_SMOOTH);
+
+  Matrix children = props.get_all_children ();
+  std::list<graphics_object> obj_list;
+  std::list<graphics_object>::iterator it;
+
+  // 1st pass: draw light objects
+
+  // Start with the last element of the array of child objects to
+  // display them in the oder they were added to the array.
+
+  for (octave_idx_type i = children.numel () - 1; i >= 0; i--)
+    {
+      graphics_object go = gh_manager::get_object (children (i));
+
+      if (go.get_properties ().is_visible ())
+        {
+          if (go.isa ("light"))
+            draw (go);
+          else
+            obj_list.push_back (go);
+        }
+    }
+
+  // 2nd pass: draw other objects (with units set to "data")
+
+  it = obj_list.begin ();
+  while (it != obj_list.end ())
+    {
+      graphics_object go = (*it);
+
+      // FIXME: check whether object has "units" property and it is set
+      // to "data"
+      if (! go.isa ("text") || go.get ("units").string_value () == "data")
+        {
+          set_clipping (go.get_properties ().is_clipping ());
+          draw (go);
+
+          it = obj_list.erase (it);
+        }
+      else
+        it++;
+    }
+
+  // 3rd pass: draw remaining objects
+
+  glDisable (GL_DEPTH_TEST);
+
+  for (it = obj_list.begin (); it != obj_list.end (); it++)
+    {
+      graphics_object go = (*it);
+
+      set_clipping (go.get_properties ().is_clipping ());
+      draw (go);
+    }
+
+  glEnable (GL_DEPTH_TEST);
+
+  set_clipping (false);
+
+  // FIXME: finalize rendering (transparency processing)
+  // FIXME: draw zoom box, if needed
+}
+
+void
+opengl_renderer::draw_axes (const axes::properties& props)
+{
+  double x_min = props.get_x_min ();
+  double x_max = props.get_x_max ();
+  double y_min = props.get_y_min ();
+  double y_max = props.get_y_max ();
+  double z_min = props.get_z_min ();
+  double z_max = props.get_z_max ();
+
+  setup_opengl_transformation (props);
+
+  // draw axes object
+
+  draw_axes_planes (props);
+  draw_axes_boxes (props);
+
+  set_font (props);
+
+  draw_axes_x_grid (props);
+  draw_axes_y_grid (props);
+  draw_axes_z_grid (props);
+
+  set_linestyle ("-");
+
+  set_clipbox (x_min, x_max, y_min, y_max, z_min, z_max);
+
+  draw_axes_children (props);
+}
+
+void
+opengl_renderer::draw_line (const line::properties& props)
+{
+  Matrix x = xform.xscale (props.get_xdata ().matrix_value ());
+  Matrix y = xform.yscale (props.get_ydata ().matrix_value ());
+  Matrix z = xform.zscale (props.get_zdata ().matrix_value ());
+
+  bool has_z = (z.numel () > 0);
+  int n = static_cast<int> (::xmin (::xmin (x.numel (), y.numel ()), (has_z ? z.numel () : INT_MAX)));
+  octave_uint8 clip_mask = (props.is_clipping () ? 0x7F : 0x40), clip_ok (0x40);
+
+  std::vector<octave_uint8> clip (n);
+
+  if (has_z)
+    for (int i = 0; i < n; i++)
+      clip[i] = (clip_code (x(i), y(i), z(i)) & clip_mask);
+  else
+    {
+      double z_mid = (zmin+zmax)/2;
+
+      for (int i = 0; i < n; i++)
+        clip[i] = (clip_code (x(i), y(i), z_mid) & clip_mask);
+    }
+
+  if (! props.linestyle_is ("none"))
+    {
+      set_color (props.get_color_rgb ());
+      set_linestyle (props.get_linestyle (), false);
+      set_linewidth (props.get_linewidth ());
+
+      if (has_z)
+        {
+          bool flag = false;
+
+          for (int i = 1; i < n; i++)
+            {
+              if ((clip[i-1] & clip[i]) == clip_ok)
+                {
+                  if (! flag)
+                    {
+                      flag = true;
+                      glBegin (GL_LINE_STRIP);
+                      glVertex3d (x(i-1), y(i-1), z(i-1));
+                    }
+                  glVertex3d (x(i), y(i), z(i));
+                }
+              else if (flag)
+                {
+                  flag = false;
+                  glEnd ();
+                }
+            }
+
+          if (flag)
+            glEnd ();
+        }
+      else
+        {
+          bool flag = false;
+
+          for (int i = 1; i < n; i++)
+            {
+              if ((clip[i-1] & clip[i]) == clip_ok)
+                {
+                  if (! flag)
+                    {
+                      flag = true;
+                      glBegin (GL_LINE_STRIP);
+                      glVertex2d (x(i-1), y(i-1));
+                    }
+                  glVertex2d (x(i), y(i));
+                }
+              else if (flag)
+                {
+                  flag = false;
+                  glEnd ();
+                }
+            }
+
+          if (flag)
+            glEnd ();
+        }
+
+      set_linewidth (0.5);
+      set_linestyle ("-");
+    }
+
+  set_clipping (false);
+
+  if (! props.marker_is ("none") &&
+      ! (props.markeredgecolor_is ("none")
+         && props.markerfacecolor_is ("none")))
+    {
+      Matrix lc, fc;
+
+      if (props.markeredgecolor_is ("auto"))
+        lc = props.get_color_rgb ();
+      else if (! props.markeredgecolor_is ("none"))
+        lc = props.get_markeredgecolor_rgb ();
+
+      if (props.markerfacecolor_is ("auto"))
+        fc = props.get_color_rgb ();
+      else if (! props.markerfacecolor_is ("none"))
+        fc = props.get_markerfacecolor_rgb ();
+
+      init_marker (props.get_marker (), props.get_markersize (),
+                   props.get_linewidth ());
+
+      for (int i = 0; i < n; i++)
+        {
+          if (clip[i] == clip_ok)
+            draw_marker (x(i), y(i),
+                         has_z ? z(i) : static_cast<double> (i) / n,
+                         lc, fc);
+        }
+
+      end_marker ();
+    }
+
+  set_clipping (props.is_clipping ());
+}
+
+void
+opengl_renderer::draw_surface (const surface::properties& props)
+{
+  const Matrix x = xform.xscale (props.get_xdata ().matrix_value ());
+  const Matrix y = xform.yscale (props.get_ydata ().matrix_value ());
+  const Matrix z = xform.zscale (props.get_zdata ().matrix_value ());
+
+  int zr = z.rows (), zc = z.columns ();
+
+  NDArray c;
+  const NDArray n = props.get_vertexnormals ().array_value ();
+
+  // FIXME: handle transparency
+  Matrix a;
+
+  if (props.facelighting_is ("phong") || props.edgelighting_is ("phong"))
+    warning ("opengl_renderer::draw: phong light model not supported");
+
+  int fc_mode = (props.facecolor_is_rgb () ? 0 :
+                 (props.facecolor_is ("flat") ? 1 :
+                  (props.facecolor_is ("interp") ? 2 :
+                   (props.facecolor_is ("texturemap") ? 3 : -1))));
+  int fl_mode = (props.facelighting_is ("none") ? 0 :
+                 (props.facelighting_is ("flat") ? 1 : 2));
+  int fa_mode = (props.facealpha_is_double () ? 0 :
+                 (props.facealpha_is ("flat") ? 1 : 2));
+  int ec_mode = (props.edgecolor_is_rgb () ? 0 :
+                 (props.edgecolor_is ("flat") ? 1 :
+                  (props.edgecolor_is ("interp") ? 2 : -1)));
+  int el_mode = (props.edgelighting_is ("none") ? 0 :
+                 (props.edgelighting_is ("flat") ? 1 : 2));
+  int ea_mode = (props.edgealpha_is_double () ? 0 :
+                 (props.edgealpha_is ("flat") ? 1 : 2));
+
+  Matrix fcolor = (fc_mode == 3 ? Matrix (1, 3, 1.0) : props.get_facecolor_rgb ());
+  Matrix ecolor = props.get_edgecolor_rgb ();
+
+  float as = props.get_ambientstrength ();
+  float ds = props.get_diffusestrength ();
+  float ss = props.get_specularstrength ();
+  float se = props.get_specularexponent ();
+  float cb[4] = { 0.0, 0.0, 0.0, 1.0 };
+  double d = 1.0;
+
+  opengl_texture tex;
+
+  int i1, i2, j1, j2;
+  bool x_mat = (x.rows () == z.rows ());
+  bool y_mat = (y.columns () == z.columns ());
+
+  i1 = i2 = j1 = j2 = 0;
+
+  boolMatrix clip (z.dims (), false);
+
+  for (int i = 0; i < zr; i++)
+    {
+      if (x_mat)
+        i1 = i;
+
+      for (int j = 0; j < zc; j++)
+        {
+          if (y_mat)
+            j1 = j;
+
+          clip(i,j) = is_nan_or_inf (x(i1,j), y(i,j1), z(i,j));
+        }
+    }
+
+  if ((fc_mode > 0 && fc_mode < 3) || ec_mode > 0)
+    c = props.get_color_data ().array_value ();
+
+  if (fa_mode > 0 || ea_mode > 0)
+    {
+      // FIXME: implement alphadata conversion
+      //a = props.get_alpha_data ();
+    }
+
+  if (fl_mode > 0 || el_mode > 0)
+    {
+      float buf[4] = { ss, ss, ss, 1 };
+
+      glMaterialfv (LIGHT_MODE, GL_SPECULAR, buf);
+      glMaterialf (LIGHT_MODE, GL_SHININESS, se);
+    }
+
+  // FIXME: good candidate for caching, transfering pixel
+  // data to OpenGL is time consuming.
+  if (fc_mode == 3)
+    tex = opengl_texture::create (props.get_color_data ());
+
+  if (! props.facecolor_is ("none"))
+    {
+      if (props.get_facealpha_double () == 1)
+        {
+          if (fc_mode == 0 || fc_mode == 3)
+            {
+              glColor3dv (fcolor.data ());
+              if (fl_mode > 0)
+                {
+                  for (int i = 0; i < 3; i++)
+                    cb[i] = as * fcolor(i);
+                  glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
+
+                  for (int i = 0; i < 3; i++)
+                    cb[i] = ds * fcolor(i);
+                  glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
+                }
+            }
+
+          if (fl_mode > 0)
+            glEnable (GL_LIGHTING);
+          glShadeModel ((fc_mode == 2 || fl_mode == 2) ? GL_SMOOTH : GL_FLAT);
+          set_polygon_offset (true, 1);
+          if (fc_mode == 3)
+            glEnable (GL_TEXTURE_2D);
+
+          for (int i = 1; i < zc; i++)
+            {
+              if (y_mat)
+                {
+                  i1 = i-1;
+                  i2 = i;
+                }
+
+              for (int j = 1; j < zr; j++)
+                {
+                  if (clip(j-1, i-1) || clip (j, i-1)
+                      || clip (j-1, i) || clip (j, i))
+                    continue;
+
+                  if (x_mat)
+                    {
+                      j1 = j-1;
+                      j2 = j;
+                    }
+
+                  glBegin (GL_QUADS);
+
+                  // Vertex 1
+                  if (fc_mode == 3)
+                    tex.tex_coord (double (i-1) / (zc-1), double (j-1) / (zr-1));
+                  else if (fc_mode > 0)
+                    {
+                      // FIXME: is there a smarter way to do this?
+                      for (int k = 0; k < 3; k++)
+                        cb[k] = c(j-1, i-1, k);
+                      glColor3fv (cb);
+
+                      if (fl_mode > 0)
+                        {
+                          for (int k = 0; k < 3; k++)
+                            cb[k] *= as;
+                          glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
+
+                          for (int k = 0; k < 3; k++)
+                            cb[k] = ds * c(j-1, i-1, k);
+                          glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
+                        }
+                    }
+                  if (fl_mode > 0)
+                    {
+                      d = sqrt (n(j-1,i-1,0) * n(j-1,i-1,0)
+                                + n(j-1,i-1,1) * n(j-1,i-1,1)
+                                + n(j-1,i-1,2) * n(j-1,i-1,2));
+                      glNormal3d (n(j-1,i-1,0)/d, n(j-1,i-1,1)/d, n(j-1,i-1,2)/d);
+                    }
+                  glVertex3d (x(j1,i-1), y(j-1,i1), z(j-1,i-1));
+
+                  // Vertex 2
+                  if (fc_mode == 3)
+                    tex.tex_coord (double (i) / (zc-1), double (j-1) / (zr-1));
+                  else if (fc_mode == 2)
+                    {
+                      for (int k = 0; k < 3; k++)
+                        cb[k] = c(j-1, i, k);
+                      glColor3fv (cb);
+
+                      if (fl_mode > 0)
+                        {
+                          for (int k = 0; k < 3; k++)
+                            cb[k] *= as;
+                          glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
+
+                          for (int k = 0; k < 3; k++)
+                            cb[k] = ds * c(j-1, i, k);
+                          glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
+                        }
+                    }
+
+                  if (fl_mode == 2)
+                    {
+                      d = sqrt (n(j-1,i,0) * n(j-1,i,0)
+                                + n(j-1,i,1) * n(j-1,i,1)
+                                + n(j-1,i,2) * n(j-1,i,2));
+                      glNormal3d (n(j-1,i,0)/d, n(j-1,i,1)/d, n(j-1,i,2)/d);
+                    }
+
+                  glVertex3d (x(j1,i), y(j-1,i2), z(j-1,i));
+
+                  // Vertex 3
+                  if (fc_mode == 3)
+                    tex.tex_coord (double (i) / (zc-1), double (j) / (zr-1));
+                  else if (fc_mode == 2)
+                    {
+                      for (int k = 0; k < 3; k++)
+                        cb[k] = c(j, i, k);
+                      glColor3fv (cb);
+
+                      if (fl_mode > 0)
+                        {
+                          for (int k = 0; k < 3; k++)
+                            cb[k] *= as;
+                          glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
+
+                          for (int k = 0; k < 3; k++)
+                            cb[k] = ds * c(j, i, k);
+                          glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
+                        }
+                    }
+                  if (fl_mode == 2)
+                    {
+                      d = sqrt (n(j,i,0) * n(j,i,0)
+                                + n(j,i,1) * n(j,i,1)
+                                + n(j,i,2) * n(j,i,2));
+                      glNormal3d (n(j,i,0)/d, n(j,i,1)/d, n(j,i,2)/d);
+                    }
+                  glVertex3d (x(j2,i), y(j,i2), z(j,i));
+
+                  // Vertex 4
+                  if (fc_mode == 3)
+                    tex.tex_coord (double (i-1) / (zc-1), double (j) / (zr-1));
+                  else if (fc_mode == 2)
+                    {
+                      for (int k = 0; k < 3; k++)
+                        cb[k] = c(j, i-1, k);
+                      glColor3fv (cb);
+
+                      if (fl_mode > 0)
+                        {
+                          for (int k = 0; k < 3; k++)
+                            cb[k] *= as;
+                          glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
+
+                          for (int k = 0; k < 3; k++)
+                            cb[k] = ds * c(j, i-1, k);
+                          glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
+                        }
+                    }
+                  if (fl_mode == 2)
+                    {
+                      d = sqrt (n(j,i-1,0) * n(j,i-1,0)
+                                + n(j,i-1,1) * n(j,i-1,1)
+                                + n(j,i-1,2) * n(j,i-1,2));
+                      glNormal3d (n(j,i-1,0)/d, n(j,i-1,1)/d, n(j,i-1,2)/d);
+                    }
+                  glVertex3d (x(j2,i-1), y(j,i1), z(j,i-1));
+
+                  glEnd ();
+                }
+            }
+
+          set_polygon_offset (false);
+          if (fc_mode == 3)
+            glDisable (GL_TEXTURE_2D);
+
+          if (fl_mode > 0)
+            glDisable (GL_LIGHTING);
+        }
+      else
+        {
+          // FIXME: implement transparency
+        }
+    }
+
+  if (! props.edgecolor_is ("none"))
+    {
+      if (props.get_edgealpha_double () == 1)
+        {
+          if (ec_mode == 0)
+            {
+              glColor3dv (ecolor.data ());
+              if (fl_mode > 0)
+                {
+                  for (int i = 0; i < 3; i++)
+                    cb[i] = as * ecolor(i);
+                  glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
+
+                  for (int i = 0; i < 3; i++)
+                    cb[i] = ds * ecolor(i);
+                  glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
+                }
+            }
+
+          if (el_mode > 0)
+            glEnable (GL_LIGHTING);
+          glShadeModel ((ec_mode == 2 || el_mode == 2) ? GL_SMOOTH : GL_FLAT);
+
+          set_linestyle (props.get_linestyle (), false);
+          set_linewidth (props.get_linewidth ());
+
+          // Mesh along Y-axis
+
+          if (props.meshstyle_is ("both") || props.meshstyle_is ("column"))
+            {
+              for (int i = 0; i < zc; i++)
+                {
+                  if (y_mat)
+                    {
+                      i1 = i-1;
+                      i2 = i;
+                    }
+
+                  for (int j = 1; j < zr; j++)
+                    {
+                      if (clip(j-1,i) || clip(j,i))
+                        continue;
+
+                      if (x_mat)
+                        {
+                          j1 = j-1;
+                          j2 = j;
+                        }
+
+                      glBegin (GL_LINES);
+
+                      // Vertex 1
+                      if (ec_mode > 0)
+                        {
+                          for (int k = 0; k < 3; k++)
+                            cb[k] = c(j-1, i, k);
+                          glColor3fv (cb);
+
+                          if (fl_mode > 0)
+                            {
+                              for (int k = 0; k < 3; k++)
+                                cb[k] *= as;
+                              glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
+
+                              for (int k = 0; k < 3; k++)
+                                cb[k] = ds * c(j-1, i, k);
+                              glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
+                            }
+                        }
+                      if (el_mode > 0)
+                        {
+                          d = sqrt (n(j-1,i,0) * n(j-1,i,0)
+                                    + n(j-1,i,1) * n(j-1,i,1)
+                                    + n(j-1,i,2) * n(j-1,i,2));
+                          glNormal3d (n(j-1,i,0)/d, n(j-1,i,1)/d, n(j-1,i,2)/d);
+                        }
+                      glVertex3d (x(j1,i), y(j-1,i2), z(j-1,i));
+
+                      // Vertex 2
+                      if (ec_mode == 2)
+                        {
+                          for (int k = 0; k < 3; k++)
+                            cb[k] = c(j, i, k);
+                          glColor3fv (cb);
+
+                          if (fl_mode > 0)
+                            {
+                              for (int k = 0; k < 3; k++)
+                                cb[k] *= as;
+                              glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
+
+                              for (int k = 0; k < 3; k++)
+                                cb[k] = ds * c(j, i, k);
+                              glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
+                            }
+                        }
+                      if (el_mode == 2)
+                        {
+                          d = sqrt (n(j,i,0) * n(j,i,0)
+                                    + n(j,i,1) * n(j,i,1)
+                                    + n(j,i,2) * n(j,i,2));
+                          glNormal3d (n(j,i,0)/d, n(j,i,1)/d, n(j,i,2)/d);
+                        }
+                      glVertex3d (x(j2,i), y(j,i2), z(j,i));
+
+                      glEnd ();
+                    }
+                }
+            }
+
+          // Mesh along X-axis
+
+          if (props.meshstyle_is ("both") || props.meshstyle_is ("row"))
+            {
+              for (int j = 0; j < zr; j++)
+                {
+                  if (x_mat)
+                    {
+                      j1 = j-1;
+                      j2 = j;
+                    }
+
+                  for (int i = 1; i < zc; i++)
+                    {
+                      if (clip(j,i-1) || clip(j,i))
+                        continue;
+
+                      if (y_mat)
+                        {
+                          i1 = i-1;
+                          i2 = i;
+                        }
+
+                      glBegin (GL_LINES);
+
+                      // Vertex 1
+                      if (ec_mode > 0)
+                        {
+                          for (int k = 0; k < 3; k++)
+                            cb[k] = c(j, i-1, k);
+                          glColor3fv (cb);
+
+                          if (fl_mode > 0)
+                            {
+                              for (int k = 0; k < 3; k++)
+                                cb[k] *= as;
+                              glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
+
+                              for (int k = 0; k < 3; k++)
+                                cb[k] = ds * c(j, i-1, k);
+                              glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
+                            }
+                        }
+                      if (el_mode > 0)
+                        {
+                          d = sqrt (n(j,i-1,0) * n(j,i-1,0)
+                                    + n(j,i-1,1) * n(j,i-1,1)
+                                    + n(j,i-1,2) * n(j,i-1,2));
+                          glNormal3d (n(j,i-1,0)/d, n(j,i-1,1)/d, n(j,i-1,2)/d);
+                        }
+                      glVertex3d (x(j2,i-1), y(j,i1), z(j,i-1));
+
+                      // Vertex 2
+                      if (ec_mode == 2)
+                        {
+                          for (int k = 0; k < 3; k++)
+                            cb[k] = c(j, i, k);
+                          glColor3fv (cb);
+
+                          if (fl_mode > 0)
+                            {
+                              for (int k = 0; k < 3; k++)
+                                cb[k] *= as;
+                              glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
+
+                              for (int k = 0; k < 3; k++)
+                                cb[k] = ds * c(j, i, k);
+                              glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
+                            }
+                        }
+                      if (el_mode == 2)
+                        {
+                          d = sqrt (n(j,i,0) * n(j,i,0)
+                                    + n(j,i,1) * n(j,i,1)
+                                    + n(j,i,2) * n(j,i,2));
+                          glNormal3d (n(j,i,0)/d, n(j,i,1)/d, n(j,i,2)/d);
+                        }
+                      glVertex3d (x(j2,i), y(j,i2), z(j,i));
+
+                      glEnd ();
+                    }
+                }
+            }
+
+          set_linestyle ("-");
+          set_linewidth (0.5);
+
+          if (el_mode > 0)
+            glDisable (GL_LIGHTING);
+        }
+      else
+        {
+          // FIXME: implement transparency
+        }
+    }
+
+  if (! props.marker_is ("none") &&
+      ! (props.markeredgecolor_is ("none")
+         && props.markerfacecolor_is ("none")))
+    {
+      // FIXME: check how transparency should be handled in markers
+      // FIXME: check what to do with marker facecolor set to auto
+      //        and facecolor set to none.
+
+      bool do_edge = ! props.markeredgecolor_is ("none");
+      bool do_face = ! props.markerfacecolor_is ("none");
+
+      Matrix mecolor = props.get_markeredgecolor_rgb ();
+      Matrix mfcolor = props.get_markerfacecolor_rgb ();
+      Matrix cc (1, 3, 0.0);
+
+      if (mecolor.numel () == 0 && props.markeredgecolor_is ("auto"))
+        {
+          mecolor = props.get_edgecolor_rgb ();
+          do_edge = ! props.edgecolor_is ("none");
+        }
+
+      if (mfcolor.numel () == 0 && props.markerfacecolor_is ("auto"))
+        {
+          mfcolor = props.get_facecolor_rgb ();
+          do_face = ! props.facecolor_is ("none");
+        }
+
+      if ((mecolor.numel () == 0 || mfcolor.numel () == 0)
+          && c.numel () == 0)
+        c = props.get_color_data ().array_value ();
+
+      init_marker (props.get_marker (), props.get_markersize (),
+                   props.get_linewidth ());
+
+      for (int i = 0; i < zc; i++)
+        {
+          if (y_mat)
+            i1 = i;
+
+          for (int j = 0; j < zr; j++)
+            {
+              if (clip(j,i))
+                continue;
+
+              if (x_mat)
+                j1 = j;
+
+              if ((do_edge && mecolor.numel () == 0)
+                  || (do_face && mfcolor.numel () == 0))
+                {
+                  for (int k = 0; k < 3; k++)
+                    cc(k) = c(j,i,k);
+                }
+
+              Matrix lc = (do_edge ? (mecolor.numel () == 0 ? cc : mecolor) : Matrix ());
+              Matrix fc = (do_face ? (mfcolor.numel () == 0 ? cc : mfcolor) : Matrix ());
+
+              draw_marker (x(j1,i), y(j,i1), z(j,i), lc, fc);
+            }
+        }
+
+      end_marker ();
+    }
+}
+
+// FIXME: global optimization (rendering, data structures...), there
+// is probably a smarter/faster/less-memory-consuming way to do this.
+void
+opengl_renderer::draw_patch (const patch::properties &props)
+{
+  const Matrix f = props.get_faces ().matrix_value ();
+  const Matrix v = xform.scale (props.get_vertices ().matrix_value ());
+  Matrix c;
+  const Matrix n = props.get_vertexnormals ().matrix_value ();
+  Matrix a;
+
+  int nv = v.rows ();
+  // int vmax = v.columns ();
+  int nf = f.rows ();
+  int fcmax = f.columns ();
+
+  bool has_z = (v.columns () > 2);
+  bool has_facecolor = false;
+  bool has_facealpha = false;
+
+  int fc_mode = ((props.facecolor_is ("none")
+                  || props.facecolor_is_rgb ()) ? 0 :
+                 (props.facecolor_is ("flat") ? 1 : 2));
+  int fl_mode = (props.facelighting_is ("none") ? 0 :
+                 (props.facelighting_is ("flat") ? 1 : 2));
+  int fa_mode = (props.facealpha_is_double () ? 0 :
+                 (props.facealpha_is ("flat") ? 1 : 2));
+  int ec_mode = ((props.edgecolor_is ("none")
+                  || props.edgecolor_is_rgb ()) ? 0 :
+                 (props.edgecolor_is ("flat") ? 1 : 2));
+  int el_mode = (props.edgelighting_is ("none") ? 0 :
+                 (props.edgelighting_is ("flat") ? 1 : 2));
+  int ea_mode = (props.edgealpha_is_double () ? 0 :
+                 (props.edgealpha_is ("flat") ? 1 : 2));
+
+  Matrix fcolor = props.get_facecolor_rgb ();
+  Matrix ecolor = props.get_edgecolor_rgb ();
+
+  float as = props.get_ambientstrength ();
+  float ds = props.get_diffusestrength ();
+  float ss = props.get_specularstrength ();
+  float se = props.get_specularexponent ();
+
+  boolMatrix clip (1, nv, false);
+
+  if (has_z)
+    for (int i = 0; i < nv; i++)
+      clip(i) = is_nan_or_inf (v(i,0), v(i,1), v(i,2));
+  else
+    for (int i = 0; i < nv; i++)
+      clip(i) = is_nan_or_inf (v(i,0), v(i,1), 0);
+
+  boolMatrix clip_f (1, nf, false);
+  Array<int> count_f (dim_vector (nf, 1), 0);
+
+  for (int i = 0; i < nf; i++)
+    {
+      bool fclip = false;
+      int count = 0;
+
+      for (int j = 0; j < fcmax && ! xisnan (f(i,j)); j++, count++)
+        fclip = (fclip || clip(int (f(i,j) - 1)));
+
+      clip_f(i) = fclip;
+      count_f(i) = count;
+    }
+
+  if (fc_mode > 0 || ec_mode > 0)
+    {
+      c = props.get_color_data ().matrix_value ();
+
+      if (c.rows () == 1)
+        {
+          // Single color specifications, we can simplify a little bit
+
+          if (fc_mode > 0)
+            {
+              fcolor = c;
+              fc_mode = 0;
+            }
+
+          if (ec_mode > 0)
+            {
+              ecolor = c;
+              ec_mode = 0;
+            }
+
+          c = Matrix ();
+        }
+      else
+        has_facecolor = ((c.numel () > 0) && (c.rows () == f.rows ()));
+    }
+
+  if (fa_mode > 0 || ea_mode > 0)
+    {
+      // FIXME: retrieve alpha data from patch object
+      //a = props.get_alpha_data ();
+      has_facealpha = ((a.numel () > 0) && (a.rows () == f.rows ()));
+    }
+
+  octave_idx_type fr = f.rows ();
+  std::vector<vertex_data> vdata (f.numel ());
+
+  for (int i = 0; i < nf; i++)
+    for (int j = 0; j < count_f(i); j++)
+      {
+        int idx = int (f(i,j) - 1);
+
+        Matrix vv (1, 3, 0.0);
+        Matrix cc;
+        Matrix nn(1, 3, 0.0);
+        double aa = 1.0;
+
+        vv(0) = v(idx,0); vv(1) = v(idx,1);
+        if (has_z)
+          vv(2) = v(idx,2);
+        // FIXME: uncomment when patch object has normal computation
+        //nn(0) = n(idx,0); nn(1) = n(idx,1); nn(2) = n(idx,2);
+        if (c.numel () > 0)
+          {
+            cc.resize (1, 3);
+            if (has_facecolor)
+              cc(0) = c(i,0), cc(1) = c(i,1), cc(2) = c(i,2);
+            else
+              cc(0) = c(idx,0), cc(1) = c(idx,1), cc(2) = c(idx,2);
+          }
+        if (a.numel () > 0)
+          {
+            if (has_facealpha)
+              aa = a(i);
+            else
+              aa = a(idx);
+          }
+
+        vdata[i+j*fr] =
+            vertex_data (vv, cc, nn, aa, as, ds, ss, se);
+      }
+
+  if (fl_mode > 0 || el_mode > 0)
+    {
+      float buf[4] = { ss, ss, ss, 1 };
+
+      glMaterialfv (LIGHT_MODE, GL_SPECULAR, buf);
+      glMaterialf (LIGHT_MODE, GL_SHININESS, se);
+    }
+
+  if (! props.facecolor_is ("none"))
+    {
+      // FIXME: adapt to double-radio property
+      if (props.get_facealpha_double () == 1)
+        {
+          if (fc_mode == 0)
+            {
+              glColor3dv (fcolor.data ());
+              if (fl_mode > 0)
+                {
+                  float cb[4] = { 0, 0, 0, 1 };
+
+                  for (int i = 0; i < 3; i++)
+                    cb[i] = (as * fcolor(i));
+                  glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
+
+                  for (int i = 0; i < 3; i++)
+                    cb[i] = ds * fcolor(i);
+                  glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
+                }
+            }
+
+          if (fl_mode > 0)
+            glEnable (GL_LIGHTING);
+
+          // FIXME: use __index__ property from patch object
+          patch_tesselator tess (this, fc_mode, fl_mode, 0);
+
+          for (int i = 0; i < nf; i++)
+            {
+              if (clip_f(i))
+                continue;
+
+              tess.begin_polygon (true);
+              tess.begin_contour ();
+
+              for (int j = 0; j < count_f(i); j++)
+                {
+                  vertex_data::vertex_data_rep *vv = vdata[i+j*fr].get_rep ();
+
+                  tess.add_vertex (vv->coords.fortran_vec (), vv);
+                }
+
+              tess.end_contour ();
+              tess.end_polygon ();
+            }
+
+          if (fl_mode > 0)
+            glDisable (GL_LIGHTING);
+        }
+      else
+        {
+          // FIXME: implement transparency
+        }
+    }
+
+  if (! props.edgecolor_is ("none"))
+    {
+      // FIXME: adapt to double-radio property
+      if (props.get_edgealpha_double () == 1)
+        {
+          if (ec_mode == 0)
+            {
+              glColor3dv (ecolor.data ());
+              if (el_mode > 0)
+                {
+                  float cb[4] = { 0, 0, 0, 1 };
+
+                  for (int i = 0; i < 3; i++)
+                    cb[i] = (as * ecolor(i));
+                  glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
+
+                  for (int i = 0; i < 3; i++)
+                    cb[i] = ds * ecolor(i);
+                  glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
+                }
+            }
+
+          if (el_mode > 0)
+            glEnable (GL_LIGHTING);
+
+          set_linestyle (props.get_linestyle (), false);
+          set_linewidth (props.get_linewidth ());
+
+
+          // FIXME: use __index__ property from patch object; should we
+          // offset patch contour as well?
+          patch_tesselator tess (this, ec_mode, el_mode);
+
+          for (int i = 0; i < nf; i++)
+            {
+              if (clip_f(i))
+                {
+                  // This is an unclosed contour. Draw it as a line
+                  bool flag = false;
+
+                  for (int j = 0; j < count_f(i); j++)
+                    {
+                      if (! clip(int (f(i,j) - 1)))
+                        {
+                          vertex_data::vertex_data_rep *vv = vdata[i+j*fr].get_rep ();
+                          const Matrix m = vv->coords;
+                          if (! flag)
+                            {
+                              flag = true;
+                              glBegin (GL_LINE_STRIP);
+                            }
+                          glVertex3d (m(0), m(1), m(2));
+                        }
+                      else if (flag)
+                        {
+                          flag = false;
+                          glEnd ();
+                        }
+                    }
+
+                  if (flag)
+                    glEnd ();
+                }
+              else
+                {
+                  tess.begin_polygon (false);
+                  tess.begin_contour ();
+
+                  for (int j = 0; j < count_f(i); j++)
+                    {
+                      vertex_data::vertex_data_rep *vv = vdata[i+j*fr].get_rep ();
+                      tess.add_vertex (vv->coords.fortran_vec (), vv);
+                    }
+
+                  tess.end_contour ();
+                  tess.end_polygon ();
+                }
+            }
+
+          set_linestyle ("-");
+          set_linewidth (0.5);
+
+          if (el_mode > 0)
+            glDisable (GL_LIGHTING);
+        }
+      else
+        {
+          // FIXME: implement transparency
+        }
+    }
+
+  if (! props.marker_is ("none") &&
+      ! (props.markeredgecolor_is ("none") && props.markerfacecolor_is ("none")))
+    {
+      bool do_edge = ! props.markeredgecolor_is ("none");
+      bool do_face = ! props.markerfacecolor_is ("none");
+
+      Matrix mecolor = props.get_markeredgecolor_rgb ();
+      Matrix mfcolor = props.get_markerfacecolor_rgb ();
+
+      bool has_markerfacecolor = false;
+
+      if ((mecolor.numel () == 0 && ! props.markeredgecolor_is ("none"))
+          || (mfcolor.numel () == 0 && ! props.markerfacecolor_is ("none")))
+        {
+          Matrix mc = props.get_color_data ().matrix_value ();
+
+          if (mc.rows () == 1)
+            {
+              // Single color specifications, we can simplify a little bit
+
+              if (mfcolor.numel () == 0
+                   && ! props.markerfacecolor_is ("none"))
+                mfcolor = mc;
+
+              if (mecolor.numel () == 0
+                   && ! props.markeredgecolor_is ("none"))
+                mecolor = mc;
+            }
+          else
+            {
+              if (c.numel () == 0)
+                c = props.get_color_data ().matrix_value ();
+              has_markerfacecolor = ((c.numel () > 0)
+                                    && (c.rows () == f.rows ()));
+            }
+        }
+
+
+      init_marker (props.get_marker (), props.get_markersize (),
+                   props.get_linewidth ());
+
+      for (int i = 0; i < nf; i++)
+        for (int j = 0; j < count_f(i); j++)
+          {
+            int idx = int (f(i,j) - 1);
+
+            if (clip(idx))
+              continue;
+
+            Matrix cc;
+            if (c.numel () > 0)
+              {
+                cc.resize (1, 3);
+                if (has_markerfacecolor)
+                  cc(0) = c(i,0), cc(1) = c(i,1), cc(2) = c(i,2);
+                else
+                  cc(0) = c(idx,0), cc(1) = c(idx,1), cc(2) = c(idx,2);
+              }
+
+            Matrix lc = (do_edge ? (mecolor.numel () == 0 ? cc : mecolor)
+                         : Matrix ());
+            Matrix fc = (do_face ? (mfcolor.numel () == 0 ? cc : mfcolor)
+                         : Matrix ());
+
+            draw_marker (v(idx,0), v(idx,1), (has_z ? v(idx,2) : 0), lc, fc);
+          }
+
+      end_marker ();
+    }
+}
+
+void
+opengl_renderer::draw_hggroup (const hggroup::properties &props)
+{
+  draw (props.get_children ());
+}
+
+void
+opengl_renderer::draw_text (const text::properties& props)
+{
+  if (props.get_string ().is_empty ())
+    return;
+
+  Matrix pos = xform.scale (props.get_data_position ());
+  const Matrix bbox = props.get_extent_matrix ();
+
+  // FIXME: handle margin and surrounding box
+  bool blend = glIsEnabled (GL_BLEND);
+
+  glEnable (GL_BLEND);
+  glEnable (GL_ALPHA_TEST);
+  glRasterPos3d (pos(0), pos(1), pos.numel () > 2 ? pos(2) : 0.0);
+  glBitmap (0, 0, 0, 0, bbox(0), bbox(1), 0);
+  glDrawPixels (bbox(2), bbox(3),
+                GL_RGBA, GL_UNSIGNED_BYTE, props.get_pixels ().data ());
+  glDisable (GL_ALPHA_TEST);
+  if (! blend)
+    glDisable (GL_BLEND);
+
+}
+
+void
+opengl_renderer::draw_image (const image::properties& props)
+{
+  octave_value cdata = props.get_color_data ();
+  dim_vector dv (cdata.dims ());
+  int h = dv(0), w = dv(1);
+
+  Matrix x = props.get_xdata ().matrix_value ();
+  Matrix y = props.get_ydata ().matrix_value ();
+
+  // Someone wants us to draw an empty image? No way.
+  if (x.is_empty () || y.is_empty ())
+    return;
+
+  if (w > 1 && x(1) == x(0))
+    x(1) = x(1) + (w-1);
+
+  if (h > 1 && y(1) == y(0))
+    y(1) = y(1) + (h-1);
+
+  const ColumnVector p0 = xform.transform (x(0), y(0), 0);
+  const ColumnVector p1 = xform.transform (x(1), y(1), 0);
+
+  // image pixel size in screen pixel units
+  float pix_dx, pix_dy;
+  // image pixel size in normalized units
+  float nor_dx, nor_dy;
+
+  if (w > 1)
+    {
+      pix_dx = (p1(0) - p0(0))/(w-1);
+      nor_dx = (x(1) - x(0))/(w-1);
+    }
+  else
+    {
+      const ColumnVector p1w = xform.transform (x(1) + 1, y(1), 0);
+      pix_dx = p1w(0) - p0(0);
+      nor_dx = 1;
+    }
+
+  if (h > 1)
+    {
+      pix_dy = (p1(1) - p0(1))/(h-1);
+      nor_dy = (y(1) - y(0))/(h-1);
+    }
+  else
+    {
+      const ColumnVector p1h = xform.transform (x(1), y(1) + 1, 0);
+      pix_dy = p1h(1) - p0(1);
+      nor_dy = 1;
+    }
+
+
+  // OpenGL won't draw the image if it's origin is outside the
+  // viewport/clipping plane so we must do the clipping
+  // ourselfes - only draw part of the image
+
+  int j0 = 0, j1 = w;
+  int i0 = 0, i1 = h;
+
+  float im_xmin = x(0) - nor_dx/2;
+  float im_xmax = x(1) + nor_dx/2;
+  float im_ymin = y(0) - nor_dy/2;
+  float im_ymax = y(1) + nor_dy/2;
+  if (props.is_clipping ()) // clip to axes
+    {
+      if (im_xmin < xmin)
+        j0 += (xmin - im_xmin)/nor_dx + 1;
+      if (im_xmax > xmax)
+        j1 -= (im_xmax - xmax)/nor_dx ;
+
+      if (im_ymin < ymin)
+        i0 += (ymin - im_ymin)/nor_dy + 1;
+      if (im_ymax > ymax)
+        i1 -= (im_ymax - ymax)/nor_dy;
+    }
+  else // clip to viewport
+    {
+      GLfloat vp[4];
+      glGetFloatv (GL_VIEWPORT, vp);
+      // FIXME -- actually add the code to do it!
+
+    }
+
+  if (i0 >= i1 || j0 >= j1)
+    return;
+
+  glPixelZoom (pix_dx, -pix_dy);
+  glRasterPos3d (im_xmin + nor_dx*j0, im_ymin + nor_dy*i0, 0);
+
+  // by default this is 4
+  glPixelStorei (GL_UNPACK_ALIGNMENT,1);
+
+  // Expect RGB data
+  if (dv.length () == 3 && dv(2) == 3)
+    {
+      if (cdata.is_double_type ())
+        {
+          const NDArray xcdata = cdata.array_value ();
+
+          OCTAVE_LOCAL_BUFFER (GLfloat, a, 3*(j1-j0)*(i1-i0));
+
+          for (int i = i0; i < i1; i++)
+            {
+              for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3)
+                {
+                  a[idx]   = xcdata(i,j,0);
+                  a[idx+1] = xcdata(i,j,1);
+                  a[idx+2] = xcdata(i,j,2);
+                }
+            }
+
+          draw_pixels (j1-j0, i1-i0, GL_RGB, GL_FLOAT, a);
+
+        }
+      else if (cdata.is_uint16_type ())
+        {
+          const uint16NDArray xcdata = cdata.uint16_array_value ();
+
+          OCTAVE_LOCAL_BUFFER (GLushort, a, 3*(j1-j0)*(i1-i0));
+
+          for (int i = i0; i < i1; i++)
+            {
+              for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3)
+                {
+                  a[idx]   = xcdata(i,j,0);
+                  a[idx+1] = xcdata(i,j,1);
+                  a[idx+2] = xcdata(i,j,2);
+                }
+            }
+
+          draw_pixels (j1-j0, i1-i0, GL_RGB, GL_UNSIGNED_SHORT, a);
+
+        }
+      else if (cdata.is_uint8_type ())
+        {
+          const uint8NDArray xcdata = cdata.uint8_array_value ();
+
+          OCTAVE_LOCAL_BUFFER (GLubyte, a, 3*(j1-j0)*(i1-i0));
+
+          for (int i = i0; i < i1; i++)
+            {
+              for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3)
+                {
+                  a[idx]   = xcdata(i,j,0);
+                  a[idx+1] = xcdata(i,j,1);
+                  a[idx+2] = xcdata(i,j,2);
+                }
+            }
+
+          draw_pixels (j1-j0, i1-i0, GL_RGB, GL_UNSIGNED_BYTE, a);
+        }
+      else
+        warning ("opengl_texture::draw: invalid image data type (expected double, uint16, or uint8)");
+    }
+  else
+    warning ("opengl_texture::draw: invalid image size (expected n*m*3 or n*m)");
+
+  glPixelZoom (1, 1);
+}
+
+void
+opengl_renderer::set_viewport (int w, int h)
+{
+  glViewport (0, 0, w, h);
+}
+
+void
+opengl_renderer::draw_pixels (GLsizei width, GLsizei height, GLenum format,
+                              GLenum type, const GLvoid *data)
+{
+  glDrawPixels (width, height, format, type, data);
+}
+
+void
+opengl_renderer::set_color (const Matrix& c)
+{
+  glColor3dv (c.data ());
+#if HAVE_FREETYPE
+  text_renderer.set_color (c);
+#endif
+}
+
+void
+opengl_renderer::set_font (const base_properties& props)
+{
+#if HAVE_FREETYPE
+  text_renderer.set_font (props.get ("fontname").string_value (),
+                          props.get ("fontweight").string_value (),
+                          props.get ("fontangle").string_value (),
+                          props.get ("fontsize").double_value ());
+#endif
+}
+
+void
+opengl_renderer::set_polygon_offset (bool on, double offset)
+{
+  if (on)
+    {
+      glPolygonOffset (offset, offset);
+      glEnable (GL_POLYGON_OFFSET_FILL);
+      glEnable (GL_POLYGON_OFFSET_LINE);
+    }
+  else
+    {
+      glDisable (GL_POLYGON_OFFSET_FILL);
+      glDisable (GL_POLYGON_OFFSET_LINE);
+    }
+}
+
+void
+opengl_renderer::set_linewidth (float w)
+{
+  glLineWidth (w);
+}
+
+void
+opengl_renderer::set_linestyle (const std::string& s, bool use_stipple)
+{
+  bool solid = false;
+
+  if (s == "-")
+    {
+      glLineStipple (1, static_cast<unsigned short> (0xFFFF));
+      solid = true;
+    }
+  else if (s == ":")
+    glLineStipple (1, static_cast<unsigned short> (0x8888));
+  else if (s == "--")
+    glLineStipple (1, static_cast<unsigned short> (0x0FFF));
+  else if (s == "-.")
+    glLineStipple (1, static_cast<unsigned short> (0x020F));
+  else
+    glLineStipple (1, static_cast<unsigned short> (0x0000));
+
+  if (solid && ! use_stipple)
+    glDisable (GL_LINE_STIPPLE);
+  else
+    glEnable (GL_LINE_STIPPLE);
+}
+
+void
+opengl_renderer::set_clipbox (double x1, double x2, double y1, double y2,
+                              double z1, double z2)
+{
+  double dx = (x2-x1);
+  double dy = (y2-y1);
+  double dz = (z2-z1);
+
+  x1 -= 0.001*dx; x2 += 0.001*dx;
+  y1 -= 0.001*dy; y2 += 0.001*dy;
+  z1 -= 0.001*dz; z2 += 0.001*dz;
+
+  ColumnVector p (4, 0.0);
+
+  p(0) = -1; p(3) = x2;
+  glClipPlane (GL_CLIP_PLANE0, p.data ());
+  p(0) = 1; p(3) = -x1;
+  glClipPlane (GL_CLIP_PLANE1, p.data ());
+  p(0) = 0; p(1) = -1; p(3) = y2;
+  glClipPlane (GL_CLIP_PLANE2, p.data ());
+  p(1) = 1; p(3) = -y1;
+  glClipPlane (GL_CLIP_PLANE3, p.data ());
+  p(1) = 0; p(2) = -1; p(3) = z2;
+  glClipPlane (GL_CLIP_PLANE4, p.data ());
+  p(2) = 1; p(3) = -z1;
+  glClipPlane (GL_CLIP_PLANE5, p.data ());
+
+  xmin = x1; xmax = x2;
+  ymin = y1; ymax = y2;
+  zmin = z1; zmax = z2;
+}
+
+void
+opengl_renderer::set_clipping (bool enable)
+{
+  bool has_clipping = (glIsEnabled (GL_CLIP_PLANE0) == GL_TRUE);
+
+  if (enable != has_clipping)
+    {
+      if (enable)
+        for (int i = 0; i < 6; i++)
+          glEnable (GL_CLIP_PLANE0+i);
+      else
+        for (int i = 0; i < 6; i++)
+          glDisable (GL_CLIP_PLANE0+i);
+    }
+}
+
+void
+opengl_renderer::init_marker (const std::string& m, double size, float width)
+{
+#if defined (HAVE_FRAMEWORK_OPENGL)
+  GLint vw[4];
+#else
+  int vw[4];
+#endif
+
+  glGetIntegerv (GL_VIEWPORT, vw);
+
+  glMatrixMode (GL_PROJECTION);
+  glPushMatrix ();
+  glLoadIdentity ();
+  glOrtho (0, vw[2], vw[3], 0, xZ1, xZ2);
+  glMatrixMode (GL_MODELVIEW);
+  glPushMatrix ();
+
+  set_clipping (false);
+  set_linewidth (width);
+
+  marker_id = make_marker_list (m, size, false);
+  filled_marker_id = make_marker_list (m, size, true);
+}
+
+void
+opengl_renderer::end_marker (void)
+{
+  glDeleteLists (marker_id, 1);
+  glDeleteLists (filled_marker_id, 1);
+
+  glMatrixMode (GL_MODELVIEW);
+  glPopMatrix ();
+  glMatrixMode (GL_PROJECTION);
+  glPopMatrix ();
+  set_linewidth (0.5f);
+}
+
+void
+opengl_renderer::draw_marker (double x, double y, double z,
+                              const Matrix& lc, const Matrix& fc)
+{
+  ColumnVector tmp = xform.transform (x, y, z, false);
+
+  glLoadIdentity ();
+  glTranslated (tmp(0), tmp(1), -tmp(2));
+
+  if (filled_marker_id > 0 && fc.numel () > 0)
+    {
+      glColor3dv (fc.data ());
+      set_polygon_offset (true, -1.0);
+      glCallList (filled_marker_id);
+      if (lc.numel () > 0)
+        {
+          glColor3dv (lc.data ());
+          glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
+          glEdgeFlag (GL_TRUE);
+          set_polygon_offset (true, -2.0);
+          glCallList (filled_marker_id);
+          glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
+        }
+      set_polygon_offset (false);
+    }
+  else if (marker_id > 0 && lc.numel () > 0)
+    {
+      glColor3dv (lc.data ());
+      glCallList (marker_id);
+    }
+}
+
+unsigned int
+opengl_renderer::make_marker_list (const std::string& marker, double size,
+                                   bool filled) const
+{
+  char c = marker[0];
+
+  if (filled && (c == '+' || c == 'x' || c == '*' || c == '.'))
+    return 0;
+
+  unsigned int ID = glGenLists (1);
+  double sz = size * toolkit.get_screen_resolution () / 72.0;
+
+  // constants for the * marker
+  const double sqrt2d4 = 0.35355339059327;
+  double tt = sz*sqrt2d4;
+
+  glNewList (ID, GL_COMPILE);
+
+  switch (marker[0])
+    {
+    case '+':
+      glBegin (GL_LINES);
+      glVertex2f (-sz/2, 0);
+      glVertex2f (sz/2, 0);
+      glVertex2f (0, -sz/2);
+      glVertex2f (0, sz/2);
+      glEnd ();
+      break;
+    case 'x':
+      glBegin (GL_LINES);
+      glVertex2f (-sz/2, -sz/2);
+      glVertex2f (sz/2, sz/2);
+      glVertex2f (-sz/2, sz/2);
+      glVertex2f (sz/2, -sz/2);
+      glEnd ();
+      break;
+    case '*':
+      glBegin (GL_LINES);
+      glVertex2f (-sz/2, 0);
+      glVertex2f (sz/2, 0);
+      glVertex2f (0, -sz/2);
+      glVertex2f (0, sz/2);
+      glVertex2f (-tt, -tt);
+      glVertex2f (+tt, +tt);
+      glVertex2f (-tt, +tt);
+      glVertex2f (+tt, -tt);
+      glEnd ();
+      break;
+    case '.':
+      {
+        double ang_step = M_PI / 5;
+
+        glBegin (GL_POLYGON);
+        for (double ang = 0; ang < (2*M_PI); ang += ang_step)
+          glVertex2d (sz*cos (ang)/3, sz*sin (ang)/3);
+        glEnd ();
+      }
+      break;
+    case 's':
+      glBegin ((filled ? GL_POLYGON : GL_LINE_LOOP));
+      glVertex2d (-sz/2, -sz/2);
+      glVertex2d (-sz/2, sz/2);
+      glVertex2d (sz/2, sz/2);
+      glVertex2d (sz/2, -sz/2);
+      glEnd ();
+      break;
+    case 'o':
+      {
+        double ang_step = M_PI / 5;
+
+        glBegin ((filled ? GL_POLYGON : GL_LINE_LOOP));
+        for (double ang = 0; ang < (2*M_PI); ang += ang_step)
+          glVertex2d (sz*cos (ang)/2, sz*sin (ang)/2);
+        glEnd ();
+      }
+      break;
+    case 'd':
+      glBegin ((filled ? GL_POLYGON : GL_LINE_LOOP));
+      glVertex2d (0, -sz/2);
+      glVertex2d (sz/2, 0);
+      glVertex2d (0, sz/2);
+      glVertex2d (-sz/2, 0);
+      glEnd ();
+      break;
+    case 'v':
+      glBegin ((filled ? GL_POLYGON : GL_LINE_LOOP));
+      glVertex2f (0, sz/2);
+      glVertex2f (sz/2, -sz/2);
+      glVertex2f (-sz/2, -sz/2);
+      glEnd ();
+      break;
+    case '^':
+      glBegin ((filled ? GL_POLYGON : GL_LINE_LOOP));
+      glVertex2f (0, -sz/2);
+      glVertex2f (-sz/2, sz/2);
+      glVertex2f (sz/2, sz/2);
+      glEnd ();
+      break;
+    case '>':
+      glBegin ((filled ? GL_POLYGON : GL_LINE_LOOP));
+      glVertex2f (sz/2, 0);
+      glVertex2f (-sz/2, sz/2);
+      glVertex2f (-sz/2, -sz/2);
+      glEnd ();
+      break;
+    case '<':
+      glBegin ((filled ? GL_POLYGON : GL_LINE_LOOP));
+      glVertex2f (-sz/2, 0);
+      glVertex2f (sz/2, -sz/2);
+      glVertex2f (sz/2, sz/2);
+      glEnd ();
+      break;
+    case 'p':
+      {
+        double ang;
+        double r;
+        double dr = 1.0 - sin (M_PI/10)/sin (3*M_PI/10)*1.02;
+
+        glBegin ((filled ? GL_POLYGON : GL_LINE_LOOP));
+        for (int i = 0; i < 2*5; i++)
+          {
+            ang = (-0.5 + double(i+1)/5) * M_PI;
+            r = 1.0 - (dr * fmod (double(i+1), 2.0));
+            glVertex2d (sz*r*cos (ang)/2, sz*r*sin (ang)/2);
+          }
+        glEnd ();
+      }
+      break;
+    case 'h':
+      {
+        double ang;
+        double r;
+        double dr = 1.0 - 0.5/sin (M_PI/3)*1.02;
+
+        glBegin ((filled ? GL_POLYGON : GL_LINE_LOOP));
+        for (int i = 0; i < 2*6; i++)
+          {
+            ang = (0.5 + double(i+1)/6.0) * M_PI;
+            r = 1.0 - (dr * fmod (double(i+1), 2.0));
+            glVertex2d (sz*r*cos (ang)/2, sz*r*sin (ang)/2);
+          }
+        glEnd ();
+      }
+      break;
+    default:
+      warning ("opengl_renderer: unsupported marker `%s'",
+               marker.c_str ());
+      break;
+    }
+
+  glEndList ();
+
+  return ID;
+}
+
+void
+opengl_renderer::text_to_pixels (const std::string& txt,
+                                 uint8NDArray& pixels,
+                                 Matrix& bbox,
+                                 int halign, int valign, double rotation)
+{
+#if HAVE_FREETYPE
+  text_renderer.text_to_pixels (txt, pixels, bbox,
+                                halign, valign, rotation);
+#endif
+}
+
+Matrix
+opengl_renderer::render_text (const std::string& txt,
+                            double x, double y, double z,
+                            int halign, int valign, double rotation)
+{
+#if HAVE_FREETYPE
+  if (txt.empty ())
+    return Matrix (1, 4, 0.0);
+
+  uint8NDArray pixels;
+  Matrix bbox;
+  text_to_pixels (txt, pixels, bbox, halign, valign, rotation);
+
+  bool blend = glIsEnabled (GL_BLEND);
+
+  glEnable (GL_BLEND);
+  glEnable (GL_ALPHA_TEST);
+  glRasterPos3d (x, y, z);
+  glBitmap(0, 0, 0, 0, bbox(0), bbox(1), 0);
+  glDrawPixels (bbox(2), bbox(3),
+                GL_RGBA, GL_UNSIGNED_BYTE, pixels.data ());
+  glDisable (GL_ALPHA_TEST);
+  if (! blend)
+    glDisable (GL_BLEND);
+
+  return bbox;
+#else
+  ::warning ("render_text: cannot render text, Freetype library not available");
+  return Matrix (1, 4, 0.0);
+#endif
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/gl-render.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,211 @@
+/*
+
+Copyright (C) 2008-2012 Michael Goffioul
+
+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/>.
+
+*/
+
+#if !defined (gl_render_h)
+#define gl_render_h 1
+
+#ifdef HAVE_WINDOWS_H
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#endif
+
+#ifdef HAVE_GL_GL_H
+#include <GL/gl.h>
+#elif defined HAVE_OPENGL_GL_H || defined HAVE_FRAMEWORK_OPENGL
+#include <OpenGL/gl.h>
+#endif
+
+#ifdef HAVE_GL_GLU_H
+#include <GL/glu.h>
+#elif defined HAVE_OPENGL_GLU_H || defined HAVE_FRAMEWORK_OPENGL
+#include <OpenGL/glu.h>
+#endif
+
+#include "graphics.h"
+#include "txt-eng-ft.h"
+
+class
+OCTINTERP_API
+opengl_renderer
+{
+public:
+  opengl_renderer (void)
+    : toolkit (), xform (), xmin (), xmax (), ymin (), ymax (),
+    zmin (), zmax (), xZ1 (), xZ2 (), marker_id (), filled_marker_id (),
+    camera_pos (), camera_dir ()
+#if HAVE_FREETYPE
+    , text_renderer ()
+#endif
+  { }
+
+  virtual ~opengl_renderer (void) { }
+
+  virtual void draw (const graphics_object& go, bool toplevel = true);
+
+  virtual void draw (const Matrix& hlist, bool toplevel = false)
+    {
+      int len = hlist.length ();
+
+      for (int i = len-1; i >= 0; i--)
+        {
+          graphics_object obj = gh_manager::get_object (hlist(i));
+
+          if (obj)
+            draw (obj, toplevel);
+        }
+    }
+
+  virtual void set_viewport (int w, int h);
+  virtual graphics_xform get_transform (void) const { return xform; }
+
+protected:
+  virtual void draw_figure (const figure::properties& props);
+  virtual void draw_axes (const axes::properties& props);
+  virtual void draw_line (const line::properties& props);
+  virtual void draw_surface (const surface::properties& props);
+  virtual void draw_patch (const patch::properties& props);
+  virtual void draw_hggroup (const hggroup::properties& props);
+  virtual void draw_text (const text::properties& props);
+  virtual void draw_image (const image::properties& props);
+  virtual void draw_uipanel (const uipanel::properties& props,
+                             const graphics_object& go);
+
+  virtual void init_gl_context (bool enhanced, const Matrix& backgroundColor);
+  virtual void setup_opengl_transformation (const axes::properties& props);
+
+  virtual void set_color (const Matrix& c);
+  virtual void set_polygon_offset (bool on, double offset = 0.0);
+  virtual void set_linewidth (float w);
+  virtual void set_linestyle (const std::string& s, bool stipple = false);
+  virtual void set_clipbox (double x1, double x2, double y1, double y2,
+                            double z1, double z2);
+  virtual void set_clipping (bool on);
+  virtual void set_font (const base_properties& props);
+
+  virtual void init_marker (const std::string& m, double size, float width);
+  virtual void end_marker (void);
+  virtual void draw_marker (double x, double y, double z,
+                            const Matrix& lc, const Matrix& fc);
+
+  virtual void text_to_pixels (const std::string& txt,
+                               uint8NDArray& pixels,
+                               Matrix& bbox,
+                               int halign = 0, int valign = 0,
+                               double rotation = 0.0);
+
+  virtual Matrix render_text (const std::string& txt,
+                              double x, double y, double z,
+                              int halign, int valign, double rotation = 0.0);
+
+  virtual void draw_pixels (GLsizei w, GLsizei h, GLenum format,
+                            GLenum type, const GLvoid *data);
+
+  virtual void render_grid (const std::string& gridstyle, const Matrix& ticks,
+                            double lim1, double lim2,
+                            double p1, double p1N, double p2, double p2N,
+                            int xyz, bool is_3D);
+
+  virtual void render_tickmarks (const Matrix& ticks, double lim1, double lim2,
+                                 double p1, double p1N, double p2, double p2N,
+                                 double dx, double dy, double dz,
+                                 int xyz, bool doubleside);
+
+  virtual void render_ticktexts (const Matrix& ticks,
+                                 const string_vector& ticklabels,
+                                 double lim1, double lim2,
+                                 double p1, double p2,
+                                 int xyz, int ha, int va,
+                                 int& wmax, int& hmax);
+
+private:
+  opengl_renderer (const opengl_renderer&)
+    : toolkit (), xform (), xmin (), xmax (), ymin (), ymax (),
+    zmin (), zmax (), xZ1 (), xZ2 (), marker_id (), filled_marker_id (),
+    camera_pos (), camera_dir ()
+#if HAVE_FREETYPE
+    , text_renderer ()
+#endif
+    { }
+
+  opengl_renderer& operator = (const opengl_renderer&)
+    { return *this; }
+
+  bool is_nan_or_inf (double x, double y, double z) const
+    {
+      return (xisnan (x) || xisnan (y) || xisnan (z)
+              || xisinf (x) || xisinf (y) || xisinf (z));
+    }
+
+  octave_uint8 clip_code (double x, double y, double z) const
+    {
+      return ((x < xmin ? 1 : 0)
+              | (x > xmax ? 1 : 0) << 1
+              | (y < ymin ? 1 : 0) << 2
+              | (y > ymax ? 1 : 0) << 3
+              | (z < zmin ? 1 : 0) << 4
+              | (z > zmax ? 1 : 0) << 5
+              | (is_nan_or_inf (x, y, z) ? 0 : 1) << 6);
+    }
+
+  unsigned int make_marker_list (const std::string& m, double size,
+                                 bool filled) const;
+
+  void draw_axes_planes (const axes::properties& props);
+  void draw_axes_boxes (const axes::properties& props);
+
+  void draw_axes_x_grid (const axes::properties& props);
+  void draw_axes_y_grid (const axes::properties& props);
+  void draw_axes_z_grid (const axes::properties& props);
+
+  void draw_axes_children (const axes::properties& props);
+
+private:
+  // The graphics toolkit associated with the figure being rendered.
+  graphics_toolkit toolkit;
+
+  // axes transformation data
+  graphics_xform xform;
+
+  // axis limits in model scaled coordinate
+  double xmin, xmax;
+  double ymin, ymax;
+  double zmin, zmax;
+
+  // Z projection limits in windows coordinate
+  double xZ1, xZ2;
+
+  // call lists identifiers for markers
+  unsigned int marker_id, filled_marker_id;
+
+  // camera information for primitive sorting
+  ColumnVector camera_pos, camera_dir;
+
+#if HAVE_FREETYPE
+  // freetype render, used for text rendering
+  ft_render text_renderer;
+#endif
+
+private:
+  class patch_tesselator;
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/gl2ps-renderer.cc	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,232 @@
+/*
+
+Copyright (C) 2009-2012 Shai Ayal
+
+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/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#if defined (HAVE_OPENGL)
+
+#include <cstdio>
+
+#include "lo-mappers.h"
+#include "oct-locbuf.h"
+
+#include "gl2ps-renderer.h"
+#include "gl2ps.h"
+
+void
+glps_renderer::draw (const graphics_object& go)
+{
+  static bool in_draw = false;
+
+  if (!in_draw)
+    {
+      in_draw = true;
+
+      GLint buffsize = 0, state = GL2PS_OVERFLOW;
+      GLint viewport[4];
+
+      glGetIntegerv (GL_VIEWPORT, viewport);
+
+      GLint gl2ps_term;
+      if (term.find ("eps") != std::string::npos) gl2ps_term = GL2PS_EPS;
+      else if (term.find ("pdf") != std::string::npos) gl2ps_term = GL2PS_PDF;
+      else if (term.find ("svg") != std::string::npos) gl2ps_term = GL2PS_SVG;
+      else if (term.find ("ps") != std::string::npos) gl2ps_term = GL2PS_PS;
+      else if (term.find ("pgf") != std::string::npos) gl2ps_term = GL2PS_PGF;
+      else if (term.find ("tex") != std::string::npos) gl2ps_term = GL2PS_TEX;
+      else
+        {
+          error ("gl2ps-renderer:: Unknown terminal");
+          return;
+        }
+
+      GLint gl2ps_text = 0;
+      if (term.find ("notxt") != std::string::npos) gl2ps_text = GL2PS_NO_TEXT;
+
+      // Default sort order optimizes for 3D plots
+      GLint gl2ps_sort = GL2PS_BSP_SORT;
+      if (term.find ("is2D") != std::string::npos) gl2ps_sort = GL2PS_NO_SORT;
+
+      while (state == GL2PS_OVERFLOW)
+        {
+          buffsize += 1024*1024;
+          gl2psBeginPage ("glps_renderer figure", "Octave", viewport,
+                          gl2ps_term, gl2ps_sort,
+                          (GL2PS_SILENT | GL2PS_SIMPLE_LINE_OFFSET
+                           | GL2PS_NO_BLENDING | GL2PS_OCCLUSION_CULL
+                           | GL2PS_BEST_ROOT | gl2ps_text
+                           | GL2PS_NO_PS3_SHADING),
+                          GL_RGBA, 0, NULL, 0, 0, 0,
+                          buffsize, fp, "" );
+
+          opengl_renderer::draw (go);
+          state = gl2psEndPage ();
+        }
+
+      in_draw = 0;
+    }
+  else
+    opengl_renderer::draw (go);
+}
+
+int
+glps_renderer::alignment_to_mode (int ha, int va) const
+{
+  int gl2psa=GL2PS_TEXT_BL;
+  if (ha == 0)
+    {
+      if (va == 0 || va == 3)
+        gl2psa=GL2PS_TEXT_BL;
+      else if (va == 2)
+        gl2psa=GL2PS_TEXT_TL;
+      else if (va == 1)
+        gl2psa=GL2PS_TEXT_CL;
+    }
+  else if (ha == 2)
+    {
+      if (va == 0 || va == 3)
+        gl2psa=GL2PS_TEXT_BR;
+      else if (va == 2)
+        gl2psa=GL2PS_TEXT_TR;
+      else if (va == 1)
+        gl2psa=GL2PS_TEXT_CR;
+    }
+  else if (ha == 1)
+    {
+      if (va == 0 || va == 3)
+        gl2psa=GL2PS_TEXT_B;
+      else if (va == 2)
+        gl2psa=GL2PS_TEXT_T;
+      else if (va == 1)
+        gl2psa=GL2PS_TEXT_C;
+    }
+  return gl2psa;
+}
+
+Matrix
+glps_renderer::render_text (const std::string& txt,
+                            double x, double y, double z,
+                            int ha, int va, double rotation)
+{
+  if (txt.empty ())
+    return Matrix (1, 4, 0.0);
+
+  glRasterPos3d (x, y, z);
+  gl2psTextOpt (txt.c_str (), fontname.c_str (), fontsize,
+                alignment_to_mode (ha, va), rotation);
+
+  // FIXME? -- we have no way of getting a bounding box from gl2ps, so
+  // we use freetype
+  Matrix bbox;
+  uint8NDArray pixels;
+  text_to_pixels (txt, pixels, bbox, 0, 0, rotation);
+  return bbox;
+}
+
+void
+glps_renderer::set_font (const base_properties& props)
+{
+  opengl_renderer::set_font (props);
+
+  fontsize = props.get ("fontsize").double_value ();
+
+  caseless_str fn = props.get ("fontname").string_value ();
+  fontname = "";
+  if (fn == "times" || fn == "times-roman")
+    fontname = "Times-Roman";
+  else if (fn == "courier")
+    fontname = "Courier";
+  else if (fn == "symbol")
+    fontname = "Symbol";
+  else if (fn == "zapfdingbats")
+    fontname = "ZapfDingbats";
+  else
+    fontname = "Helvetica";
+
+  // FIXME -- add support for bold and italic
+}
+
+template <typename T>
+static void
+draw_pixels (GLsizei w, GLsizei h, GLenum format, const T *data)
+{
+  OCTAVE_LOCAL_BUFFER (GLfloat, a, 3*w*h);
+
+  for (int i = 0; i < 3*w*h; i++)
+    a[i] = data[i];
+
+  gl2psDrawPixels (w, h, 0, 0, format, GL_FLOAT, a);
+}
+
+void
+glps_renderer::draw_pixels (GLsizei w, GLsizei h, GLenum format,
+                            GLenum type, const GLvoid *data)
+{
+  if (type == GL_UNSIGNED_SHORT)
+    ::draw_pixels (w, h, format, static_cast<const GLushort *> (data));
+  else if (type == GL_UNSIGNED_BYTE)
+    ::draw_pixels (w, h, format, static_cast<const GLubyte *> (data));
+  else
+    gl2psDrawPixels (w, h, 0, 0, format, type, data);
+}
+
+void
+glps_renderer::draw_text (const text::properties& props)
+{
+  if (props.get_string ().is_empty ())
+    return;
+
+  set_font (props);
+  set_color (props.get_color_rgb ());
+
+  const Matrix pos = get_transform ().scale (props.get_data_position ());
+  int halign = 0, valign = 0;
+
+  if (props.horizontalalignment_is ("center"))
+    halign = 1;
+  else if (props.horizontalalignment_is ("right"))
+    halign = 2;
+
+  if (props.verticalalignment_is ("top"))
+    valign = 2;
+  else if (props.verticalalignment_is ("baseline"))
+    valign = 3;
+  else if (props.verticalalignment_is ("middle"))
+    valign = 1;
+
+  // FIXME: handle margin and surrounding box
+
+  glRasterPos3d (pos(0), pos(1), pos.numel () > 2 ? pos(2) : 0.0);
+
+  octave_value string_prop = props.get_string ();
+
+  string_vector sv = string_prop.all_strings ();
+
+  std::string s = sv.join ("\n");
+
+  gl2psTextOpt (s.c_str (), fontname.c_str (), fontsize,
+                alignment_to_mode (halign, valign), props.get_rotation ());
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/gl2ps-renderer.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,87 @@
+/*
+
+Copyright (C) 2009-2012 Shai Ayal
+
+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/>.
+
+*/
+
+#if !defined (gl2ps_renderer_h)
+#define gl2ps_renderer_h 1
+
+#include "gl-render.h"
+#include "gl2ps.h"
+
+class
+OCTINTERP_API
+glps_renderer : public opengl_renderer
+{
+public:
+  glps_renderer (FILE *_fp, const std::string& _term)
+    : opengl_renderer () , fp (_fp), term (_term),
+    fontsize (), fontname () { }
+
+  ~glps_renderer (void) { }
+
+  void draw (const graphics_object& go);
+
+protected:
+
+  Matrix render_text (const std::string& txt,
+                      double x, double y, double z,
+                      int halign, int valign, double rotation = 0.0);
+
+
+  void set_font (const base_properties& props);
+
+  void draw_text (const text::properties& props);
+  void draw_pixels (GLsizei w, GLsizei h, GLenum format,
+                    GLenum type, const GLvoid *data);
+
+  void set_linestyle (const std::string& s, bool use_stipple = false)
+  {
+    opengl_renderer::set_linestyle (s, use_stipple);
+
+    if (s == "-" && ! use_stipple)
+      gl2psDisable (GL2PS_LINE_STIPPLE);
+    else
+      gl2psEnable (GL2PS_LINE_STIPPLE);
+  }
+
+  void set_polygon_offset (bool on, double offset = 0.0)
+  {
+    opengl_renderer::set_polygon_offset (on, offset);
+    if (on)
+      gl2psEnable (GL2PS_POLYGON_OFFSET_FILL);
+    else
+      gl2psDisable (GL2PS_POLYGON_OFFSET_FILL);
+  }
+
+  void set_linewidth (float w)
+  {
+    gl2psLineWidth (w);
+  }
+
+private:
+  int alignment_to_mode (int ha, int va) const;
+  FILE *fp;
+  caseless_str term;
+  double fontsize;
+  std::string fontname;
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/gl2ps.c	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,6078 @@
+/*
+ * GL2PS, an OpenGL to PostScript Printing Library
+ * Copyright (C) 1999-2011 C. Geuzaine
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of either:
+ *
+ * a) the GNU Library General Public License as published by the Free
+ * Software Foundation, either version 2 of the License, or (at your
+ * option) any later version; or
+ *
+ * b) the GL2PS License as published by Christophe Geuzaine, either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program 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 either
+ * the GNU Library General Public License or the GL2PS License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library in the file named "COPYING.LGPL";
+ * if not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+ * Cambridge, MA 02139, USA.
+ *
+ * You should have received a copy of the GL2PS License with this
+ * library in the file named "COPYING.GL2PS"; if not, I will be glad
+ * to provide one.
+ *
+ * For the latest info about gl2ps and a full list of contributors,
+ * see http://www.geuz.org/gl2ps/.
+ *
+ * Please report all bugs and problems to <gl2ps@geuz.org>.
+ */
+
+#include "gl2ps.h"
+
+#include <math.h>
+#include <string.h>
+#include <sys/types.h>
+#include <stdarg.h>
+#include <time.h>
+#include <float.h>
+
+#if defined(GL2PS_HAVE_ZLIB)
+#include <zlib.h>
+#endif
+
+#if defined(GL2PS_HAVE_LIBPNG)
+#include <png.h>
+#endif
+
+/*********************************************************************
+ *
+ * Private definitions, data structures and prototypes
+ *
+ *********************************************************************/
+
+/* Magic numbers (assuming that the order of magnitude of window
+   coordinates is 10^3) */
+
+#define GL2PS_EPSILON       5.0e-3F
+#define GL2PS_ZSCALE        1000.0F
+#define GL2PS_ZOFFSET       5.0e-2F
+#define GL2PS_ZOFFSET_LARGE 20.0F
+#define GL2PS_ZERO(arg)     (fabs(arg) < 1.e-20)
+
+/* Primitive types */
+
+#define GL2PS_NO_TYPE          -1
+#define GL2PS_TEXT             1
+#define GL2PS_POINT            2
+#define GL2PS_LINE             3
+#define GL2PS_QUADRANGLE       4
+#define GL2PS_TRIANGLE         5
+#define GL2PS_PIXMAP           6
+#define GL2PS_IMAGEMAP         7
+#define GL2PS_IMAGEMAP_WRITTEN 8
+#define GL2PS_IMAGEMAP_VISIBLE 9
+#define GL2PS_SPECIAL          10
+
+/* BSP tree primitive comparison */
+
+#define GL2PS_COINCIDENT  1
+#define GL2PS_IN_FRONT_OF 2
+#define GL2PS_IN_BACK_OF  3
+#define GL2PS_SPANNING    4
+
+/* 2D BSP tree primitive comparison */
+
+#define GL2PS_POINT_COINCIDENT 0
+#define GL2PS_POINT_INFRONT    1
+#define GL2PS_POINT_BACK       2
+
+/* Internal feedback buffer pass-through tokens */
+
+#define GL2PS_BEGIN_OFFSET_TOKEN   1
+#define GL2PS_END_OFFSET_TOKEN     2
+#define GL2PS_BEGIN_BOUNDARY_TOKEN 3
+#define GL2PS_END_BOUNDARY_TOKEN   4
+#define GL2PS_BEGIN_STIPPLE_TOKEN  5
+#define GL2PS_END_STIPPLE_TOKEN    6
+#define GL2PS_POINT_SIZE_TOKEN     7
+#define GL2PS_LINE_WIDTH_TOKEN     8
+#define GL2PS_BEGIN_BLEND_TOKEN    9
+#define GL2PS_END_BLEND_TOKEN      10
+#define GL2PS_SRC_BLEND_TOKEN      11
+#define GL2PS_DST_BLEND_TOKEN      12
+#define GL2PS_IMAGEMAP_TOKEN       13
+#define GL2PS_DRAW_PIXELS_TOKEN    14
+#define GL2PS_TEXT_TOKEN           15
+
+typedef enum {
+  T_UNDEFINED    = -1,
+  T_CONST_COLOR  = 1,
+  T_VAR_COLOR    = 1<<1,
+  T_ALPHA_1      = 1<<2,
+  T_ALPHA_LESS_1 = 1<<3,
+  T_VAR_ALPHA    = 1<<4
+} GL2PS_TRIANGLE_PROPERTY;
+
+typedef GLfloat GL2PSxyz[3];
+typedef GLfloat GL2PSplane[4];
+
+typedef struct _GL2PSbsptree2d GL2PSbsptree2d;
+
+struct _GL2PSbsptree2d {
+  GL2PSplane plane;
+  GL2PSbsptree2d *front, *back;
+};
+
+typedef struct {
+  GLint nmax, size, incr, n;
+  char *array;
+} GL2PSlist;
+
+typedef struct _GL2PSbsptree GL2PSbsptree;
+
+struct _GL2PSbsptree {
+  GL2PSplane plane;
+  GL2PSlist *primitives;
+  GL2PSbsptree *front, *back;
+};
+
+typedef struct {
+  GL2PSxyz xyz;
+  GL2PSrgba rgba;
+} GL2PSvertex;
+
+typedef struct {
+  GL2PSvertex vertex[3];
+  int prop;
+} GL2PStriangle;
+
+typedef struct {
+  GLshort fontsize;
+  char *str, *fontname;
+  /* Note: for a 'special' string, 'alignment' holds the format
+     (PostScript, PDF, etc.) of the special string */
+  GLint alignment;
+  GLfloat angle;
+} GL2PSstring;
+
+typedef struct {
+  GLsizei width, height;
+  /* Note: for an imagemap, 'type' indicates if it has already been
+     written to the file or not, and 'format' indicates if it is
+     visible or not */
+  GLenum format, type;
+  GLfloat zoom_x, zoom_y;
+  GLfloat *pixels;
+} GL2PSimage;
+
+typedef struct _GL2PSimagemap GL2PSimagemap;
+
+struct _GL2PSimagemap {
+  GL2PSimage *image;
+  GL2PSimagemap *next;
+};
+
+typedef struct {
+  GLshort type, numverts;
+  GLushort pattern;
+  char boundary, offset, culled;
+  GLint factor;
+  GLfloat width;
+  GL2PSvertex *verts;
+  union {
+    GL2PSstring *text;
+    GL2PSimage *image;
+  } data;
+} GL2PSprimitive;
+
+typedef struct {
+#if defined(GL2PS_HAVE_ZLIB)
+  Bytef *dest, *src, *start;
+  uLongf destLen, srcLen;
+#else
+  int dummy;
+#endif
+} GL2PScompress;
+
+typedef struct{
+  GL2PSlist* ptrlist;
+  int gsno, fontno, imno, shno, maskshno, trgroupno;
+  int gsobjno, fontobjno, imobjno, shobjno, maskshobjno, trgroupobjno;
+} GL2PSpdfgroup;
+
+typedef struct {
+  /* General */
+  GLint format, sort, options, colorsize, colormode, buffersize;
+  char *title, *producer, *filename;
+  GLboolean boundary, blending;
+  GLfloat *feedback, offset[2], lastlinewidth;
+  GLint viewport[4], blendfunc[2], lastfactor;
+  GL2PSrgba *colormap, lastrgba, threshold, bgcolor;
+  GLushort lastpattern;
+  GL2PSvertex lastvertex;
+  GL2PSlist *primitives, *auxprimitives;
+  FILE *stream;
+  GL2PScompress *compress;
+  GLboolean header;
+
+  /* BSP-specific */
+  GLint maxbestroot;
+
+  /* Occlusion culling-specific */
+  GLboolean zerosurfacearea;
+  GL2PSbsptree2d *imagetree;
+  GL2PSprimitive *primitivetoadd;
+
+  /* PDF-specific */
+  int streamlength;
+  GL2PSlist *pdfprimlist, *pdfgrouplist;
+  int *xreflist;
+  int objects_stack; /* available objects */
+  int extgs_stack; /* graphics state object number */
+  int font_stack; /* font object number */
+  int im_stack; /* image object number */
+  int trgroupobjects_stack; /* xobject numbers */
+  int shader_stack; /* shader object numbers */
+  int mshader_stack; /* mask shader object numbers */
+
+  /* for image map list */
+  GL2PSimagemap *imagemap_head;
+  GL2PSimagemap *imagemap_tail;
+} GL2PScontext;
+
+typedef struct {
+  void  (*printHeader)(void);
+  void  (*printFooter)(void);
+  void  (*beginViewport)(GLint viewport[4]);
+  GLint (*endViewport)(void);
+  void  (*printPrimitive)(void *data);
+  void  (*printFinalPrimitive)(void);
+  const char *file_extension;
+  const char *description;
+} GL2PSbackend;
+
+/* The gl2ps context. gl2ps is not thread safe (we should create a
+   local GL2PScontext during gl2psBeginPage) */
+
+static GL2PScontext *gl2ps = NULL;
+
+/* Need to forward-declare this one */
+
+static GLint gl2psPrintPrimitives(void);
+
+/*********************************************************************
+ *
+ * Utility routines
+ *
+ *********************************************************************/
+
+static void gl2psMsg(GLint level, const char *fmt, ...)
+{
+  va_list args;
+
+  if(!(gl2ps->options & GL2PS_SILENT)){
+    switch(level){
+    case GL2PS_INFO : fprintf(stderr, "GL2PS info: "); break;
+    case GL2PS_WARNING : fprintf(stderr, "GL2PS warning: "); break;
+    case GL2PS_ERROR : fprintf(stderr, "GL2PS error: "); break;
+    }
+    va_start(args, fmt);
+    vfprintf(stderr, fmt, args);
+    va_end(args);
+    fprintf(stderr, "\n");
+  }
+  /* if(level == GL2PS_ERROR) exit(1); */
+}
+
+static void *gl2psMalloc(size_t size)
+{
+  void *ptr;
+
+  if(!size) return NULL;
+  ptr = malloc(size);
+  if(!ptr){
+    gl2psMsg(GL2PS_ERROR, "Couldn't allocate requested memory");
+    return NULL;
+  }
+  return ptr;
+}
+
+static void *gl2psRealloc(void *ptr, size_t size)
+{
+  void *orig = ptr;
+  if(!size) return NULL;
+  ptr = realloc(orig, size);
+  if(!ptr){
+    gl2psMsg(GL2PS_ERROR, "Couldn't reallocate requested memory");
+    free(orig);
+    return NULL;
+  }
+  return ptr;
+}
+
+static void gl2psFree(void *ptr)
+{
+  if(!ptr) return;
+  free(ptr);
+}
+
+static int gl2psWriteBigEndian(unsigned long data, int bytes)
+{
+  int i;
+  int size = sizeof(unsigned long);
+  for(i = 1; i <= bytes; ++i){
+    fputc(0xff & (data >> (size - i) * 8), gl2ps->stream);
+  }
+  return bytes;
+}
+
+/* zlib compression helper routines */
+
+#if defined(GL2PS_HAVE_ZLIB)
+
+static void gl2psSetupCompress(void)
+{
+  gl2ps->compress = (GL2PScompress*)gl2psMalloc(sizeof(GL2PScompress));
+  gl2ps->compress->src = NULL;
+  gl2ps->compress->start = NULL;
+  gl2ps->compress->dest = NULL;
+  gl2ps->compress->srcLen = 0;
+  gl2ps->compress->destLen = 0;
+}
+
+static void gl2psFreeCompress(void)
+{
+  if(!gl2ps->compress)
+    return;
+  gl2psFree(gl2ps->compress->start);
+  gl2psFree(gl2ps->compress->dest);
+  gl2ps->compress->src = NULL;
+  gl2ps->compress->start = NULL;
+  gl2ps->compress->dest = NULL;
+  gl2ps->compress->srcLen = 0;
+  gl2ps->compress->destLen = 0;
+}
+
+static int gl2psAllocCompress(unsigned int srcsize)
+{
+  gl2psFreeCompress();
+
+  if(!gl2ps->compress || !srcsize)
+    return GL2PS_ERROR;
+
+  gl2ps->compress->srcLen = srcsize;
+  gl2ps->compress->destLen = (int)ceil(1.001 * gl2ps->compress->srcLen + 12);
+  gl2ps->compress->src = (Bytef*)gl2psMalloc(gl2ps->compress->srcLen);
+  gl2ps->compress->start = gl2ps->compress->src;
+  gl2ps->compress->dest = (Bytef*)gl2psMalloc(gl2ps->compress->destLen);
+
+  return GL2PS_SUCCESS;
+}
+
+static void *gl2psReallocCompress(unsigned int srcsize)
+{
+  if(!gl2ps->compress || !srcsize)
+    return NULL;
+
+  if(srcsize < gl2ps->compress->srcLen)
+    return gl2ps->compress->start;
+
+  gl2ps->compress->srcLen = srcsize;
+  gl2ps->compress->destLen = (int)ceil(1.001 * gl2ps->compress->srcLen + 12);
+  gl2ps->compress->src = (Bytef*)gl2psRealloc(gl2ps->compress->src,
+                                              gl2ps->compress->srcLen);
+  gl2ps->compress->start = gl2ps->compress->src;
+  gl2ps->compress->dest = (Bytef*)gl2psRealloc(gl2ps->compress->dest,
+                                               gl2ps->compress->destLen);
+
+  return gl2ps->compress->start;
+}
+
+static int gl2psWriteBigEndianCompress(unsigned long data, int bytes)
+{
+  int i;
+  int size = sizeof(unsigned long);
+  for(i = 1; i <= bytes; ++i){
+    *gl2ps->compress->src = (Bytef)(0xff & (data >> (size-i) * 8));
+    ++gl2ps->compress->src;
+  }
+  return bytes;
+}
+
+static int gl2psDeflate(void)
+{
+  /* For compatibility with older zlib versions, we use compress(...)
+     instead of compress2(..., Z_BEST_COMPRESSION) */
+  return compress(gl2ps->compress->dest, &gl2ps->compress->destLen,
+                  gl2ps->compress->start, gl2ps->compress->srcLen);
+}
+
+#endif
+
+static int gl2psPrintf(const char* fmt, ...)
+{
+  int ret;
+  va_list args;
+
+#if defined(GL2PS_HAVE_ZLIB)
+  unsigned int oldsize = 0;
+  static char buf[1000];
+  if(gl2ps->options & GL2PS_COMPRESS){
+    va_start(args, fmt);
+    ret = vsprintf(buf, fmt, args);
+    va_end(args);
+    oldsize = gl2ps->compress->srcLen;
+    gl2ps->compress->start = (Bytef*)gl2psReallocCompress(oldsize + ret);
+    memcpy(gl2ps->compress->start+oldsize, buf, ret);
+    ret = 0;
+  }
+  else{
+#endif
+    va_start(args, fmt);
+    ret = vfprintf(gl2ps->stream, fmt, args);
+    va_end(args);
+#if defined(GL2PS_HAVE_ZLIB)
+  }
+#endif
+  return ret;
+}
+
+static void gl2psPrintGzipHeader(void)
+{
+#if defined(GL2PS_HAVE_ZLIB)
+  char tmp[10] = {'\x1f', '\x8b', /* magic numbers: 0x1f, 0x8b */
+                  8, /* compression method: Z_DEFLATED */
+                  0, /* flags */
+                  0, 0, 0, 0, /* time */
+                  2, /* extra flags: max compression */
+                  '\x03'}; /* OS code: 0x03 (Unix) */
+
+  if(gl2ps->options & GL2PS_COMPRESS){
+    gl2psSetupCompress();
+    /* add the gzip file header */
+    fwrite(tmp, 10, 1, gl2ps->stream);
+  }
+#endif
+}
+
+static void gl2psPrintGzipFooter(void)
+{
+#if defined(GL2PS_HAVE_ZLIB)
+  int n;
+  uLong crc, len;
+  char tmp[8];
+
+  if(gl2ps->options & GL2PS_COMPRESS){
+    if(Z_OK != gl2psDeflate()){
+      gl2psMsg(GL2PS_ERROR, "Zlib deflate error");
+    }
+    else{
+      /* determine the length of the header in the zlib stream */
+      n = 2; /* CMF+FLG */
+      if(gl2ps->compress->dest[1] & (1<<5)){
+        n += 4; /* DICTID */
+      }
+      /* write the data, without the zlib header and footer */
+      fwrite(gl2ps->compress->dest+n, gl2ps->compress->destLen-(n+4),
+             1, gl2ps->stream);
+      /* add the gzip file footer */
+      crc = crc32(0L, gl2ps->compress->start, gl2ps->compress->srcLen);
+      for(n = 0; n < 4; ++n){
+        tmp[n] = (char)(crc & 0xff);
+        crc >>= 8;
+      }
+      len = gl2ps->compress->srcLen;
+      for(n = 4; n < 8; ++n){
+        tmp[n] = (char)(len & 0xff);
+        len >>= 8;
+      }
+      fwrite(tmp, 8, 1, gl2ps->stream);
+    }
+    gl2psFreeCompress();
+    gl2psFree(gl2ps->compress);
+    gl2ps->compress = NULL;
+  }
+#endif
+}
+
+/* The list handling routines */
+
+static void gl2psListRealloc(GL2PSlist *list, GLint n)
+{
+  if(!list){
+    gl2psMsg(GL2PS_ERROR, "Cannot reallocate NULL list");
+    return;
+  }
+  if(n <= 0) return;
+  if(!list->array){
+    list->nmax = n;
+    list->array = (char*)gl2psMalloc(list->nmax * list->size);
+  }
+  else{
+    if(n > list->nmax){
+      list->nmax = ((n - 1) / list->incr + 1) * list->incr;
+      list->array = (char*)gl2psRealloc(list->array,
+                                        list->nmax * list->size);
+    }
+  }
+}
+
+static GL2PSlist *gl2psListCreate(GLint n, GLint incr, GLint size)
+{
+  GL2PSlist *list;
+
+  if(n < 0) n = 0;
+  if(incr <= 0) incr = 1;
+  list = (GL2PSlist*)gl2psMalloc(sizeof(GL2PSlist));
+  list->nmax = 0;
+  list->incr = incr;
+  list->size = size;
+  list->n = 0;
+  list->array = NULL;
+  gl2psListRealloc(list, n);
+  return list;
+}
+
+static void gl2psListReset(GL2PSlist *list)
+{
+  if(!list) return;
+  list->n = 0;
+}
+
+static void gl2psListDelete(GL2PSlist *list)
+{
+  if(!list) return;
+  gl2psFree(list->array);
+  gl2psFree(list);
+}
+
+static void gl2psListAdd(GL2PSlist *list, void *data)
+{
+  if(!list){
+    gl2psMsg(GL2PS_ERROR, "Cannot add into unallocated list");
+    return;
+  }
+  list->n++;
+  gl2psListRealloc(list, list->n);
+  memcpy(&list->array[(list->n - 1) * list->size], data, list->size);
+}
+
+static int gl2psListNbr(GL2PSlist *list)
+{
+  if(!list)
+    return 0;
+  return list->n;
+}
+
+static void *gl2psListPointer(GL2PSlist *list, GLint index)
+{
+  if(!list){
+    gl2psMsg(GL2PS_ERROR, "Cannot point into unallocated list");
+    return NULL;
+  }
+  if((index < 0) || (index >= list->n)){
+    gl2psMsg(GL2PS_ERROR, "Wrong list index in gl2psListPointer");
+    return NULL;
+  }
+  return &list->array[index * list->size];
+}
+
+static void gl2psListSort(GL2PSlist *list,
+                          int (*fcmp)(const void *a, const void *b))
+{
+  if(!list)
+    return;
+  qsort(list->array, list->n, list->size, fcmp);
+}
+
+static void gl2psListAction(GL2PSlist *list, void (*action)(void *data))
+{
+  GLint i;
+
+  for(i = 0; i < gl2psListNbr(list); i++){
+    (*action)(gl2psListPointer(list, i));
+  }
+}
+
+static void gl2psListActionInverse(GL2PSlist *list, void (*action)(void *data))
+{
+  GLint i;
+
+  for(i = gl2psListNbr(list); i > 0; i--){
+    (*action)(gl2psListPointer(list, i-1));
+  }
+}
+
+#if defined(GL2PS_HAVE_LIBPNG)
+
+static void gl2psListRead(GL2PSlist *list, int index, void *data)
+{
+  if((index < 0) || (index >= list->n))
+    gl2psMsg(GL2PS_ERROR, "Wrong list index in gl2psListRead");
+  memcpy(data, &list->array[index * list->size], list->size);
+}
+
+static void gl2psEncodeBase64Block(unsigned char in[3], unsigned char out[4], int len)
+{
+  static const char cb64[] =
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+  out[0] = cb64[ in[0] >> 2 ];
+  out[1] = cb64[ ((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4) ];
+  out[2] = (len > 1) ? cb64[ ((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6) ] : '=';
+  out[3] = (len > 2) ? cb64[ in[2] & 0x3f ] : '=';
+}
+
+static void gl2psListEncodeBase64(GL2PSlist *list)
+{
+  unsigned char *buffer, in[3], out[4];
+  int i, n, index, len;
+
+  n = list->n * list->size;
+  buffer = (unsigned char*)gl2psMalloc(n * sizeof(unsigned char));
+  memcpy(buffer, list->array, n * sizeof(unsigned char));
+  gl2psListReset(list);
+
+  index = 0;
+  while(index < n) {
+    len = 0;
+    for(i = 0; i < 3; i++) {
+      if(index < n){
+        in[i] = buffer[index];
+        len++;
+      }
+      else{
+        in[i] = 0;
+      }
+      index++;
+    }
+    if(len) {
+      gl2psEncodeBase64Block(in, out, len);
+      for(i = 0; i < 4; i++)
+        gl2psListAdd(list, &out[i]);
+    }
+  }
+  gl2psFree(buffer);
+}
+
+#endif
+
+/* Helpers for rgba colors */
+
+static GLboolean gl2psSameColor(GL2PSrgba rgba1, GL2PSrgba rgba2)
+{
+  if(!GL2PS_ZERO(rgba1[0] - rgba2[0]) ||
+     !GL2PS_ZERO(rgba1[1] - rgba2[1]) ||
+     !GL2PS_ZERO(rgba1[2] - rgba2[2]))
+    return GL_FALSE;
+  return GL_TRUE;
+}
+
+static GLboolean gl2psVertsSameColor(const GL2PSprimitive *prim)
+{
+  int i;
+
+  for(i = 1; i < prim->numverts; i++){
+    if(!gl2psSameColor(prim->verts[0].rgba, prim->verts[i].rgba)){
+      return GL_FALSE;
+    }
+  }
+  return GL_TRUE;
+}
+
+static GLboolean gl2psSameColorThreshold(int n, GL2PSrgba rgba[],
+                                         GL2PSrgba threshold)
+{
+  int i;
+
+  if(n < 2) return GL_TRUE;
+
+  for(i = 1; i < n; i++){
+    if(fabs(rgba[0][0] - rgba[i][0]) > threshold[0] ||
+       fabs(rgba[0][1] - rgba[i][1]) > threshold[1] ||
+       fabs(rgba[0][2] - rgba[i][2]) > threshold[2])
+      return GL_FALSE;
+  }
+
+  return GL_TRUE;
+}
+
+static void gl2psSetLastColor(GL2PSrgba rgba)
+{
+  int i;
+  for(i = 0; i < 3; ++i){
+    gl2ps->lastrgba[i] = rgba[i];
+  }
+}
+
+static GLfloat gl2psGetRGB(GL2PSimage *im, GLuint x, GLuint y,
+                           GLfloat *red, GLfloat *green, GLfloat *blue)
+{
+
+  GLsizei width = im->width;
+  GLsizei height = im->height;
+  GLfloat *pixels = im->pixels;
+  GLfloat *pimag;
+
+  /* OpenGL image is from down to up, PS image is up to down */
+  switch(im->format){
+  case GL_RGBA:
+    pimag = pixels + 4 * (width * (height - 1 - y) + x);
+    break;
+  case GL_RGB:
+  default:
+    pimag = pixels + 3 * (width * (height - 1 - y) + x);
+    break;
+  }
+  *red = *pimag; pimag++;
+  *green = *pimag; pimag++;
+  *blue = *pimag; pimag++;
+
+  return (im->format == GL_RGBA) ? *pimag : 1.0F;
+}
+
+/* Helper routines for pixmaps */
+
+static GL2PSimage *gl2psCopyPixmap(GL2PSimage *im)
+{
+  int size;
+  GL2PSimage *image = (GL2PSimage*)gl2psMalloc(sizeof(GL2PSimage));
+
+  image->width = im->width;
+  image->height = im->height;
+  image->format = im->format;
+  image->type = im->type;
+  image->zoom_x = im->zoom_x;
+  image->zoom_y = im->zoom_y;
+
+  switch(image->format){
+  case GL_RGBA:
+    size = image->height * image->width * 4 * sizeof(GLfloat);
+    break;
+  case GL_RGB:
+  default:
+    size = image->height * image->width * 3 * sizeof(GLfloat);
+    break;
+  }
+
+  image->pixels = (GLfloat*)gl2psMalloc(size);
+  memcpy(image->pixels, im->pixels, size);
+
+  return image;
+}
+
+static void gl2psFreePixmap(GL2PSimage *im)
+{
+  if(!im)
+    return;
+  gl2psFree(im->pixels);
+  gl2psFree(im);
+}
+
+#if defined(GL2PS_HAVE_LIBPNG)
+
+#if !defined(png_jmpbuf)
+#  define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf)
+#endif
+
+static void gl2psUserWritePNG(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+  unsigned int i;
+  GL2PSlist *png = (GL2PSlist*)png_get_io_ptr(png_ptr);
+  for(i = 0; i < length; i++)
+    gl2psListAdd(png, &data[i]);
+}
+
+static void gl2psUserFlushPNG(png_structp png_ptr)
+{
+  (void) png_ptr;  /* not used */
+}
+
+static void gl2psConvertPixmapToPNG(GL2PSimage *pixmap, GL2PSlist *png)
+{
+  png_structp png_ptr;
+  png_infop info_ptr;
+  unsigned char *row_data;
+  GLfloat dr, dg, db;
+  int row, col;
+
+  if(!(png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)))
+    return;
+
+  if(!(info_ptr = png_create_info_struct(png_ptr))){
+    png_destroy_write_struct(&png_ptr, NULL);
+    return;
+  }
+
+  if(setjmp(png_jmpbuf(png_ptr))) {
+    png_destroy_write_struct(&png_ptr, &info_ptr);
+    return;
+  }
+
+  png_set_write_fn(png_ptr, (void *)png, gl2psUserWritePNG, gl2psUserFlushPNG);
+  png_set_compression_level(png_ptr, Z_DEFAULT_COMPRESSION);
+  png_set_IHDR(png_ptr, info_ptr, pixmap->width, pixmap->height, 8,
+               PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
+               PNG_FILTER_TYPE_BASE);
+  png_write_info(png_ptr, info_ptr);
+
+  row_data = (unsigned char*)gl2psMalloc(3 * pixmap->width * sizeof(unsigned char));
+  for(row = 0; row < pixmap->height; row++){
+    for(col = 0; col < pixmap->width; col++){
+      gl2psGetRGB(pixmap, col, row, &dr, &dg, &db);
+      row_data[3*col] = (unsigned char)(255. * dr);
+      row_data[3*col+1] = (unsigned char)(255. * dg);
+      row_data[3*col+2] = (unsigned char)(255. * db);
+    }
+    png_write_row(png_ptr, (png_bytep)row_data);
+  }
+  gl2psFree(row_data);
+
+  png_write_end(png_ptr, info_ptr);
+  png_destroy_write_struct(&png_ptr, &info_ptr);
+}
+
+#endif
+
+/* Helper routines for text strings */
+
+static GLint gl2psAddText(GLint type, const char *str, const char *fontname,
+                          GLshort fontsize, GLint alignment, GLfloat angle)
+{
+  GLfloat pos[4];
+  GL2PSprimitive *prim;
+  GLboolean valid;
+
+  if(!gl2ps || !str || !fontname) return GL2PS_UNINITIALIZED;
+
+  if(gl2ps->options & GL2PS_NO_TEXT) return GL2PS_SUCCESS;
+
+  glGetBooleanv(GL_CURRENT_RASTER_POSITION_VALID, &valid);
+  if(GL_FALSE == valid) return GL2PS_SUCCESS; /* the primitive is culled */
+
+  glGetFloatv(GL_CURRENT_RASTER_POSITION, pos);
+
+  prim = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
+  prim->type = type;
+  prim->boundary = 0;
+  prim->numverts = 1;
+  prim->verts = (GL2PSvertex*)gl2psMalloc(sizeof(GL2PSvertex));
+  prim->verts[0].xyz[0] = pos[0];
+  prim->verts[0].xyz[1] = pos[1];
+  prim->verts[0].xyz[2] = pos[2];
+  prim->culled = 0;
+  prim->offset = 0;
+  prim->pattern = 0;
+  prim->factor = 0;
+  prim->width = 1;
+  glGetFloatv(GL_CURRENT_RASTER_COLOR, prim->verts[0].rgba);
+  prim->data.text = (GL2PSstring*)gl2psMalloc(sizeof(GL2PSstring));
+  prim->data.text->str = (char*)gl2psMalloc((strlen(str)+1)*sizeof(char));
+  strcpy(prim->data.text->str, str);
+  prim->data.text->fontname = (char*)gl2psMalloc((strlen(fontname)+1)*sizeof(char));
+  strcpy(prim->data.text->fontname, fontname);
+  prim->data.text->fontsize = fontsize;
+  prim->data.text->alignment = alignment;
+  prim->data.text->angle = angle;
+
+  gl2psListAdd(gl2ps->auxprimitives, &prim);
+  glPassThrough(GL2PS_TEXT_TOKEN);
+
+  return GL2PS_SUCCESS;
+}
+
+static GL2PSstring *gl2psCopyText(GL2PSstring *t)
+{
+  GL2PSstring *text = (GL2PSstring*)gl2psMalloc(sizeof(GL2PSstring));
+  text->str = (char*)gl2psMalloc((strlen(t->str)+1)*sizeof(char));
+  strcpy(text->str, t->str);
+  text->fontname = (char*)gl2psMalloc((strlen(t->fontname)+1)*sizeof(char));
+  strcpy(text->fontname, t->fontname);
+  text->fontsize = t->fontsize;
+  text->alignment = t->alignment;
+  text->angle = t->angle;
+
+  return text;
+}
+
+static void gl2psFreeText(GL2PSstring *text)
+{
+  if(!text)
+    return;
+  gl2psFree(text->str);
+  gl2psFree(text->fontname);
+  gl2psFree(text);
+}
+
+/* Helpers for blending modes */
+
+static GLboolean gl2psSupportedBlendMode(GLenum sfactor, GLenum dfactor)
+{
+  /* returns TRUE if gl2ps supports the argument combination: only two
+     blending modes have been implemented so far */
+
+  if( (sfactor == GL_SRC_ALPHA && dfactor == GL_ONE_MINUS_SRC_ALPHA) ||
+      (sfactor == GL_ONE && dfactor == GL_ZERO) )
+    return GL_TRUE;
+  return GL_FALSE;
+}
+
+static void gl2psAdaptVertexForBlending(GL2PSvertex *v)
+{
+  /* Transforms vertex depending on the actual blending function -
+     currently the vertex v is considered as source vertex and his
+     alpha value is changed to 1.0 if source blending GL_ONE is
+     active. This might be extended in the future */
+
+  if(!v || !gl2ps)
+    return;
+
+  if(gl2ps->options & GL2PS_NO_BLENDING || !gl2ps->blending){
+    v->rgba[3] = 1.0F;
+    return;
+  }
+
+  switch(gl2ps->blendfunc[0]){
+  case GL_ONE:
+    v->rgba[3] = 1.0F;
+    break;
+  default:
+    break;
+  }
+}
+
+static void gl2psAssignTriangleProperties(GL2PStriangle *t)
+{
+  /* int i; */
+
+  t->prop = T_VAR_COLOR;
+
+  /* Uncommenting the following lines activates an even more fine
+     grained distinction between triangle types - please don't delete,
+     a remarkable amount of PDF handling code inside this file depends
+     on it if activated */
+  /*
+  t->prop = T_CONST_COLOR;
+  for(i = 0; i < 3; ++i){
+    if(!GL2PS_ZERO(t->vertex[0].rgba[i] - t->vertex[1].rgba[i]) ||
+       !GL2PS_ZERO(t->vertex[1].rgba[i] - t->vertex[2].rgba[i])){
+      t->prop = T_VAR_COLOR;
+      break;
+    }
+  }
+  */
+
+  if(!GL2PS_ZERO(t->vertex[0].rgba[3] - t->vertex[1].rgba[3]) ||
+     !GL2PS_ZERO(t->vertex[1].rgba[3] - t->vertex[2].rgba[3])){
+    t->prop |= T_VAR_ALPHA;
+  }
+  else{
+    if(t->vertex[0].rgba[3] < 1)
+      t->prop |= T_ALPHA_LESS_1;
+    else
+      t->prop |= T_ALPHA_1;
+  }
+}
+
+static void gl2psFillTriangleFromPrimitive(GL2PStriangle *t, GL2PSprimitive *p,
+                                           GLboolean assignprops)
+{
+  t->vertex[0] = p->verts[0];
+  t->vertex[1] = p->verts[1];
+  t->vertex[2] = p->verts[2];
+  if(GL_TRUE == assignprops)
+    gl2psAssignTriangleProperties(t);
+}
+
+static void gl2psInitTriangle(GL2PStriangle *t)
+{
+  int i;
+  GL2PSvertex vertex = { {-1.0F, -1.0F, -1.0F}, {-1.0F, -1.0F, -1.0F, -1.0F} };
+  for(i = 0; i < 3; i++)
+    t->vertex[i] = vertex;
+  t->prop = T_UNDEFINED;
+}
+
+/* Miscellaneous helper routines */
+
+static GL2PSprimitive *gl2psCopyPrimitive(GL2PSprimitive *p)
+{
+  GL2PSprimitive *prim;
+
+  if(!p){
+    gl2psMsg(GL2PS_ERROR, "Trying to copy an empty primitive");
+    return NULL;
+  }
+
+  prim = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
+
+  prim->type = p->type;
+  prim->numverts = p->numverts;
+  prim->boundary = p->boundary;
+  prim->offset = p->offset;
+  prim->pattern = p->pattern;
+  prim->factor = p->factor;
+  prim->culled = p->culled;
+  prim->width = p->width;
+  prim->verts = (GL2PSvertex*)gl2psMalloc(p->numverts*sizeof(GL2PSvertex));
+  memcpy(prim->verts, p->verts, p->numverts * sizeof(GL2PSvertex));
+
+  switch(prim->type){
+  case GL2PS_PIXMAP :
+    prim->data.image = gl2psCopyPixmap(p->data.image);
+    break;
+  case GL2PS_TEXT :
+  case GL2PS_SPECIAL :
+    prim->data.text = gl2psCopyText(p->data.text);
+    break;
+  default:
+    break;
+  }
+
+  return prim;
+}
+
+static GLboolean gl2psSamePosition(GL2PSxyz p1, GL2PSxyz p2)
+{
+  if(!GL2PS_ZERO(p1[0] - p2[0]) ||
+     !GL2PS_ZERO(p1[1] - p2[1]) ||
+     !GL2PS_ZERO(p1[2] - p2[2]))
+    return GL_FALSE;
+  return GL_TRUE;
+}
+
+/*********************************************************************
+ *
+ * 3D sorting routines
+ *
+ *********************************************************************/
+
+static GLfloat gl2psComparePointPlane(GL2PSxyz point, GL2PSplane plane)
+{
+  return (plane[0] * point[0] +
+          plane[1] * point[1] +
+          plane[2] * point[2] +
+          plane[3]);
+}
+
+static GLfloat gl2psPsca(GLfloat *a, GLfloat *b)
+{
+  return (a[0]*b[0] + a[1]*b[1] + a[2]*b[2]);
+}
+
+static void gl2psPvec(GLfloat *a, GLfloat *b, GLfloat *c)
+{
+  c[0] = a[1]*b[2] - a[2]*b[1];
+  c[1] = a[2]*b[0] - a[0]*b[2];
+  c[2] = a[0]*b[1] - a[1]*b[0];
+}
+
+static GLfloat gl2psNorm(GLfloat *a)
+{
+  return (GLfloat)sqrt(a[0]*a[0] + a[1]*a[1] + a[2]*a[2]);
+}
+
+static void gl2psGetNormal(GLfloat *a, GLfloat *b, GLfloat *c)
+{
+  GLfloat norm;
+
+  gl2psPvec(a, b, c);
+  if(!GL2PS_ZERO(norm = gl2psNorm(c))){
+    c[0] = c[0] / norm;
+    c[1] = c[1] / norm;
+    c[2] = c[2] / norm;
+  }
+  else{
+    /* The plane is still wrong despite our tests in gl2psGetPlane.
+       Let's return a dummy value for now (this is a hack: we should
+       do more intelligent tests in GetPlane) */
+    c[0] = c[1] = 0.0F;
+    c[2] = 1.0F;
+  }
+}
+
+static void gl2psGetPlane(GL2PSprimitive *prim, GL2PSplane plane)
+{
+  GL2PSxyz v = {0.0F, 0.0F, 0.0F}, w = {0.0F, 0.0F, 0.0F};
+
+  switch(prim->type){
+  case GL2PS_TRIANGLE :
+  case GL2PS_QUADRANGLE :
+    v[0] = prim->verts[1].xyz[0] - prim->verts[0].xyz[0];
+    v[1] = prim->verts[1].xyz[1] - prim->verts[0].xyz[1];
+    v[2] = prim->verts[1].xyz[2] - prim->verts[0].xyz[2];
+    w[0] = prim->verts[2].xyz[0] - prim->verts[0].xyz[0];
+    w[1] = prim->verts[2].xyz[1] - prim->verts[0].xyz[1];
+    w[2] = prim->verts[2].xyz[2] - prim->verts[0].xyz[2];
+    if((GL2PS_ZERO(v[0]) && GL2PS_ZERO(v[1]) && GL2PS_ZERO(v[2])) ||
+       (GL2PS_ZERO(w[0]) && GL2PS_ZERO(w[1]) && GL2PS_ZERO(w[2]))){
+      plane[0] = plane[1] = 0.0F;
+      plane[2] = 1.0F;
+      plane[3] = -prim->verts[0].xyz[2];
+    }
+    else{
+      gl2psGetNormal(v, w, plane);
+      plane[3] =
+        - plane[0] * prim->verts[0].xyz[0]
+        - plane[1] * prim->verts[0].xyz[1]
+        - plane[2] * prim->verts[0].xyz[2];
+    }
+    break;
+  case GL2PS_LINE :
+    v[0] = prim->verts[1].xyz[0] - prim->verts[0].xyz[0];
+    v[1] = prim->verts[1].xyz[1] - prim->verts[0].xyz[1];
+    v[2] = prim->verts[1].xyz[2] - prim->verts[0].xyz[2];
+    if(GL2PS_ZERO(v[0]) && GL2PS_ZERO(v[1]) && GL2PS_ZERO(v[2])){
+      plane[0] = plane[1] = 0.0F;
+      plane[2] = 1.0F;
+      plane[3] = -prim->verts[0].xyz[2];
+    }
+    else{
+      if(GL2PS_ZERO(v[0]))      w[0] = 1.0F;
+      else if(GL2PS_ZERO(v[1])) w[1] = 1.0F;
+      else                      w[2] = 1.0F;
+      gl2psGetNormal(v, w, plane);
+      plane[3] =
+        - plane[0] * prim->verts[0].xyz[0]
+        - plane[1] * prim->verts[0].xyz[1]
+        - plane[2] * prim->verts[0].xyz[2];
+    }
+    break;
+  case GL2PS_POINT :
+  case GL2PS_PIXMAP :
+  case GL2PS_TEXT :
+  case GL2PS_SPECIAL :
+  case GL2PS_IMAGEMAP:
+    plane[0] = plane[1] = 0.0F;
+    plane[2] = 1.0F;
+    plane[3] = -prim->verts[0].xyz[2];
+    break;
+  default :
+    gl2psMsg(GL2PS_ERROR, "Unknown primitive type in BSP tree");
+    plane[0] = plane[1] = plane[3] = 0.0F;
+    plane[2] = 1.0F;
+    break;
+  }
+}
+
+static void gl2psCutEdge(GL2PSvertex *a, GL2PSvertex *b, GL2PSplane plane,
+                         GL2PSvertex *c)
+{
+  GL2PSxyz v;
+  GLfloat sect, psca;
+
+  v[0] = b->xyz[0] - a->xyz[0];
+  v[1] = b->xyz[1] - a->xyz[1];
+  v[2] = b->xyz[2] - a->xyz[2];
+
+  if(!GL2PS_ZERO(psca = gl2psPsca(plane, v)))
+    sect = -gl2psComparePointPlane(a->xyz, plane) / psca;
+  else
+    sect = 0.0F;
+
+  c->xyz[0] = a->xyz[0] + v[0] * sect;
+  c->xyz[1] = a->xyz[1] + v[1] * sect;
+  c->xyz[2] = a->xyz[2] + v[2] * sect;
+
+  c->rgba[0] = (1 - sect) * a->rgba[0] + sect * b->rgba[0];
+  c->rgba[1] = (1 - sect) * a->rgba[1] + sect * b->rgba[1];
+  c->rgba[2] = (1 - sect) * a->rgba[2] + sect * b->rgba[2];
+  c->rgba[3] = (1 - sect) * a->rgba[3] + sect * b->rgba[3];
+}
+
+static void gl2psCreateSplitPrimitive(GL2PSprimitive *parent, GL2PSplane plane,
+                                      GL2PSprimitive *child, GLshort numverts,
+                                      GLshort *index0, GLshort *index1)
+{
+  GLshort i;
+
+  if(parent->type == GL2PS_IMAGEMAP){
+    child->type = GL2PS_IMAGEMAP;
+    child->data.image = parent->data.image;
+  }
+  else{
+    if(numverts > 4){
+      gl2psMsg(GL2PS_WARNING, "%d vertices in polygon", numverts);
+      numverts = 4;
+    }
+    switch(numverts){
+    case 1 : child->type = GL2PS_POINT; break;
+    case 2 : child->type = GL2PS_LINE; break;
+    case 3 : child->type = GL2PS_TRIANGLE; break;
+    case 4 : child->type = GL2PS_QUADRANGLE; break;
+    default: child->type = GL2PS_NO_TYPE; break;
+    }
+  }
+
+  child->boundary = 0; /* FIXME: not done! */
+  child->culled = parent->culled;
+  child->offset = parent->offset;
+  child->pattern = parent->pattern;
+  child->factor = parent->factor;
+  child->width = parent->width;
+  child->numverts = numverts;
+  child->verts = (GL2PSvertex*)gl2psMalloc(numverts * sizeof(GL2PSvertex));
+
+  for(i = 0; i < numverts; i++){
+    if(index1[i] < 0){
+      child->verts[i] = parent->verts[index0[i]];
+    }
+    else{
+      gl2psCutEdge(&parent->verts[index0[i]], &parent->verts[index1[i]],
+                   plane, &child->verts[i]);
+    }
+  }
+}
+
+static void gl2psAddIndex(GLshort *index0, GLshort *index1, GLshort *nb,
+                          GLshort i, GLshort j)
+{
+  GLint k;
+
+  for(k = 0; k < *nb; k++){
+    if((index0[k] == i && index1[k] == j) ||
+       (index1[k] == i && index0[k] == j)) return;
+  }
+  index0[*nb] = i;
+  index1[*nb] = j;
+  (*nb)++;
+}
+
+static GLshort gl2psGetIndex(GLshort i, GLshort num)
+{
+  return (i < num - 1) ? i + 1 : 0;
+}
+
+static GLint gl2psTestSplitPrimitive(GL2PSprimitive *prim, GL2PSplane plane)
+{
+  GLint type = GL2PS_COINCIDENT;
+  GLshort i, j;
+  GLfloat d[5];
+
+  for(i = 0; i < prim->numverts; i++){
+    d[i] = gl2psComparePointPlane(prim->verts[i].xyz, plane);
+  }
+
+  if(prim->numverts < 2){
+    return 0;
+  }
+  else{
+    for(i = 0; i < prim->numverts; i++){
+      j = gl2psGetIndex(i, prim->numverts);
+      if(d[j] > GL2PS_EPSILON){
+        if(type == GL2PS_COINCIDENT)      type = GL2PS_IN_BACK_OF;
+        else if(type != GL2PS_IN_BACK_OF) return 1;
+        if(d[i] < -GL2PS_EPSILON)         return 1;
+      }
+      else if(d[j] < -GL2PS_EPSILON){
+        if(type == GL2PS_COINCIDENT)       type = GL2PS_IN_FRONT_OF;
+        else if(type != GL2PS_IN_FRONT_OF) return 1;
+        if(d[i] > GL2PS_EPSILON)           return 1;
+      }
+    }
+  }
+  return 0;
+}
+
+static GLint gl2psSplitPrimitive(GL2PSprimitive *prim, GL2PSplane plane,
+                                 GL2PSprimitive **front, GL2PSprimitive **back)
+{
+  GLshort i, j, in = 0, out = 0, in0[5], in1[5], out0[5], out1[5];
+  GLint type;
+  GLfloat d[5];
+
+  type = GL2PS_COINCIDENT;
+
+  for(i = 0; i < prim->numverts; i++){
+    d[i] = gl2psComparePointPlane(prim->verts[i].xyz, plane);
+  }
+
+  switch(prim->type){
+  case GL2PS_POINT :
+    if(d[0] > GL2PS_EPSILON)       type = GL2PS_IN_BACK_OF;
+    else if(d[0] < -GL2PS_EPSILON) type = GL2PS_IN_FRONT_OF;
+    else                           type = GL2PS_COINCIDENT;
+    break;
+  default :
+    for(i = 0; i < prim->numverts; i++){
+      j = gl2psGetIndex(i, prim->numverts);
+      if(d[j] > GL2PS_EPSILON){
+        if(type == GL2PS_COINCIDENT)      type = GL2PS_IN_BACK_OF;
+        else if(type != GL2PS_IN_BACK_OF) type = GL2PS_SPANNING;
+        if(d[i] < -GL2PS_EPSILON){
+          gl2psAddIndex(in0, in1, &in, i, j);
+          gl2psAddIndex(out0, out1, &out, i, j);
+          type = GL2PS_SPANNING;
+        }
+        gl2psAddIndex(out0, out1, &out, j, -1);
+      }
+      else if(d[j] < -GL2PS_EPSILON){
+        if(type == GL2PS_COINCIDENT)       type = GL2PS_IN_FRONT_OF;
+        else if(type != GL2PS_IN_FRONT_OF) type = GL2PS_SPANNING;
+        if(d[i] > GL2PS_EPSILON){
+          gl2psAddIndex(in0, in1, &in, i, j);
+          gl2psAddIndex(out0, out1, &out, i, j);
+          type = GL2PS_SPANNING;
+        }
+        gl2psAddIndex(in0, in1, &in, j, -1);
+      }
+      else{
+        gl2psAddIndex(in0, in1, &in, j, -1);
+        gl2psAddIndex(out0, out1, &out, j, -1);
+      }
+    }
+    break;
+  }
+
+  if(type == GL2PS_SPANNING){
+    *back = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
+    *front = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
+    gl2psCreateSplitPrimitive(prim, plane, *back, out, out0, out1);
+    gl2psCreateSplitPrimitive(prim, plane, *front, in, in0, in1);
+  }
+
+  return type;
+}
+
+static void gl2psDivideQuad(GL2PSprimitive *quad,
+                            GL2PSprimitive **t1, GL2PSprimitive **t2)
+{
+  *t1 = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
+  *t2 = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
+  (*t1)->type = (*t2)->type = GL2PS_TRIANGLE;
+  (*t1)->numverts = (*t2)->numverts = 3;
+  (*t1)->culled = (*t2)->culled = quad->culled;
+  (*t1)->offset = (*t2)->offset = quad->offset;
+  (*t1)->pattern = (*t2)->pattern = quad->pattern;
+  (*t1)->factor = (*t2)->factor = quad->factor;
+  (*t1)->width = (*t2)->width = quad->width;
+  (*t1)->verts = (GL2PSvertex*)gl2psMalloc(3 * sizeof(GL2PSvertex));
+  (*t2)->verts = (GL2PSvertex*)gl2psMalloc(3 * sizeof(GL2PSvertex));
+  (*t1)->verts[0] = quad->verts[0];
+  (*t1)->verts[1] = quad->verts[1];
+  (*t1)->verts[2] = quad->verts[2];
+  (*t1)->boundary = ((quad->boundary & 1) ? 1 : 0) | ((quad->boundary & 2) ? 2 : 0);
+  (*t2)->verts[0] = quad->verts[0];
+  (*t2)->verts[1] = quad->verts[2];
+  (*t2)->verts[2] = quad->verts[3];
+  (*t2)->boundary = ((quad->boundary & 4) ? 2 : 0) | ((quad->boundary & 8) ? 4 : 0);
+}
+
+static int gl2psCompareDepth(const void *a, const void *b)
+{
+  const GL2PSprimitive *q, *w;
+  GLfloat dq = 0.0F, dw = 0.0F, diff;
+  int i;
+
+  q = *(const GL2PSprimitive* const*)a;
+  w = *(const GL2PSprimitive* const*)b;
+
+  for(i = 0; i < q->numverts; i++){
+    dq += q->verts[i].xyz[2];
+  }
+  dq /= (GLfloat)q->numverts;
+
+  for(i = 0; i < w->numverts; i++){
+    dw += w->verts[i].xyz[2];
+  }
+  dw /= (GLfloat)w->numverts;
+
+  diff = dq - dw;
+  if(diff > 0.){
+    return -1;
+  }
+  else if(diff < 0.){
+    return 1;
+  }
+  else{
+    return 0;
+  }
+}
+
+static int gl2psTrianglesFirst(const void *a, const void *b)
+{
+  const GL2PSprimitive *q, *w;
+
+  q = *(const GL2PSprimitive* const*)a;
+  w = *(const GL2PSprimitive* const*)b;
+  return (q->type < w->type ? 1 : -1);
+}
+
+static GLint gl2psFindRoot(GL2PSlist *primitives, GL2PSprimitive **root)
+{
+  GLint i, j, count, best = 1000000, index = 0;
+  GL2PSprimitive *prim1, *prim2;
+  GL2PSplane plane;
+  GLint maxp;
+
+  if(!gl2psListNbr(primitives)){
+    gl2psMsg(GL2PS_ERROR, "Cannot fint root in empty primitive list");
+    return 0;
+  }
+
+  *root = *(GL2PSprimitive**)gl2psListPointer(primitives, 0);
+
+  if(gl2ps->options & GL2PS_BEST_ROOT){
+    maxp = gl2psListNbr(primitives);
+    if(maxp > gl2ps->maxbestroot){
+      maxp = gl2ps->maxbestroot;
+    }
+    for(i = 0; i < maxp; i++){
+      prim1 = *(GL2PSprimitive**)gl2psListPointer(primitives, i);
+      gl2psGetPlane(prim1, plane);
+      count = 0;
+      for(j = 0; j < gl2psListNbr(primitives); j++){
+        if(j != i){
+          prim2 = *(GL2PSprimitive**)gl2psListPointer(primitives, j);
+          count += gl2psTestSplitPrimitive(prim2, plane);
+        }
+        if(count > best) break;
+      }
+      if(count < best){
+        best = count;
+        index = i;
+        *root = prim1;
+        if(!count) return index;
+      }
+    }
+    /* if(index) gl2psMsg(GL2PS_INFO, "GL2PS_BEST_ROOT was worth it: %d", index); */
+    return index;
+  }
+  else{
+    return 0;
+  }
+}
+
+static void gl2psFreeImagemap(GL2PSimagemap *list)
+{
+  GL2PSimagemap *next;
+  while(list != NULL){
+    next = list->next;
+    gl2psFree(list->image->pixels);
+    gl2psFree(list->image);
+    gl2psFree(list);
+    list = next;
+  }
+}
+
+static void gl2psFreePrimitive(void *data)
+{
+  GL2PSprimitive *q;
+
+  q = *(GL2PSprimitive**)data;
+  gl2psFree(q->verts);
+  if(q->type == GL2PS_TEXT || q->type == GL2PS_SPECIAL){
+    gl2psFreeText(q->data.text);
+  }
+  else if(q->type == GL2PS_PIXMAP){
+    gl2psFreePixmap(q->data.image);
+  }
+  gl2psFree(q);
+}
+
+static void gl2psAddPrimitiveInList(GL2PSprimitive *prim, GL2PSlist *list)
+{
+  GL2PSprimitive *t1, *t2;
+
+  if(prim->type != GL2PS_QUADRANGLE){
+    gl2psListAdd(list, &prim);
+  }
+  else{
+    gl2psDivideQuad(prim, &t1, &t2);
+    gl2psListAdd(list, &t1);
+    gl2psListAdd(list, &t2);
+    gl2psFreePrimitive(&prim);
+  }
+
+}
+
+static void gl2psFreeBspTree(GL2PSbsptree **tree)
+{
+  if(*tree){
+    if((*tree)->back) gl2psFreeBspTree(&(*tree)->back);
+    if((*tree)->primitives){
+      gl2psListAction((*tree)->primitives, gl2psFreePrimitive);
+      gl2psListDelete((*tree)->primitives);
+    }
+    if((*tree)->front) gl2psFreeBspTree(&(*tree)->front);
+    gl2psFree(*tree);
+    *tree = NULL;
+  }
+}
+
+static GLboolean gl2psGreater(GLfloat f1, GLfloat f2)
+{
+  if(f1 > f2) return GL_TRUE;
+  else return GL_FALSE;
+}
+
+static GLboolean gl2psLess(GLfloat f1, GLfloat f2)
+{
+  if(f1 < f2) return GL_TRUE;
+  else return GL_FALSE;
+}
+
+static void gl2psBuildBspTree(GL2PSbsptree *tree, GL2PSlist *primitives)
+{
+  GL2PSprimitive *prim, *frontprim = NULL, *backprim = NULL;
+  GL2PSlist *frontlist, *backlist;
+  GLint i, index;
+
+  tree->front = NULL;
+  tree->back = NULL;
+  tree->primitives = gl2psListCreate(1, 2, sizeof(GL2PSprimitive*));
+  index = gl2psFindRoot(primitives, &prim);
+  gl2psGetPlane(prim, tree->plane);
+  gl2psAddPrimitiveInList(prim, tree->primitives);
+
+  frontlist = gl2psListCreate(1, 2, sizeof(GL2PSprimitive*));
+  backlist = gl2psListCreate(1, 2, sizeof(GL2PSprimitive*));
+
+  for(i = 0; i < gl2psListNbr(primitives); i++){
+    if(i != index){
+      prim = *(GL2PSprimitive**)gl2psListPointer(primitives,i);
+      switch(gl2psSplitPrimitive(prim, tree->plane, &frontprim, &backprim)){
+      case GL2PS_COINCIDENT:
+        gl2psAddPrimitiveInList(prim, tree->primitives);
+        break;
+      case GL2PS_IN_BACK_OF:
+        gl2psAddPrimitiveInList(prim, backlist);
+        break;
+      case GL2PS_IN_FRONT_OF:
+        gl2psAddPrimitiveInList(prim, frontlist);
+        break;
+      case GL2PS_SPANNING:
+        gl2psAddPrimitiveInList(backprim, backlist);
+        gl2psAddPrimitiveInList(frontprim, frontlist);
+        gl2psFreePrimitive(&prim);
+        break;
+      }
+    }
+  }
+
+  if(gl2psListNbr(tree->primitives)){
+    gl2psListSort(tree->primitives, gl2psTrianglesFirst);
+  }
+
+  if(gl2psListNbr(frontlist)){
+    gl2psListSort(frontlist, gl2psTrianglesFirst);
+    tree->front = (GL2PSbsptree*)gl2psMalloc(sizeof(GL2PSbsptree));
+    gl2psBuildBspTree(tree->front, frontlist);
+  }
+  else{
+    gl2psListDelete(frontlist);
+  }
+
+  if(gl2psListNbr(backlist)){
+    gl2psListSort(backlist, gl2psTrianglesFirst);
+    tree->back = (GL2PSbsptree*)gl2psMalloc(sizeof(GL2PSbsptree));
+    gl2psBuildBspTree(tree->back, backlist);
+  }
+  else{
+    gl2psListDelete(backlist);
+  }
+
+  gl2psListDelete(primitives);
+}
+
+static void gl2psTraverseBspTree(GL2PSbsptree *tree, GL2PSxyz eye, GLfloat epsilon,
+                                 GLboolean (*compare)(GLfloat f1, GLfloat f2),
+                                 void (*action)(void *data), int inverse)
+{
+  GLfloat result;
+
+  if(!tree) return;
+
+  result = gl2psComparePointPlane(eye, tree->plane);
+
+  if(GL_TRUE == compare(result, epsilon)){
+    gl2psTraverseBspTree(tree->back, eye, epsilon, compare, action, inverse);
+    if(inverse){
+      gl2psListActionInverse(tree->primitives, action);
+    }
+    else{
+      gl2psListAction(tree->primitives, action);
+    }
+    gl2psTraverseBspTree(tree->front, eye, epsilon, compare, action, inverse);
+  }
+  else if(GL_TRUE == compare(-epsilon, result)){
+    gl2psTraverseBspTree(tree->front, eye, epsilon, compare, action, inverse);
+    if(inverse){
+      gl2psListActionInverse(tree->primitives, action);
+    }
+    else{
+      gl2psListAction(tree->primitives, action);
+    }
+    gl2psTraverseBspTree(tree->back, eye, epsilon, compare, action, inverse);
+  }
+  else{
+    gl2psTraverseBspTree(tree->front, eye, epsilon, compare, action, inverse);
+    gl2psTraverseBspTree(tree->back, eye, epsilon, compare, action, inverse);
+  }
+}
+
+static void gl2psRescaleAndOffset(void)
+{
+  GL2PSprimitive *prim;
+  GLfloat minZ, maxZ, rangeZ, scaleZ;
+  GLfloat factor, units, area, dZ, dZdX, dZdY, maxdZ;
+  int i, j;
+
+  if(!gl2psListNbr(gl2ps->primitives))
+    return;
+
+  /* get z-buffer range */
+  prim = *(GL2PSprimitive**)gl2psListPointer(gl2ps->primitives, 0);
+  minZ = maxZ = prim->verts[0].xyz[2];
+  for(i = 1; i < prim->numverts; i++){
+    if(prim->verts[i].xyz[2] < minZ) minZ = prim->verts[i].xyz[2];
+    if(prim->verts[i].xyz[2] > maxZ) maxZ = prim->verts[i].xyz[2];
+  }
+  for(i = 1; i < gl2psListNbr(gl2ps->primitives); i++){
+    prim = *(GL2PSprimitive**)gl2psListPointer(gl2ps->primitives, i);
+    for(j = 0; j < prim->numverts; j++){
+      if(prim->verts[j].xyz[2] < minZ) minZ = prim->verts[j].xyz[2];
+      if(prim->verts[j].xyz[2] > maxZ) maxZ = prim->verts[j].xyz[2];
+    }
+  }
+  rangeZ = (maxZ - minZ);
+
+  /* rescale z-buffer coordinate in [0,GL2PS_ZSCALE], to make it of
+     the same order of magnitude as the x and y coordinates */
+  scaleZ = GL2PS_ZERO(rangeZ) ? GL2PS_ZSCALE : (GL2PS_ZSCALE / rangeZ);
+  /* avoid precision loss (we use floats!) */
+  if(scaleZ > 100000.F) scaleZ = 100000.F;
+
+  /* apply offsets */
+  for(i = 0; i < gl2psListNbr(gl2ps->primitives); i++){
+    prim = *(GL2PSprimitive**)gl2psListPointer(gl2ps->primitives, i);
+    for(j = 0; j < prim->numverts; j++){
+      prim->verts[j].xyz[2] = (prim->verts[j].xyz[2] - minZ) * scaleZ;
+    }
+    if((gl2ps->options & GL2PS_SIMPLE_LINE_OFFSET) &&
+       (prim->type == GL2PS_LINE)){
+      if(gl2ps->sort == GL2PS_SIMPLE_SORT){
+        prim->verts[0].xyz[2] -= GL2PS_ZOFFSET_LARGE;
+        prim->verts[1].xyz[2] -= GL2PS_ZOFFSET_LARGE;
+      }
+      else{
+        prim->verts[0].xyz[2] -= GL2PS_ZOFFSET;
+        prim->verts[1].xyz[2] -= GL2PS_ZOFFSET;
+      }
+    }
+    else if(prim->offset && (prim->type == GL2PS_TRIANGLE)){
+      factor = gl2ps->offset[0];
+      units = gl2ps->offset[1];
+      area =
+        (prim->verts[1].xyz[0] - prim->verts[0].xyz[0]) *
+        (prim->verts[2].xyz[1] - prim->verts[1].xyz[1]) -
+        (prim->verts[2].xyz[0] - prim->verts[1].xyz[0]) *
+        (prim->verts[1].xyz[1] - prim->verts[0].xyz[1]);
+      if(!GL2PS_ZERO(area)){
+        dZdX =
+          ((prim->verts[2].xyz[1] - prim->verts[1].xyz[1]) *
+           (prim->verts[1].xyz[2] - prim->verts[0].xyz[2]) -
+           (prim->verts[1].xyz[1] - prim->verts[0].xyz[1]) *
+           (prim->verts[2].xyz[2] - prim->verts[1].xyz[2])) / area;
+        dZdY =
+          ((prim->verts[1].xyz[0] - prim->verts[0].xyz[0]) *
+           (prim->verts[2].xyz[2] - prim->verts[1].xyz[2]) -
+           (prim->verts[2].xyz[0] - prim->verts[1].xyz[0]) *
+           (prim->verts[1].xyz[2] - prim->verts[0].xyz[2])) / area;
+        maxdZ = (GLfloat)sqrt(dZdX * dZdX + dZdY * dZdY);
+      }
+      else{
+        maxdZ = 0.0F;
+      }
+      dZ = factor * maxdZ + units;
+      prim->verts[0].xyz[2] += dZ;
+      prim->verts[1].xyz[2] += dZ;
+      prim->verts[2].xyz[2] += dZ;
+    }
+  }
+}
+
+/*********************************************************************
+ *
+ * 2D sorting routines (for occlusion culling)
+ *
+ *********************************************************************/
+
+static GLint gl2psGetPlaneFromPoints(GL2PSxyz a, GL2PSxyz b, GL2PSplane plane)
+{
+  GLfloat n;
+
+  plane[0] = b[1] - a[1];
+  plane[1] = a[0] - b[0];
+  n = (GLfloat)sqrt(plane[0]*plane[0] + plane[1]*plane[1]);
+  plane[2] = 0.0F;
+  if(!GL2PS_ZERO(n)){
+    plane[0] /= n;
+    plane[1] /= n;
+    plane[3] = -plane[0]*a[0]-plane[1]*a[1];
+    return 1;
+  }
+  else{
+    plane[0] = -1.0F;
+    plane[1] = 0.0F;
+    plane[3] = a[0];
+    return 0;
+  }
+}
+
+static void gl2psFreeBspImageTree(GL2PSbsptree2d **tree)
+{
+  if(*tree){
+    if((*tree)->back)  gl2psFreeBspImageTree(&(*tree)->back);
+    if((*tree)->front) gl2psFreeBspImageTree(&(*tree)->front);
+    gl2psFree(*tree);
+    *tree = NULL;
+  }
+}
+
+static GLint gl2psCheckPoint(GL2PSxyz point, GL2PSplane plane)
+{
+  GLfloat pt_dis;
+
+  pt_dis = gl2psComparePointPlane(point, plane);
+  if(pt_dis > GL2PS_EPSILON)        return GL2PS_POINT_INFRONT;
+  else if(pt_dis < -GL2PS_EPSILON)  return GL2PS_POINT_BACK;
+  else                              return GL2PS_POINT_COINCIDENT;
+}
+
+static void gl2psAddPlanesInBspTreeImage(GL2PSprimitive *prim,
+                                         GL2PSbsptree2d **tree)
+{
+  GLint ret = 0;
+  GLint i;
+  GLint offset = 0;
+  GL2PSbsptree2d *head = NULL, *cur = NULL;
+
+  if((*tree == NULL) && (prim->numverts > 2)){
+    /* don't cull if transparent
+    for(i = 0; i < prim->numverts - 1; i++)
+      if(prim->verts[i].rgba[3] < 1.0F) return;
+    */
+    head = (GL2PSbsptree2d*)gl2psMalloc(sizeof(GL2PSbsptree2d));
+    for(i = 0; i < prim->numverts-1; i++){
+      if(!gl2psGetPlaneFromPoints(prim->verts[i].xyz,
+                                  prim->verts[i+1].xyz,
+                                  head->plane)){
+        if(prim->numverts-i > 3){
+          offset++;
+        }
+        else{
+          gl2psFree(head);
+          return;
+        }
+      }
+      else{
+        break;
+      }
+    }
+    head->back = NULL;
+    head->front = NULL;
+    for(i = 2+offset; i < prim->numverts; i++){
+      ret = gl2psCheckPoint(prim->verts[i].xyz, head->plane);
+      if(ret != GL2PS_POINT_COINCIDENT) break;
+    }
+    switch(ret){
+    case GL2PS_POINT_INFRONT :
+      cur = head;
+      for(i = 1+offset; i < prim->numverts-1; i++){
+        if(cur->front == NULL){
+          cur->front = (GL2PSbsptree2d*)gl2psMalloc(sizeof(GL2PSbsptree2d));
+        }
+        if(gl2psGetPlaneFromPoints(prim->verts[i].xyz,
+                                   prim->verts[i+1].xyz,
+                                   cur->front->plane)){
+          cur = cur->front;
+          cur->front = NULL;
+          cur->back = NULL;
+        }
+      }
+      if(cur->front == NULL){
+        cur->front = (GL2PSbsptree2d*)gl2psMalloc(sizeof(GL2PSbsptree2d));
+      }
+      if(gl2psGetPlaneFromPoints(prim->verts[i].xyz,
+                                 prim->verts[offset].xyz,
+                                 cur->front->plane)){
+        cur->front->front = NULL;
+        cur->front->back = NULL;
+      }
+      else{
+        gl2psFree(cur->front);
+        cur->front = NULL;
+      }
+      break;
+    case GL2PS_POINT_BACK :
+      for(i = 0; i < 4; i++){
+        head->plane[i] = -head->plane[i];
+      }
+      cur = head;
+      for(i = 1+offset; i < prim->numverts-1; i++){
+        if(cur->front == NULL){
+          cur->front = (GL2PSbsptree2d*)gl2psMalloc(sizeof(GL2PSbsptree2d));
+        }
+        if(gl2psGetPlaneFromPoints(prim->verts[i+1].xyz,
+                                   prim->verts[i].xyz,
+                                   cur->front->plane)){
+          cur = cur->front;
+          cur->front = NULL;
+          cur->back = NULL;
+        }
+      }
+      if(cur->front == NULL){
+        cur->front = (GL2PSbsptree2d*)gl2psMalloc(sizeof(GL2PSbsptree2d));
+      }
+      if(gl2psGetPlaneFromPoints(prim->verts[offset].xyz,
+                                 prim->verts[i].xyz,
+                                 cur->front->plane)){
+        cur->front->front = NULL;
+        cur->front->back = NULL;
+      }
+      else{
+        gl2psFree(cur->front);
+        cur->front = NULL;
+      }
+      break;
+    default:
+      gl2psFree(head);
+      return;
+    }
+    (*tree) = head;
+  }
+}
+
+static GLint gl2psCheckPrimitive(GL2PSprimitive *prim, GL2PSplane plane)
+{
+  GLint i;
+  GLint pos;
+
+  pos = gl2psCheckPoint(prim->verts[0].xyz, plane);
+  for(i = 1; i < prim->numverts; i++){
+    pos |= gl2psCheckPoint(prim->verts[i].xyz, plane);
+    if(pos == (GL2PS_POINT_INFRONT | GL2PS_POINT_BACK)) return GL2PS_SPANNING;
+  }
+  if(pos & GL2PS_POINT_INFRONT)   return GL2PS_IN_FRONT_OF;
+  else if(pos & GL2PS_POINT_BACK) return GL2PS_IN_BACK_OF;
+  else                            return GL2PS_COINCIDENT;
+}
+
+static GL2PSprimitive *gl2psCreateSplitPrimitive2D(GL2PSprimitive *parent,
+                                                   GLshort numverts,
+                                                   GL2PSvertex *vertx)
+{
+  GLint i;
+  GL2PSprimitive *child = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
+
+  if(parent->type == GL2PS_IMAGEMAP){
+    child->type = GL2PS_IMAGEMAP;
+    child->data.image = parent->data.image;
+  }
+  else {
+    switch(numverts){
+    case 1 : child->type = GL2PS_POINT; break;
+    case 2 : child->type = GL2PS_LINE; break;
+    case 3 : child->type = GL2PS_TRIANGLE; break;
+    case 4 : child->type = GL2PS_QUADRANGLE; break;
+    default: child->type = GL2PS_NO_TYPE; break; /* FIXME */
+    }
+  }
+  child->boundary = 0; /* FIXME: not done! */
+  child->culled = parent->culled;
+  child->offset = parent->offset;
+  child->pattern = parent->pattern;
+  child->factor = parent->factor;
+  child->width = parent->width;
+  child->numverts = numverts;
+  child->verts = (GL2PSvertex*)gl2psMalloc(numverts * sizeof(GL2PSvertex));
+  for(i = 0; i < numverts; i++){
+    child->verts[i] = vertx[i];
+  }
+  return child;
+}
+
+static void gl2psSplitPrimitive2D(GL2PSprimitive *prim,
+                                  GL2PSplane plane,
+                                  GL2PSprimitive **front,
+                                  GL2PSprimitive **back)
+{
+  /* cur will hold the position of the current vertex
+     prev will hold the position of the previous vertex
+     prev0 will hold the position of the vertex number 0
+     v1 and v2 represent the current and previous vertices, respectively
+     flag is set if the current vertex should be checked against the plane */
+  GLint cur = -1, prev = -1, i, v1 = 0, v2 = 0, flag = 1, prev0 = -1;
+
+  /* list of vertices that will go in front and back primitive */
+  GL2PSvertex *front_list = NULL, *back_list = NULL;
+
+  /* number of vertices in front and back list */
+  GLshort front_count = 0, back_count = 0;
+
+  for(i = 0; i <= prim->numverts; i++){
+    v1 = i;
+    if(v1 == prim->numverts){
+      if(prim->numverts < 3) break;
+      v1 = 0;
+      v2 = prim->numverts - 1;
+      cur = prev0;
+    }
+    else if(flag){
+      cur = gl2psCheckPoint(prim->verts[v1].xyz, plane);
+      if(i == 0){
+        prev0 = cur;
+      }
+    }
+    if(((prev == -1) || (prev == cur) || (prev == 0) || (cur == 0)) &&
+       (i < prim->numverts)){
+      if(cur == GL2PS_POINT_INFRONT){
+        front_count++;
+        front_list = (GL2PSvertex*)gl2psRealloc(front_list,
+                                                sizeof(GL2PSvertex)*front_count);
+        front_list[front_count-1] = prim->verts[v1];
+      }
+      else if(cur == GL2PS_POINT_BACK){
+        back_count++;
+        back_list = (GL2PSvertex*)gl2psRealloc(back_list,
+                                               sizeof(GL2PSvertex)*back_count);
+        back_list[back_count-1] = prim->verts[v1];
+      }
+      else{
+        front_count++;
+        front_list = (GL2PSvertex*)gl2psRealloc(front_list,
+                                                sizeof(GL2PSvertex)*front_count);
+        front_list[front_count-1] = prim->verts[v1];
+        back_count++;
+        back_list = (GL2PSvertex*)gl2psRealloc(back_list,
+                                               sizeof(GL2PSvertex)*back_count);
+        back_list[back_count-1] = prim->verts[v1];
+      }
+      flag = 1;
+    }
+    else if((prev != cur) && (cur != 0) && (prev != 0)){
+      if(v1 != 0){
+        v2 = v1-1;
+        i--;
+      }
+      front_count++;
+      front_list = (GL2PSvertex*)gl2psRealloc(front_list,
+                                              sizeof(GL2PSvertex)*front_count);
+      gl2psCutEdge(&prim->verts[v2], &prim->verts[v1],
+                   plane, &front_list[front_count-1]);
+      back_count++;
+      back_list = (GL2PSvertex*)gl2psRealloc(back_list,
+                                             sizeof(GL2PSvertex)*back_count);
+      back_list[back_count-1] = front_list[front_count-1];
+      flag = 0;
+    }
+    prev = cur;
+  }
+  *front = gl2psCreateSplitPrimitive2D(prim, front_count, front_list);
+  *back = gl2psCreateSplitPrimitive2D(prim, back_count, back_list);
+  gl2psFree(front_list);
+  gl2psFree(back_list);
+}
+
+static GLint gl2psAddInBspImageTree(GL2PSprimitive *prim, GL2PSbsptree2d **tree)
+{
+  GLint ret = 0;
+  GL2PSprimitive *frontprim = NULL, *backprim = NULL;
+
+  /* FIXME: until we consider the actual extent of text strings and
+     pixmaps, never cull them. Otherwise the whole string/pixmap gets
+     culled as soon as the reference point is hidden */
+  if(prim->type == GL2PS_PIXMAP ||
+     prim->type == GL2PS_TEXT ||
+     prim->type == GL2PS_SPECIAL){
+    return 1;
+  }
+
+  if(*tree == NULL){
+    if((prim->type != GL2PS_IMAGEMAP) && (GL_FALSE == gl2ps->zerosurfacearea)){
+      gl2psAddPlanesInBspTreeImage(gl2ps->primitivetoadd, tree);
+    }
+    return 1;
+  }
+  else{
+    switch(gl2psCheckPrimitive(prim, (*tree)->plane)){
+    case GL2PS_IN_BACK_OF: return gl2psAddInBspImageTree(prim, &(*tree)->back);
+    case GL2PS_IN_FRONT_OF:
+      if((*tree)->front != NULL) return gl2psAddInBspImageTree(prim, &(*tree)->front);
+      else                       return 0;
+    case GL2PS_SPANNING:
+      gl2psSplitPrimitive2D(prim, (*tree)->plane, &frontprim, &backprim);
+      ret = gl2psAddInBspImageTree(backprim, &(*tree)->back);
+      if((*tree)->front != NULL){
+        if(gl2psAddInBspImageTree(frontprim, &(*tree)->front)){
+          ret = 1;
+        }
+      }
+      gl2psFree(frontprim->verts);
+      gl2psFree(frontprim);
+      gl2psFree(backprim->verts);
+      gl2psFree(backprim);
+      return ret;
+    case GL2PS_COINCIDENT:
+      if((*tree)->back != NULL){
+        gl2ps->zerosurfacearea = GL_TRUE;
+        ret = gl2psAddInBspImageTree(prim, &(*tree)->back);
+        gl2ps->zerosurfacearea = GL_FALSE;
+        if(ret) return ret;
+      }
+      if((*tree)->front != NULL){
+        gl2ps->zerosurfacearea = GL_TRUE;
+        ret = gl2psAddInBspImageTree(prim, &(*tree)->front);
+        gl2ps->zerosurfacearea = GL_FALSE;
+        if(ret) return ret;
+      }
+      if(prim->type == GL2PS_LINE) return 1;
+      else                         return 0;
+    }
+  }
+  return 0;
+}
+
+static void gl2psAddInImageTree(void *data)
+{
+  GL2PSprimitive *prim = *(GL2PSprimitive **)data;
+  gl2ps->primitivetoadd = prim;
+  if(prim->type == GL2PS_IMAGEMAP && prim->data.image->format == GL2PS_IMAGEMAP_VISIBLE){
+    prim->culled = 1;
+  }
+  else if(!gl2psAddInBspImageTree(prim, &gl2ps->imagetree)){
+    prim->culled = 1;
+  }
+  else if(prim->type == GL2PS_IMAGEMAP){
+    prim->data.image->format = GL2PS_IMAGEMAP_VISIBLE;
+  }
+}
+
+/* Boundary construction */
+
+static void gl2psAddBoundaryInList(GL2PSprimitive *prim, GL2PSlist *list)
+{
+  GL2PSprimitive *b;
+  GLshort i;
+  GL2PSxyz c;
+
+  c[0] = c[1] = c[2] = 0.0F;
+  for(i = 0; i < prim->numverts; i++){
+    c[0] += prim->verts[i].xyz[0];
+    c[1] += prim->verts[i].xyz[1];
+  }
+  c[0] /= prim->numverts;
+  c[1] /= prim->numverts;
+
+  for(i = 0; i < prim->numverts; i++){
+    if(prim->boundary & (GLint)pow(2., i)){
+      b = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
+      b->type = GL2PS_LINE;
+      b->offset = prim->offset;
+      b->pattern = prim->pattern;
+      b->factor = prim->factor;
+      b->culled = prim->culled;
+      b->width = prim->width;
+      b->boundary = 0;
+      b->numverts = 2;
+      b->verts = (GL2PSvertex*)gl2psMalloc(2 * sizeof(GL2PSvertex));
+
+#if 0 /* FIXME: need to work on boundary offset... */
+      v[0] = c[0] - prim->verts[i].xyz[0];
+      v[1] = c[1] - prim->verts[i].xyz[1];
+      v[2] = 0.0F;
+      norm = gl2psNorm(v);
+      v[0] /= norm;
+      v[1] /= norm;
+      b->verts[0].xyz[0] = prim->verts[i].xyz[0] +0.1*v[0];
+      b->verts[0].xyz[1] = prim->verts[i].xyz[1] +0.1*v[1];
+      b->verts[0].xyz[2] = prim->verts[i].xyz[2];
+      v[0] = c[0] - prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[0];
+      v[1] = c[1] - prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[1];
+      norm = gl2psNorm(v);
+      v[0] /= norm;
+      v[1] /= norm;
+      b->verts[1].xyz[0] = prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[0] +0.1*v[0];
+      b->verts[1].xyz[1] = prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[1] +0.1*v[1];
+      b->verts[1].xyz[2] = prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[2];
+#else
+      b->verts[0].xyz[0] = prim->verts[i].xyz[0];
+      b->verts[0].xyz[1] = prim->verts[i].xyz[1];
+      b->verts[0].xyz[2] = prim->verts[i].xyz[2];
+      b->verts[1].xyz[0] = prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[0];
+      b->verts[1].xyz[1] = prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[1];
+      b->verts[1].xyz[2] = prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[2];
+#endif
+
+      b->verts[0].rgba[0] = 0.0F;
+      b->verts[0].rgba[1] = 0.0F;
+      b->verts[0].rgba[2] = 0.0F;
+      b->verts[0].rgba[3] = 0.0F;
+      b->verts[1].rgba[0] = 0.0F;
+      b->verts[1].rgba[1] = 0.0F;
+      b->verts[1].rgba[2] = 0.0F;
+      b->verts[1].rgba[3] = 0.0F;
+      gl2psListAdd(list, &b);
+    }
+  }
+
+}
+
+static void gl2psBuildPolygonBoundary(GL2PSbsptree *tree)
+{
+  GLint i;
+  GL2PSprimitive *prim;
+
+  if(!tree) return;
+  gl2psBuildPolygonBoundary(tree->back);
+  for(i = 0; i < gl2psListNbr(tree->primitives); i++){
+    prim = *(GL2PSprimitive**)gl2psListPointer(tree->primitives, i);
+    if(prim->boundary) gl2psAddBoundaryInList(prim, tree->primitives);
+  }
+  gl2psBuildPolygonBoundary(tree->front);
+}
+
+/*********************************************************************
+ *
+ * Feedback buffer parser
+ *
+ *********************************************************************/
+
+static void gl2psAddPolyPrimitive(GLshort type, GLshort numverts,
+                                  GL2PSvertex *verts, GLint offset,
+                                  GLushort pattern, GLint factor,
+                                  GLfloat width, char boundary)
+{
+  GL2PSprimitive *prim;
+
+  prim = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
+  prim->type = type;
+  prim->numverts = numverts;
+  prim->verts = (GL2PSvertex*)gl2psMalloc(numverts * sizeof(GL2PSvertex));
+  memcpy(prim->verts, verts, numverts * sizeof(GL2PSvertex));
+  prim->boundary = boundary;
+  prim->offset = offset;
+  prim->pattern = pattern;
+  prim->factor = factor;
+  prim->width = width;
+  prim->culled = 0;
+
+  /* FIXME: here we should have an option to split stretched
+     tris/quads to enhance SIMPLE_SORT */
+
+  gl2psListAdd(gl2ps->primitives, &prim);
+}
+
+static GLint gl2psGetVertex(GL2PSvertex *v, GLfloat *p)
+{
+  GLint i;
+
+  v->xyz[0] = p[0];
+  v->xyz[1] = p[1];
+  v->xyz[2] = p[2];
+
+  if(gl2ps->colormode == GL_COLOR_INDEX && gl2ps->colorsize > 0){
+    i = (GLint)(p[3] + 0.5);
+    v->rgba[0] = gl2ps->colormap[i][0];
+    v->rgba[1] = gl2ps->colormap[i][1];
+    v->rgba[2] = gl2ps->colormap[i][2];
+    v->rgba[3] = gl2ps->colormap[i][3];
+    return 4;
+  }
+  else{
+    v->rgba[0] = p[3];
+    v->rgba[1] = p[4];
+    v->rgba[2] = p[5];
+    v->rgba[3] = p[6];
+    return 7;
+  }
+}
+
+static void gl2psParseFeedbackBuffer(GLint used)
+{
+  char flag;
+  GLushort pattern = 0;
+  GLboolean boundary;
+  GLint i, sizeoffloat, count, v, vtot, offset = 0, factor = 0, auxindex = 0;
+  GLfloat lwidth = 1.0F, psize = 1.0F;
+  GLfloat *current;
+  GL2PSvertex vertices[3];
+  GL2PSprimitive *prim;
+  GL2PSimagemap *node;
+
+  current = gl2ps->feedback;
+  boundary = gl2ps->boundary = GL_FALSE;
+
+  while(used > 0){
+
+    if(GL_TRUE == boundary) gl2ps->boundary = GL_TRUE;
+
+    switch((GLint)*current){
+    case GL_POINT_TOKEN :
+      current ++;
+      used --;
+      i = gl2psGetVertex(&vertices[0], current);
+      current += i;
+      used    -= i;
+      gl2psAddPolyPrimitive(GL2PS_POINT, 1, vertices, 0,
+                            pattern, factor, psize, 0);
+      break;
+    case GL_LINE_TOKEN :
+    case GL_LINE_RESET_TOKEN :
+      current ++;
+      used --;
+      i = gl2psGetVertex(&vertices[0], current);
+      current += i;
+      used    -= i;
+      i = gl2psGetVertex(&vertices[1], current);
+      current += i;
+      used    -= i;
+      gl2psAddPolyPrimitive(GL2PS_LINE, 2, vertices, 0,
+                            pattern, factor, lwidth, 0);
+      break;
+    case GL_POLYGON_TOKEN :
+      count = (GLint)current[1];
+      current += 2;
+      used -= 2;
+      v = vtot = 0;
+      while(count > 0 && used > 0){
+        i = gl2psGetVertex(&vertices[v], current);
+        gl2psAdaptVertexForBlending(&vertices[v]);
+        current += i;
+        used    -= i;
+        count --;
+        vtot++;
+        if(v == 2){
+          if(GL_TRUE == boundary){
+            if(!count && vtot == 2) flag = 1|2|4;
+            else if(!count) flag = 2|4;
+            else if(vtot == 2) flag = 1|2;
+            else flag = 2;
+          }
+          else
+            flag = 0;
+          gl2psAddPolyPrimitive(GL2PS_TRIANGLE, 3, vertices, offset,
+                                pattern, factor, 1, flag);
+          vertices[1] = vertices[2];
+        }
+        else
+          v ++;
+      }
+      break;
+    case GL_BITMAP_TOKEN :
+    case GL_DRAW_PIXEL_TOKEN :
+    case GL_COPY_PIXEL_TOKEN :
+      current ++;
+      used --;
+      i = gl2psGetVertex(&vertices[0], current);
+      current += i;
+      used    -= i;
+      break;
+    case GL_PASS_THROUGH_TOKEN :
+      switch((GLint)current[1]){
+      case GL2PS_BEGIN_OFFSET_TOKEN : offset = 1; break;
+      case GL2PS_END_OFFSET_TOKEN : offset = 0; break;
+      case GL2PS_BEGIN_BOUNDARY_TOKEN : boundary = GL_TRUE; break;
+      case GL2PS_END_BOUNDARY_TOKEN : boundary = GL_FALSE; break;
+      case GL2PS_END_STIPPLE_TOKEN : pattern = factor = 0; break;
+      case GL2PS_BEGIN_BLEND_TOKEN : gl2ps->blending = GL_TRUE; break;
+      case GL2PS_END_BLEND_TOKEN : gl2ps->blending = GL_FALSE; break;
+      case GL2PS_BEGIN_STIPPLE_TOKEN :
+        current += 2;
+        used -= 2;
+        pattern = (GLushort)current[1];
+        current += 2;
+        used -= 2;
+        factor = (GLint)current[1];
+        break;
+      case GL2PS_SRC_BLEND_TOKEN :
+        current += 2;
+        used -= 2;
+        gl2ps->blendfunc[0] = (GLint)current[1];
+        break;
+      case GL2PS_DST_BLEND_TOKEN :
+        current += 2;
+        used -= 2;
+        gl2ps->blendfunc[1] = (GLint)current[1];
+        break;
+      case GL2PS_POINT_SIZE_TOKEN :
+        current += 2;
+        used -= 2;
+        psize = current[1];
+        break;
+      case GL2PS_LINE_WIDTH_TOKEN :
+        current += 2;
+        used -= 2;
+        lwidth = current[1];
+        break;
+      case GL2PS_IMAGEMAP_TOKEN :
+        prim = (GL2PSprimitive *)gl2psMalloc(sizeof(GL2PSprimitive));
+        prim->type = GL2PS_IMAGEMAP;
+        prim->boundary = 0;
+        prim->numverts = 4;
+        prim->verts = (GL2PSvertex *)gl2psMalloc(4 * sizeof(GL2PSvertex));
+        prim->culled = 0;
+        prim->offset = 0;
+        prim->pattern = 0;
+        prim->factor = 0;
+        prim->width = 1;
+
+        node = (GL2PSimagemap*)gl2psMalloc(sizeof(GL2PSimagemap));
+        node->image = (GL2PSimage*)gl2psMalloc(sizeof(GL2PSimage));
+        node->image->type = 0;
+        node->image->format = 0;
+        node->image->zoom_x = 1.0F;
+        node->image->zoom_y = 1.0F;
+        node->next = NULL;
+
+        if(gl2ps->imagemap_head == NULL)
+          gl2ps->imagemap_head = node;
+        else
+          gl2ps->imagemap_tail->next = node;
+        gl2ps->imagemap_tail = node;
+        prim->data.image = node->image;
+
+        current += 2; used -= 2;
+        i = gl2psGetVertex(&prim->verts[0], &current[1]);
+        current += i; used -= i;
+
+        node->image->width = (GLint)current[2];
+        current += 2; used -= 2;
+        node->image->height = (GLint)current[2];
+        prim->verts[0].xyz[0] = prim->verts[0].xyz[0] - (int)(node->image->width / 2) + 0.5F;
+        prim->verts[0].xyz[1] = prim->verts[0].xyz[1] - (int)(node->image->height / 2) + 0.5F;
+        for(i = 1; i < 4; i++){
+          for(v = 0; v < 3; v++){
+            prim->verts[i].xyz[v] = prim->verts[0].xyz[v];
+            prim->verts[i].rgba[v] = prim->verts[0].rgba[v];
+          }
+          prim->verts[i].rgba[v] = prim->verts[0].rgba[v];
+        }
+        prim->verts[1].xyz[0] = prim->verts[1].xyz[0] + node->image->width;
+        prim->verts[2].xyz[0] = prim->verts[1].xyz[0];
+        prim->verts[2].xyz[1] = prim->verts[2].xyz[1] + node->image->height;
+        prim->verts[3].xyz[1] = prim->verts[2].xyz[1];
+
+        sizeoffloat = sizeof(GLfloat);
+        v = 2 * sizeoffloat;
+        vtot = node->image->height + node->image->height *
+          ((node->image->width - 1) / 8);
+        node->image->pixels = (GLfloat*)gl2psMalloc(v + vtot);
+        node->image->pixels[0] = prim->verts[0].xyz[0];
+        node->image->pixels[1] = prim->verts[0].xyz[1];
+
+        for(i = 0; i < vtot; i += sizeoffloat){
+          current += 2; used -= 2;
+          if((vtot - i) >= 4)
+            memcpy(&(((char*)(node->image->pixels))[i + v]), &(current[2]), sizeoffloat);
+          else
+            memcpy(&(((char*)(node->image->pixels))[i + v]), &(current[2]), vtot - i);
+        }
+        current++; used--;
+        gl2psListAdd(gl2ps->primitives, &prim);
+        break;
+      case GL2PS_DRAW_PIXELS_TOKEN :
+      case GL2PS_TEXT_TOKEN :
+        if(auxindex < gl2psListNbr(gl2ps->auxprimitives))
+          gl2psListAdd(gl2ps->primitives,
+                       gl2psListPointer(gl2ps->auxprimitives, auxindex++));
+        else
+          gl2psMsg(GL2PS_ERROR, "Wrong number of auxiliary tokens in buffer");
+        break;
+      }
+      current += 2;
+      used -= 2;
+      break;
+    default :
+      gl2psMsg(GL2PS_WARNING, "Unknown token in buffer");
+      current ++;
+      used --;
+      break;
+    }
+  }
+
+  gl2psListReset(gl2ps->auxprimitives);
+}
+
+/*********************************************************************
+ *
+ * PostScript routines
+ *
+ *********************************************************************/
+
+static void gl2psWriteByte(unsigned char byte)
+{
+  unsigned char h = byte / 16;
+  unsigned char l = byte % 16;
+  gl2psPrintf("%x%x", h, l);
+}
+
+static void gl2psPrintPostScriptPixmap(GLfloat x, GLfloat y, GL2PSimage *im)
+{
+  GLuint nbhex, nbyte, nrgb, nbits;
+  GLuint row, col, ibyte, icase;
+  GLfloat dr, dg, db, fgrey;
+  unsigned char red = 0, green = 0, blue = 0, b, grey;
+  GLuint width = (GLuint)im->width;
+  GLuint height = (GLuint)im->height;
+
+  /* FIXME: should we define an option for these? Or just keep the
+     8-bit per component case? */
+  int greyscale = 0; /* set to 1 to output greyscale image */
+  int nbit = 8; /* number of bits per color compoment (2, 4 or 8) */
+
+  if((width <= 0) || (height <= 0)) return;
+
+  gl2psPrintf("gsave\n");
+  gl2psPrintf("%.2f %.2f translate\n", x, y);
+  gl2psPrintf("%.2f %.2f scale\n", width * im->zoom_x, height * im->zoom_y);
+
+  if(greyscale){ /* greyscale */
+    gl2psPrintf("/picstr %d string def\n", width);
+    gl2psPrintf("%d %d %d\n", width, height, 8);
+    gl2psPrintf("[ %d 0 0 -%d 0 %d ]\n", width, height, height);
+    gl2psPrintf("{ currentfile picstr readhexstring pop }\n");
+    gl2psPrintf("image\n");
+    for(row = 0; row < height; row++){
+      for(col = 0; col < width; col++){
+        gl2psGetRGB(im, col, row, &dr, &dg, &db);
+        fgrey = (0.30F * dr + 0.59F * dg + 0.11F * db);
+        grey = (unsigned char)(255. * fgrey);
+        gl2psWriteByte(grey);
+      }
+      gl2psPrintf("\n");
+    }
+    nbhex = width * height * 2;
+    gl2psPrintf("%%%% nbhex digit          :%d\n", nbhex);
+  }
+  else if(nbit == 2){ /* color, 2 bits for r and g and b; rgbs following each other */
+    nrgb = width  * 3;
+    nbits = nrgb * nbit;
+    nbyte = nbits / 8;
+    if((nbyte * 8) != nbits) nbyte++;
+    gl2psPrintf("/rgbstr %d string def\n", nbyte);
+    gl2psPrintf("%d %d %d\n", width, height, nbit);
+    gl2psPrintf("[ %d 0 0 -%d 0 %d ]\n", width, height, height);
+    gl2psPrintf("{ currentfile rgbstr readhexstring pop }\n");
+    gl2psPrintf("false 3\n");
+    gl2psPrintf("colorimage\n");
+    for(row = 0; row < height; row++){
+      icase = 1;
+      col = 0;
+      b = 0;
+      for(ibyte = 0; ibyte < nbyte; ibyte++){
+        if(icase == 1) {
+          if(col < width) {
+            gl2psGetRGB(im, col, row, &dr, &dg, &db);
+          }
+          else {
+            dr = dg = db = 0;
+          }
+          col++;
+          red = (unsigned char)(3. * dr);
+          green = (unsigned char)(3. * dg);
+          blue = (unsigned char)(3. * db);
+          b = red;
+          b = (b<<2) + green;
+          b = (b<<2) + blue;
+          if(col < width) {
+            gl2psGetRGB(im, col, row, &dr, &dg, &db);
+          }
+          else {
+            dr = dg = db = 0;
+          }
+          col++;
+          red = (unsigned char)(3. * dr);
+          green = (unsigned char)(3. * dg);
+          blue = (unsigned char)(3. * db);
+          b = (b<<2) + red;
+          gl2psWriteByte(b);
+          b = 0;
+          icase++;
+        }
+        else if(icase == 2) {
+          b = green;
+          b = (b<<2) + blue;
+          if(col < width) {
+            gl2psGetRGB(im, col, row, &dr, &dg, &db);
+          }
+          else {
+            dr = dg = db = 0;
+          }
+          col++;
+          red = (unsigned char)(3. * dr);
+          green = (unsigned char)(3. * dg);
+          blue = (unsigned char)(3. * db);
+          b = (b<<2) + red;
+          b = (b<<2) + green;
+          gl2psWriteByte(b);
+          b = 0;
+          icase++;
+        }
+        else if(icase == 3) {
+          b = blue;
+          if(col < width) {
+            gl2psGetRGB(im, col, row, &dr, &dg, &db);
+          }
+          else {
+            dr = dg = db = 0;
+          }
+          col++;
+          red = (unsigned char)(3. * dr);
+          green = (unsigned char)(3. * dg);
+          blue = (unsigned char)(3. * db);
+          b = (b<<2) + red;
+          b = (b<<2) + green;
+          b = (b<<2) + blue;
+          gl2psWriteByte(b);
+          b = 0;
+          icase = 1;
+        }
+      }
+      gl2psPrintf("\n");
+    }
+  }
+  else if(nbit == 4){ /* color, 4 bits for r and g and b; rgbs following each other */
+    nrgb = width  * 3;
+    nbits = nrgb * nbit;
+    nbyte = nbits / 8;
+    if((nbyte * 8) != nbits) nbyte++;
+    gl2psPrintf("/rgbstr %d string def\n", nbyte);
+    gl2psPrintf("%d %d %d\n", width, height, nbit);
+    gl2psPrintf("[ %d 0 0 -%d 0 %d ]\n", width, height, height);
+    gl2psPrintf("{ currentfile rgbstr readhexstring pop }\n");
+    gl2psPrintf("false 3\n");
+    gl2psPrintf("colorimage\n");
+    for(row = 0; row < height; row++){
+      col = 0;
+      icase = 1;
+      for(ibyte = 0; ibyte < nbyte; ibyte++){
+        if(icase == 1) {
+          if(col < width) {
+            gl2psGetRGB(im, col, row, &dr, &dg, &db);
+          }
+          else {
+            dr = dg = db = 0;
+          }
+          col++;
+          red = (unsigned char)(15. * dr);
+          green = (unsigned char)(15. * dg);
+          gl2psPrintf("%x%x", red, green);
+          icase++;
+        }
+        else if(icase == 2) {
+          blue = (unsigned char)(15. * db);
+          if(col < width) {
+            gl2psGetRGB(im, col, row, &dr, &dg, &db);
+          }
+          else {
+            dr = dg = db = 0;
+          }
+          col++;
+          red = (unsigned char)(15. * dr);
+          gl2psPrintf("%x%x", blue, red);
+          icase++;
+        }
+        else if(icase == 3) {
+          green = (unsigned char)(15. * dg);
+          blue = (unsigned char)(15. * db);
+          gl2psPrintf("%x%x", green, blue);
+          icase = 1;
+        }
+      }
+      gl2psPrintf("\n");
+    }
+  }
+  else{ /* 8 bit for r and g and b */
+    nbyte = width * 3;
+    gl2psPrintf("/rgbstr %d string def\n", nbyte);
+    gl2psPrintf("%d %d %d\n", width, height, 8);
+    gl2psPrintf("[ %d 0 0 -%d 0 %d ]\n", width, height, height);
+    gl2psPrintf("{ currentfile rgbstr readhexstring pop }\n");
+    gl2psPrintf("false 3\n");
+    gl2psPrintf("colorimage\n");
+    for(row = 0; row < height; row++){
+      for(col = 0; col < width; col++){
+        gl2psGetRGB(im, col, row, &dr, &dg, &db);
+        red = (unsigned char)(255. * dr);
+        gl2psWriteByte(red);
+        green = (unsigned char)(255. * dg);
+        gl2psWriteByte(green);
+        blue = (unsigned char)(255. * db);
+        gl2psWriteByte(blue);
+      }
+      gl2psPrintf("\n");
+    }
+  }
+
+  gl2psPrintf("grestore\n");
+}
+
+static void gl2psPrintPostScriptImagemap(GLfloat x, GLfloat y,
+                                         GLsizei width, GLsizei height,
+                                         const unsigned char *imagemap){
+  int i, size;
+
+  if((width <= 0) || (height <= 0)) return;
+
+  size = height + height * (width - 1) / 8;
+
+  gl2psPrintf("gsave\n");
+  gl2psPrintf("%.2f %.2f translate\n", x, y);
+  gl2psPrintf("%d %d scale\n%d %d\ntrue\n", width, height,width, height);
+  gl2psPrintf("[ %d 0 0 -%d 0 %d ] {<", width, height);
+  for(i = 0; i < size; i++){
+    gl2psWriteByte(*imagemap);
+    imagemap++;
+  }
+  gl2psPrintf(">} imagemask\ngrestore\n");
+}
+
+static void gl2psPrintPostScriptHeader(void)
+{
+  time_t now;
+
+  /* Since compression is not part of the PostScript standard,
+     compressed PostScript files are just gzipped PostScript files
+     ("ps.gz" or "eps.gz") */
+  gl2psPrintGzipHeader();
+
+  time(&now);
+
+  if(gl2ps->format == GL2PS_PS){
+    gl2psPrintf("%%!PS-Adobe-3.0\n");
+  }
+  else{
+    gl2psPrintf("%%!PS-Adobe-3.0 EPSF-3.0\n");
+  }
+
+  gl2psPrintf("%%%%Title: %s\n"
+              "%%%%Creator: GL2PS %d.%d.%d%s, %s\n"
+              "%%%%For: %s\n"
+              "%%%%CreationDate: %s"
+              "%%%%LanguageLevel: 3\n"
+              "%%%%DocumentData: Clean7Bit\n"
+              "%%%%Pages: 1\n",
+              gl2ps->title, GL2PS_MAJOR_VERSION, GL2PS_MINOR_VERSION,
+              GL2PS_PATCH_VERSION, GL2PS_EXTRA_VERSION, GL2PS_COPYRIGHT,
+              gl2ps->producer, ctime(&now));
+
+  if(gl2ps->format == GL2PS_PS){
+    gl2psPrintf("%%%%Orientation: %s\n"
+                "%%%%DocumentMedia: Default %d %d 0 () ()\n",
+                (gl2ps->options & GL2PS_LANDSCAPE) ? "Landscape" : "Portrait",
+                (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[3] :
+                (int)gl2ps->viewport[2],
+                (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[2] :
+                (int)gl2ps->viewport[3]);
+  }
+
+  gl2psPrintf("%%%%BoundingBox: %d %d %d %d\n"
+              "%%%%EndComments\n",
+              (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[1] :
+              (int)gl2ps->viewport[0],
+              (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[0] :
+              (int)gl2ps->viewport[1],
+              (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[3] :
+              (int)gl2ps->viewport[2],
+              (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[2] :
+              (int)gl2ps->viewport[3]);
+
+  /* RGB color: r g b C (replace C by G in output to change from rgb to gray)
+     Grayscale: r g b G
+     Font choose: size fontname FC
+     Text string: (string) x y size fontname S??
+     Rotated text string: (string) angle x y size fontname S??R
+     Point primitive: x y size P
+     Line width: width W
+     Line start: x y LS
+     Line joining last point: x y L
+     Line end: x y LE
+     Flat-shaded triangle: x3 y3 x2 y2 x1 y1 T
+     Smooth-shaded triangle: x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 ST */
+
+  gl2psPrintf("%%%%BeginProlog\n"
+              "/gl2psdict 64 dict def gl2psdict begin\n"
+              "0 setlinecap 0 setlinejoin\n"
+              "/tryPS3shading %s def %% set to false to force subdivision\n"
+              "/rThreshold %g def %% red component subdivision threshold\n"
+              "/gThreshold %g def %% green component subdivision threshold\n"
+              "/bThreshold %g def %% blue component subdivision threshold\n",
+              (gl2ps->options & GL2PS_NO_PS3_SHADING) ? "false" : "true",
+              gl2ps->threshold[0], gl2ps->threshold[1], gl2ps->threshold[2]);
+
+  gl2psPrintf("/BD { bind def } bind def\n"
+              "/C  { setrgbcolor } BD\n"
+              "/G  { 0.082 mul exch 0.6094 mul add exch 0.3086 mul add neg 1.0 add setgray } BD\n"
+              "/W  { setlinewidth } BD\n");
+
+  gl2psPrintf("/FC { findfont exch /SH exch def SH scalefont setfont } BD\n"
+              "/SW { dup stringwidth pop } BD\n"
+              "/S  { FC moveto show } BD\n"
+              "/SBC{ FC moveto SW -2 div 0 rmoveto show } BD\n"
+              "/SBR{ FC moveto SW neg 0 rmoveto show } BD\n"
+              "/SCL{ FC moveto 0 SH -2 div rmoveto show } BD\n"
+              "/SCC{ FC moveto SW -2 div SH -2 div rmoveto show } BD\n"
+              "/SCR{ FC moveto SW neg SH -2 div rmoveto show } BD\n"
+              "/STL{ FC moveto 0 SH neg rmoveto show } BD\n"
+              "/STC{ FC moveto SW -2 div SH neg rmoveto show } BD\n"
+              "/STR{ FC moveto SW neg SH neg rmoveto show } BD\n");
+
+  /* rotated text routines: same nameanem with R appended */
+
+  gl2psPrintf("/FCT { FC translate 0 0 } BD\n"
+              "/SR  { gsave FCT moveto rotate show grestore } BD\n"
+              "/SBCR{ gsave FCT moveto rotate SW -2 div 0 rmoveto show grestore } BD\n"
+              "/SBRR{ gsave FCT moveto rotate SW neg 0 rmoveto show grestore } BD\n"
+              "/SCLR{ gsave FCT moveto rotate 0 SH -2 div rmoveto show grestore} BD\n");
+  gl2psPrintf("/SCCR{ gsave FCT moveto rotate SW -2 div SH -2 div rmoveto show grestore} BD\n"
+              "/SCRR{ gsave FCT moveto rotate SW neg SH -2 div rmoveto show grestore} BD\n"
+              "/STLR{ gsave FCT moveto rotate 0 SH neg rmoveto show grestore } BD\n"
+              "/STCR{ gsave FCT moveto rotate SW -2 div SH neg rmoveto show grestore } BD\n"
+              "/STRR{ gsave FCT moveto rotate SW neg SH neg rmoveto show grestore } BD\n");
+
+  gl2psPrintf("/P  { newpath 0.0 360.0 arc closepath fill } BD\n"
+              "/LS { newpath moveto } BD\n"
+              "/L  { lineto } BD\n"
+              "/LE { lineto stroke } BD\n"
+              "/T  { newpath moveto lineto lineto closepath fill } BD\n");
+
+  /* Smooth-shaded triangle with PostScript level 3 shfill operator:
+        x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 STshfill */
+
+  gl2psPrintf("/STshfill {\n"
+              "      /b1 exch def /g1 exch def /r1 exch def /y1 exch def /x1 exch def\n"
+              "      /b2 exch def /g2 exch def /r2 exch def /y2 exch def /x2 exch def\n"
+              "      /b3 exch def /g3 exch def /r3 exch def /y3 exch def /x3 exch def\n"
+              "      gsave << /ShadingType 4 /ColorSpace [/DeviceRGB]\n"
+              "      /DataSource [ 0 x1 y1 r1 g1 b1 0 x2 y2 r2 g2 b2 0 x3 y3 r3 g3 b3 ] >>\n"
+              "      shfill grestore } BD\n");
+
+  /* Flat-shaded triangle with middle color:
+        x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 Tm */
+
+  gl2psPrintf(/* stack : x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 */
+              "/Tm { 3 -1 roll 8 -1 roll 13 -1 roll add add 3 div\n" /* r = (r1+r2+r3)/3 */
+              /* stack : x3 y3 g3 b3 x2 y2 g2 b2 x1 y1 g1 b1 r */
+              "      3 -1 roll 7 -1 roll 11 -1 roll add add 3 div\n" /* g = (g1+g2+g3)/3 */
+              /* stack : x3 y3 b3 x2 y2 b2 x1 y1 b1 r g b */
+              "      3 -1 roll 6 -1 roll 9 -1 roll add add 3 div" /* b = (b1+b2+b3)/3 */
+              /* stack : x3 y3 x2 y2 x1 y1 r g b */
+              " C T } BD\n");
+
+  /* Split triangle in four sub-triangles (at sides middle points) and call the
+     STnoshfill procedure on each, interpolating the colors in RGB space:
+        x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 STsplit
+     (in procedure comments key: (Vi) = xi yi ri gi bi) */
+
+  gl2psPrintf("/STsplit {\n"
+              "      4 index 15 index add 0.5 mul\n" /* x13 = (x1+x3)/2 */
+              "      4 index 15 index add 0.5 mul\n" /* y13 = (y1+y3)/2 */
+              "      4 index 15 index add 0.5 mul\n" /* r13 = (r1+r3)/2 */
+              "      4 index 15 index add 0.5 mul\n" /* g13 = (g1+g3)/2 */
+              "      4 index 15 index add 0.5 mul\n" /* b13 = (b1+b3)/2 */
+              "      5 copy 5 copy 25 15 roll\n");
+
+  /* at his point, stack = (V3) (V13) (V13) (V13) (V2) (V1) */
+
+  gl2psPrintf("      9 index 30 index add 0.5 mul\n" /* x23 = (x2+x3)/2 */
+              "      9 index 30 index add 0.5 mul\n" /* y23 = (y2+y3)/2 */
+              "      9 index 30 index add 0.5 mul\n" /* r23 = (r2+r3)/2 */
+              "      9 index 30 index add 0.5 mul\n" /* g23 = (g2+g3)/2 */
+              "      9 index 30 index add 0.5 mul\n" /* b23 = (b2+b3)/2 */
+              "      5 copy 5 copy 35 5 roll 25 5 roll 15 5 roll\n");
+
+  /* stack = (V3) (V13) (V23) (V13) (V23) (V13) (V23) (V2) (V1) */
+
+  gl2psPrintf("      4 index 10 index add 0.5 mul\n" /* x12 = (x1+x2)/2 */
+              "      4 index 10 index add 0.5 mul\n" /* y12 = (y1+y2)/2 */
+              "      4 index 10 index add 0.5 mul\n" /* r12 = (r1+r2)/2 */
+              "      4 index 10 index add 0.5 mul\n" /* g12 = (g1+g2)/2 */
+              "      4 index 10 index add 0.5 mul\n" /* b12 = (b1+b2)/2 */
+              "      5 copy 5 copy 40 5 roll 25 5 roll 15 5 roll 25 5 roll\n");
+
+  /* stack = (V3) (V13) (V23) (V13) (V12) (V23) (V13) (V1) (V12) (V23) (V12) (V2) */
+
+  gl2psPrintf("      STnoshfill STnoshfill STnoshfill STnoshfill } BD\n");
+
+  /* Gouraud shaded triangle using recursive subdivision until the difference
+     between corner colors does not exceed the thresholds:
+        x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 STnoshfill  */
+
+  gl2psPrintf("/STnoshfill {\n"
+              "      2 index 8 index sub abs rThreshold gt\n" /* |r1-r2|>rth */
+              "      { STsplit }\n"
+              "      { 1 index 7 index sub abs gThreshold gt\n" /* |g1-g2|>gth */
+              "        { STsplit }\n"
+              "        { dup 6 index sub abs bThreshold gt\n" /* |b1-b2|>bth */
+              "          { STsplit }\n"
+              "          { 2 index 13 index sub abs rThreshold gt\n" /* |r1-r3|>rht */
+              "            { STsplit }\n"
+              "            { 1 index 12 index sub abs gThreshold gt\n" /* |g1-g3|>gth */
+              "              { STsplit }\n"
+              "              { dup 11 index sub abs bThreshold gt\n" /* |b1-b3|>bth */
+              "                { STsplit }\n"
+              "                { 7 index 13 index sub abs rThreshold gt\n"); /* |r2-r3|>rht */
+  gl2psPrintf("                  { STsplit }\n"
+              "                  { 6 index 12 index sub abs gThreshold gt\n" /* |g2-g3|>gth */
+              "                    { STsplit }\n"
+              "                    { 5 index 11 index sub abs bThreshold gt\n" /* |b2-b3|>bth */
+              "                      { STsplit }\n"
+              "                      { Tm }\n" /* all colors sufficiently similar */
+              "                      ifelse }\n"
+              "                    ifelse }\n"
+              "                  ifelse }\n"
+              "                ifelse }\n"
+              "              ifelse }\n"
+              "            ifelse }\n"
+              "          ifelse }\n"
+              "        ifelse }\n"
+              "      ifelse } BD\n");
+
+  gl2psPrintf("tryPS3shading\n"
+              "{ /shfill where\n"
+              "  { /ST { STshfill } BD }\n"
+              "  { /ST { STnoshfill } BD }\n"
+              "  ifelse }\n"
+              "{ /ST { STnoshfill } BD }\n"
+              "ifelse\n");
+
+  gl2psPrintf("end\n"
+              "%%%%EndProlog\n"
+              "%%%%BeginSetup\n"
+              "/DeviceRGB setcolorspace\n"
+              "gl2psdict begin\n"
+              "%%%%EndSetup\n"
+              "%%%%Page: 1 1\n"
+              "%%%%BeginPageSetup\n");
+
+  if(gl2ps->options & GL2PS_LANDSCAPE){
+    gl2psPrintf("%d 0 translate 90 rotate\n",
+                (int)gl2ps->viewport[3]);
+  }
+
+  gl2psPrintf("%%%%EndPageSetup\n"
+              "mark\n"
+              "gsave\n"
+              "1.0 1.0 scale\n");
+
+  if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
+    gl2psPrintf("%g %g %g C\n"
+                "newpath %d %d moveto %d %d lineto %d %d lineto %d %d lineto\n"
+                "closepath fill\n",
+                gl2ps->bgcolor[0], gl2ps->bgcolor[1], gl2ps->bgcolor[2],
+                (int)gl2ps->viewport[0], (int)gl2ps->viewport[1], (int)gl2ps->viewport[2],
+                (int)gl2ps->viewport[1], (int)gl2ps->viewport[2], (int)gl2ps->viewport[3],
+                (int)gl2ps->viewport[0], (int)gl2ps->viewport[3]);
+  }
+}
+
+static void gl2psPrintPostScriptColor(GL2PSrgba rgba)
+{
+  if(!gl2psSameColor(gl2ps->lastrgba, rgba)){
+    gl2psSetLastColor(rgba);
+    gl2psPrintf("%g %g %g C\n", rgba[0], rgba[1], rgba[2]);
+  }
+}
+
+static void gl2psResetPostScriptColor(void)
+{
+  gl2ps->lastrgba[0] = gl2ps->lastrgba[1] = gl2ps->lastrgba[2] = -1.;
+}
+
+static void gl2psEndPostScriptLine(void)
+{
+  int i;
+  if(gl2ps->lastvertex.rgba[0] >= 0.){
+    gl2psPrintf("%g %g LE\n", gl2ps->lastvertex.xyz[0], gl2ps->lastvertex.xyz[1]);
+    for(i = 0; i < 3; i++)
+      gl2ps->lastvertex.xyz[i] = -1.;
+    for(i = 0; i < 4; i++)
+      gl2ps->lastvertex.rgba[i] = -1.;
+  }
+}
+
+static void gl2psParseStipplePattern(GLushort pattern, GLint factor,
+                                     int *nb, int array[10])
+{
+  int i, n;
+  int on[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+  int off[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+  char tmp[16];
+
+  /* extract the 16 bits from the OpenGL stipple pattern */
+  for(n = 15; n >= 0; n--){
+    tmp[n] = (char)(pattern & 0x01);
+    pattern >>= 1;
+  }
+  /* compute the on/off pixel sequence */
+  n = 0;
+  for(i = 0; i < 8; i++){
+    while(n < 16 && !tmp[n]){ off[i]++; n++; }
+    while(n < 16 && tmp[n]){ on[i]++; n++; }
+    if(n >= 15){ i++; break; }
+  }
+
+  /* store the on/off array from right to left, starting with off
+     pixels. The PostScript specification allows for at most 11
+     elements in the on/off array, so we limit ourselves to 5 on/off
+     couples (our longest possible array is thus [on4 off4 on3 off3
+     on2 off2 on1 off1 on0 off0]) */
+  *nb = 0;
+  for(n = i - 1; n >= 0; n--){
+    array[(*nb)++] = factor * on[n];
+    array[(*nb)++] = factor * off[n];
+    if(*nb == 10) break;
+  }
+}
+
+static int gl2psPrintPostScriptDash(GLushort pattern, GLint factor, const char *str)
+{
+  int len = 0, i, n, array[10];
+
+  if(pattern == gl2ps->lastpattern && factor == gl2ps->lastfactor)
+    return 0;
+
+  gl2ps->lastpattern = pattern;
+  gl2ps->lastfactor = factor;
+
+  if(!pattern || !factor){
+    /* solid line */
+    len += gl2psPrintf("[] 0 %s\n", str);
+  }
+  else{
+    gl2psParseStipplePattern(pattern, factor, &n, array);
+    len += gl2psPrintf("[");
+    for(i = 0; i < n; i++){
+      if(i) len += gl2psPrintf(" ");
+      len += gl2psPrintf("%d", array[i]);
+    }
+    len += gl2psPrintf("] 0 %s\n", str);
+  }
+
+  return len;
+}
+
+static void gl2psPrintPostScriptPrimitive(void *data)
+{
+  int newline;
+  GL2PSprimitive *prim;
+
+  prim = *(GL2PSprimitive**)data;
+
+  if((gl2ps->options & GL2PS_OCCLUSION_CULL) && prim->culled) return;
+
+  /* Every effort is made to draw lines as connected segments (i.e.,
+     using a single PostScript path): this is the only way to get nice
+     line joins and to not restart the stippling for every line
+     segment. So if the primitive to print is not a line we must first
+     finish the current line (if any): */
+  if(prim->type != GL2PS_LINE) gl2psEndPostScriptLine();
+
+  switch(prim->type){
+  case GL2PS_POINT :
+    gl2psPrintPostScriptColor(prim->verts[0].rgba);
+    gl2psPrintf("%g %g %g P\n",
+                prim->verts[0].xyz[0], prim->verts[0].xyz[1], 0.5 * prim->width);
+    break;
+  case GL2PS_LINE :
+    if(!gl2psSamePosition(gl2ps->lastvertex.xyz, prim->verts[0].xyz) ||
+       !gl2psSameColor(gl2ps->lastrgba, prim->verts[0].rgba) ||
+       gl2ps->lastlinewidth != prim->width ||
+       gl2ps->lastpattern != prim->pattern ||
+       gl2ps->lastfactor != prim->factor){
+      /* End the current line if the new segment does not start where
+         the last one ended, or if the color, the width or the
+         stippling have changed (multi-stroking lines with changing
+         colors is necessary until we use /shfill for lines;
+         unfortunately this means that at the moment we can screw up
+         line stippling for smooth-shaded lines) */
+      gl2psEndPostScriptLine();
+      newline = 1;
+    }
+    else{
+      newline = 0;
+    }
+    if(gl2ps->lastlinewidth != prim->width){
+      gl2ps->lastlinewidth = prim->width;
+      gl2psPrintf("%g W\n", gl2ps->lastlinewidth);
+    }
+    gl2psPrintPostScriptDash(prim->pattern, prim->factor, "setdash");
+    gl2psPrintPostScriptColor(prim->verts[0].rgba);
+    gl2psPrintf("%g %g %s\n", prim->verts[0].xyz[0], prim->verts[0].xyz[1],
+                newline ? "LS" : "L");
+    gl2ps->lastvertex = prim->verts[1];
+    break;
+  case GL2PS_TRIANGLE :
+    if(!gl2psVertsSameColor(prim)){
+      gl2psResetPostScriptColor();
+      gl2psPrintf("%g %g %g %g %g %g %g %g %g %g %g %g %g %g %g ST\n",
+                  prim->verts[2].xyz[0], prim->verts[2].xyz[1],
+                  prim->verts[2].rgba[0], prim->verts[2].rgba[1],
+                  prim->verts[2].rgba[2], prim->verts[1].xyz[0],
+                  prim->verts[1].xyz[1], prim->verts[1].rgba[0],
+                  prim->verts[1].rgba[1], prim->verts[1].rgba[2],
+                  prim->verts[0].xyz[0], prim->verts[0].xyz[1],
+                  prim->verts[0].rgba[0], prim->verts[0].rgba[1],
+                  prim->verts[0].rgba[2]);
+    }
+    else{
+      gl2psPrintPostScriptColor(prim->verts[0].rgba);
+      gl2psPrintf("%g %g %g %g %g %g T\n",
+                  prim->verts[2].xyz[0], prim->verts[2].xyz[1],
+                  prim->verts[1].xyz[0], prim->verts[1].xyz[1],
+                  prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
+    }
+    break;
+  case GL2PS_QUADRANGLE :
+    gl2psMsg(GL2PS_WARNING, "There should not be any quad left to print");
+    break;
+  case GL2PS_PIXMAP :
+    gl2psPrintPostScriptPixmap(prim->verts[0].xyz[0], prim->verts[0].xyz[1],
+                               prim->data.image);
+    break;
+  case GL2PS_IMAGEMAP :
+    if(prim->data.image->type != GL2PS_IMAGEMAP_WRITTEN){
+      gl2psPrintPostScriptColor(prim->verts[0].rgba);
+      gl2psPrintPostScriptImagemap(prim->data.image->pixels[0],
+                                   prim->data.image->pixels[1],
+                                   prim->data.image->width, prim->data.image->height,
+                                   (const unsigned char*)(&(prim->data.image->pixels[2])));
+      prim->data.image->type = GL2PS_IMAGEMAP_WRITTEN;
+    }
+    break;
+  case GL2PS_TEXT :
+    gl2psPrintPostScriptColor(prim->verts[0].rgba);
+    gl2psPrintf("(%s) ", prim->data.text->str);
+    if(prim->data.text->angle)
+      gl2psPrintf("%g ", prim->data.text->angle);
+    gl2psPrintf("%g %g %d /%s ",
+                prim->verts[0].xyz[0], prim->verts[0].xyz[1],
+                prim->data.text->fontsize, prim->data.text->fontname);
+    switch(prim->data.text->alignment){
+    case GL2PS_TEXT_C:
+      gl2psPrintf(prim->data.text->angle ? "SCCR\n" : "SCC\n");
+      break;
+    case GL2PS_TEXT_CL:
+      gl2psPrintf(prim->data.text->angle ? "SCLR\n" : "SCL\n");
+      break;
+    case GL2PS_TEXT_CR:
+      gl2psPrintf(prim->data.text->angle ? "SCRR\n" : "SCR\n");
+      break;
+    case GL2PS_TEXT_B:
+      gl2psPrintf(prim->data.text->angle ? "SBCR\n" : "SBC\n");
+      break;
+    case GL2PS_TEXT_BR:
+      gl2psPrintf(prim->data.text->angle ? "SBRR\n" : "SBR\n");
+      break;
+    case GL2PS_TEXT_T:
+      gl2psPrintf(prim->data.text->angle ? "STCR\n" : "STC\n");
+      break;
+    case GL2PS_TEXT_TL:
+      gl2psPrintf(prim->data.text->angle ? "STLR\n" : "STL\n");
+      break;
+    case GL2PS_TEXT_TR:
+      gl2psPrintf(prim->data.text->angle ? "STRR\n" : "STR\n");
+      break;
+    case GL2PS_TEXT_BL:
+    default:
+      gl2psPrintf(prim->data.text->angle ? "SR\n" : "S\n");
+      break;
+    }
+    break;
+  case GL2PS_SPECIAL :
+    /* alignment contains the format for which the special output text
+       is intended */
+    if(prim->data.text->alignment == GL2PS_PS ||
+       prim->data.text->alignment == GL2PS_EPS)
+      gl2psPrintf("%s\n", prim->data.text->str);
+    break;
+  default :
+    break;
+  }
+}
+
+static void gl2psPrintPostScriptFooter(void)
+{
+  gl2psPrintf("grestore\n"
+              "showpage\n"
+              "cleartomark\n"
+              "%%%%PageTrailer\n"
+              "%%%%Trailer\n"
+              "end\n"
+              "%%%%EOF\n");
+
+  gl2psPrintGzipFooter();
+}
+
+static void gl2psPrintPostScriptBeginViewport(GLint viewport[4])
+{
+  GLint index;
+  GLfloat rgba[4];
+  int x = viewport[0], y = viewport[1], w = viewport[2], h = viewport[3];
+
+  glRenderMode(GL_FEEDBACK);
+
+  if(gl2ps->header){
+    gl2psPrintPostScriptHeader();
+    gl2ps->header = GL_FALSE;
+  }
+
+  gl2psPrintf("gsave\n"
+              "1.0 1.0 scale\n");
+
+  if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
+    if(gl2ps->colormode == GL_RGBA || gl2ps->colorsize == 0){
+      glGetFloatv(GL_COLOR_CLEAR_VALUE, rgba);
+    }
+    else{
+      glGetIntegerv(GL_INDEX_CLEAR_VALUE, &index);
+      rgba[0] = gl2ps->colormap[index][0];
+      rgba[1] = gl2ps->colormap[index][1];
+      rgba[2] = gl2ps->colormap[index][2];
+      rgba[3] = 1.0F;
+    }
+    gl2psPrintf("%g %g %g C\n"
+                "newpath %d %d moveto %d %d lineto %d %d lineto %d %d lineto\n"
+                "closepath fill\n",
+                rgba[0], rgba[1], rgba[2],
+                x, y, x+w, y, x+w, y+h, x, y+h);
+  }
+
+  gl2psPrintf("newpath %d %d moveto %d %d lineto %d %d lineto %d %d lineto\n"
+              "closepath clip\n",
+              x, y, x+w, y, x+w, y+h, x, y+h);
+
+}
+
+static GLint gl2psPrintPostScriptEndViewport(void)
+{
+  GLint res;
+
+  res = gl2psPrintPrimitives();
+  gl2psPrintf("grestore\n");
+  return res;
+}
+
+static void gl2psPrintPostScriptFinalPrimitive(void)
+{
+  /* End any remaining line, if any */
+  gl2psEndPostScriptLine();
+}
+
+/* definition of the PostScript and Encapsulated PostScript backends */
+
+static GL2PSbackend gl2psPS = {
+  gl2psPrintPostScriptHeader,
+  gl2psPrintPostScriptFooter,
+  gl2psPrintPostScriptBeginViewport,
+  gl2psPrintPostScriptEndViewport,
+  gl2psPrintPostScriptPrimitive,
+  gl2psPrintPostScriptFinalPrimitive,
+  "ps",
+  "Postscript"
+};
+
+static GL2PSbackend gl2psEPS = {
+  gl2psPrintPostScriptHeader,
+  gl2psPrintPostScriptFooter,
+  gl2psPrintPostScriptBeginViewport,
+  gl2psPrintPostScriptEndViewport,
+  gl2psPrintPostScriptPrimitive,
+  gl2psPrintPostScriptFinalPrimitive,
+  "eps",
+  "Encapsulated Postscript"
+};
+
+/*********************************************************************
+ *
+ * LaTeX routines
+ *
+ *********************************************************************/
+
+static void gl2psPrintTeXHeader(void)
+{
+  char name[256];
+  time_t now;
+  int i;
+
+  if(gl2ps->filename && strlen(gl2ps->filename) < 256){
+    for(i = (int)strlen(gl2ps->filename) - 1; i >= 0; i--){
+      if(gl2ps->filename[i] == '.'){
+        strncpy(name, gl2ps->filename, i);
+        name[i] = '\0';
+        break;
+      }
+    }
+    if(i <= 0) strcpy(name, gl2ps->filename);
+  }
+  else{
+    strcpy(name, "untitled");
+  }
+
+  time(&now);
+
+  fprintf(gl2ps->stream,
+          "%% Title: %s\n"
+          "%% Creator: GL2PS %d.%d.%d%s, %s\n"
+          "%% For: %s\n"
+          "%% CreationDate: %s",
+          gl2ps->title, GL2PS_MAJOR_VERSION, GL2PS_MINOR_VERSION,
+          GL2PS_PATCH_VERSION, GL2PS_EXTRA_VERSION, GL2PS_COPYRIGHT,
+          gl2ps->producer, ctime(&now));
+
+  fprintf(gl2ps->stream,
+          "\\setlength{\\unitlength}{1pt}\n"
+          "\\begin{picture}(0,0)\n"
+          "\\includegraphics{%s}\n"
+          "\\end{picture}%%\n"
+          "%s\\begin{picture}(%d,%d)(0,0)\n",
+          name, (gl2ps->options & GL2PS_LANDSCAPE) ? "\\rotatebox{90}{" : "",
+          (int)gl2ps->viewport[2], (int)gl2ps->viewport[3]);
+}
+
+static void gl2psPrintTeXPrimitive(void *data)
+{
+  GL2PSprimitive *prim;
+
+  prim = *(GL2PSprimitive**)data;
+
+  switch(prim->type){
+  case GL2PS_TEXT :
+    fprintf(gl2ps->stream, "\\fontsize{%d}{0}\n\\selectfont",
+            prim->data.text->fontsize);
+    fprintf(gl2ps->stream, "\\put(%g,%g)",
+            prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
+    if(prim->data.text->angle)
+      fprintf(gl2ps->stream, "{\\rotatebox{%g}", prim->data.text->angle);
+    fprintf(gl2ps->stream, "{\\makebox(0,0)");
+    switch(prim->data.text->alignment){
+    case GL2PS_TEXT_C:
+      fprintf(gl2ps->stream, "{");
+      break;
+    case GL2PS_TEXT_CL:
+      fprintf(gl2ps->stream, "[l]{");
+      break;
+    case GL2PS_TEXT_CR:
+      fprintf(gl2ps->stream, "[r]{");
+      break;
+    case GL2PS_TEXT_B:
+      fprintf(gl2ps->stream, "[b]{");
+      break;
+    case GL2PS_TEXT_BR:
+      fprintf(gl2ps->stream, "[br]{");
+      break;
+    case GL2PS_TEXT_T:
+      fprintf(gl2ps->stream, "[t]{");
+      break;
+    case GL2PS_TEXT_TL:
+      fprintf(gl2ps->stream, "[tl]{");
+      break;
+    case GL2PS_TEXT_TR:
+      fprintf(gl2ps->stream, "[tr]{");
+      break;
+    case GL2PS_TEXT_BL:
+    default:
+      fprintf(gl2ps->stream, "[bl]{");
+      break;
+    }
+    fprintf(gl2ps->stream, "\\textcolor[rgb]{%g,%g,%g}{{%s}}",
+            prim->verts[0].rgba[0], prim->verts[0].rgba[1], prim->verts[0].rgba[2],
+            prim->data.text->str);
+    if(prim->data.text->angle)
+      fprintf(gl2ps->stream, "}");
+    fprintf(gl2ps->stream, "}}\n");
+    break;
+  case GL2PS_SPECIAL :
+    /* alignment contains the format for which the special output text
+       is intended */
+    if (prim->data.text->alignment == GL2PS_TEX)
+      fprintf(gl2ps->stream, "%s\n", prim->data.text->str);
+    break;
+  default :
+    break;
+  }
+}
+
+static void gl2psPrintTeXFooter(void)
+{
+  fprintf(gl2ps->stream, "\\end{picture}%s\n",
+          (gl2ps->options & GL2PS_LANDSCAPE) ? "}" : "");
+}
+
+static void gl2psPrintTeXBeginViewport(GLint viewport[4])
+{
+  (void) viewport;  /* not used */
+  glRenderMode(GL_FEEDBACK);
+
+  if(gl2ps->header){
+    gl2psPrintTeXHeader();
+    gl2ps->header = GL_FALSE;
+  }
+}
+
+static GLint gl2psPrintTeXEndViewport(void)
+{
+  return gl2psPrintPrimitives();
+}
+
+static void gl2psPrintTeXFinalPrimitive(void)
+{
+}
+
+/* definition of the LaTeX backend */
+
+static GL2PSbackend gl2psTEX = {
+  gl2psPrintTeXHeader,
+  gl2psPrintTeXFooter,
+  gl2psPrintTeXBeginViewport,
+  gl2psPrintTeXEndViewport,
+  gl2psPrintTeXPrimitive,
+  gl2psPrintTeXFinalPrimitive,
+  "tex",
+  "LaTeX text"
+};
+
+/*********************************************************************
+ *
+ * PDF routines
+ *
+ *********************************************************************/
+
+static int gl2psPrintPDFCompressorType(void)
+{
+#if defined(GL2PS_HAVE_ZLIB)
+  if(gl2ps->options & GL2PS_COMPRESS){
+    return fprintf(gl2ps->stream, "/Filter [/FlateDecode]\n");
+  }
+#endif
+  return 0;
+}
+
+static int gl2psPrintPDFStrokeColor(GL2PSrgba rgba)
+{
+  int i, offs = 0;
+
+  gl2psSetLastColor(rgba);
+  for(i = 0; i < 3; ++i){
+    if(GL2PS_ZERO(rgba[i]))
+      offs += gl2psPrintf("%.0f ", 0.);
+    else if(rgba[i] < 1e-4 || rgba[i] > 1e6) /* avoid %e formatting */
+      offs += gl2psPrintf("%f ", rgba[i]);
+    else
+      offs += gl2psPrintf("%g ", rgba[i]);
+  }
+  offs += gl2psPrintf("RG\n");
+  return offs;
+}
+
+static int gl2psPrintPDFFillColor(GL2PSrgba rgba)
+{
+  int i, offs = 0;
+
+  for(i = 0; i < 3; ++i){
+    if(GL2PS_ZERO(rgba[i]))
+      offs += gl2psPrintf("%.0f ", 0.);
+    else if(rgba[i] < 1e-4 || rgba[i] > 1e6) /* avoid %e formatting */
+      offs += gl2psPrintf("%f ", rgba[i]);
+    else
+      offs += gl2psPrintf("%g ", rgba[i]);
+  }
+  offs += gl2psPrintf("rg\n");
+  return offs;
+}
+
+static int gl2psPrintPDFLineWidth(GLfloat lw)
+{
+  if(GL2PS_ZERO(lw))
+    return gl2psPrintf("%.0f w\n", 0.);
+  else if(lw < 1e-4 || lw > 1e6) /* avoid %e formatting */
+    return gl2psPrintf("%f w\n", lw);
+  else
+    return gl2psPrintf("%g w\n", lw);
+}
+
+static void gl2psPutPDFText(GL2PSstring *text, int cnt, GLfloat x, GLfloat y)
+{
+  GLfloat rad, crad, srad;
+
+  if(text->angle == 0.0F){
+    gl2ps->streamlength += gl2psPrintf
+      ("BT\n"
+       "/F%d %d Tf\n"
+       "%f %f Td\n"
+       "(%s) Tj\n"
+       "ET\n",
+       cnt, text->fontsize, x, y, text->str);
+  }
+  else{
+    rad = (GLfloat)(M_PI * text->angle / 180.0F);
+    srad = (GLfloat)sin(rad);
+    crad = (GLfloat)cos(rad);
+    gl2ps->streamlength += gl2psPrintf
+      ("BT\n"
+       "/F%d %d Tf\n"
+       "%f %f %f %f %f %f Tm\n"
+       "(%s) Tj\n"
+       "ET\n",
+       cnt, text->fontsize, crad, srad, -srad, crad, x, y, text->str);
+  }
+}
+
+static void gl2psPutPDFImage(GL2PSimage *image, int cnt, GLfloat x, GLfloat y)
+{
+  gl2ps->streamlength += gl2psPrintf
+    ("q\n"
+     "%d 0 0 %d %f %f cm\n"
+     "/Im%d Do\n"
+     "Q\n",
+     (int)image->width, (int)image->height, x, y, cnt);
+}
+
+static void gl2psPDFstacksInit(void)
+{
+  gl2ps->objects_stack = 7 /* FIXED_XREF_ENTRIES */ + 1;
+  gl2ps->extgs_stack = 0;
+  gl2ps->font_stack = 0;
+  gl2ps->im_stack = 0;
+  gl2ps->trgroupobjects_stack = 0;
+  gl2ps->shader_stack = 0;
+  gl2ps->mshader_stack = 0;
+}
+
+static void gl2psPDFgroupObjectInit(GL2PSpdfgroup *gro)
+{
+  if(!gro)
+    return;
+
+  gro->ptrlist = NULL;
+  gro->fontno = gro->gsno = gro->imno = gro->maskshno = gro->shno
+    = gro->trgroupno = gro->fontobjno = gro->imobjno = gro->shobjno
+    = gro->maskshobjno = gro->gsobjno = gro->trgroupobjno = -1;
+}
+
+/* Build up group objects and assign name and object numbers */
+
+static void gl2psPDFgroupListInit(void)
+{
+  int i;
+  GL2PSprimitive *p = NULL;
+  GL2PSpdfgroup gro;
+  int lasttype = GL2PS_NO_TYPE;
+  GL2PSrgba lastrgba = {-1.0F, -1.0F, -1.0F, -1.0F};
+  GLushort lastpattern = 0;
+  GLint lastfactor = 0;
+  GLfloat lastwidth = 1;
+  GL2PStriangle lastt, tmpt;
+  int lastTriangleWasNotSimpleWithSameColor = 0;
+
+  if(!gl2ps->pdfprimlist)
+    return;
+
+  gl2ps->pdfgrouplist = gl2psListCreate(500, 500, sizeof(GL2PSpdfgroup));
+  gl2psInitTriangle(&lastt);
+
+  for(i = 0; i < gl2psListNbr(gl2ps->pdfprimlist); ++i){
+    p = *(GL2PSprimitive**)gl2psListPointer(gl2ps->pdfprimlist, i);
+    switch(p->type){
+    case GL2PS_PIXMAP:
+      gl2psPDFgroupObjectInit(&gro);
+      gro.ptrlist = gl2psListCreate(1, 2, sizeof(GL2PSprimitive*));
+      gro.imno = gl2ps->im_stack++;
+      gl2psListAdd(gro.ptrlist, &p);
+      gl2psListAdd(gl2ps->pdfgrouplist, &gro);
+      break;
+    case GL2PS_TEXT:
+      gl2psPDFgroupObjectInit(&gro);
+      gro.ptrlist = gl2psListCreate(1, 2, sizeof(GL2PSprimitive*));
+      gro.fontno = gl2ps->font_stack++;
+      gl2psListAdd(gro.ptrlist, &p);
+      gl2psListAdd(gl2ps->pdfgrouplist, &gro);
+      break;
+    case GL2PS_LINE:
+      if(lasttype != p->type || lastwidth != p->width ||
+         lastpattern != p->pattern || lastfactor != p->factor ||
+         !gl2psSameColor(p->verts[0].rgba, lastrgba)){
+        gl2psPDFgroupObjectInit(&gro);
+        gro.ptrlist = gl2psListCreate(1, 2, sizeof(GL2PSprimitive*));
+        gl2psListAdd(gro.ptrlist, &p);
+        gl2psListAdd(gl2ps->pdfgrouplist, &gro);
+      }
+      else{
+        gl2psListAdd(gro.ptrlist, &p);
+      }
+      lastpattern = p->pattern;
+      lastfactor = p->factor;
+      lastwidth = p->width;
+      lastrgba[0] = p->verts[0].rgba[0];
+      lastrgba[1] = p->verts[0].rgba[1];
+      lastrgba[2] = p->verts[0].rgba[2];
+      break;
+    case GL2PS_POINT:
+      if(lasttype != p->type || lastwidth != p->width ||
+         !gl2psSameColor(p->verts[0].rgba, lastrgba)){
+        gl2psPDFgroupObjectInit(&gro);
+        gro.ptrlist = gl2psListCreate(1,2,sizeof(GL2PSprimitive*));
+        gl2psListAdd(gro.ptrlist, &p);
+        gl2psListAdd(gl2ps->pdfgrouplist, &gro);
+      }
+      else{
+        gl2psListAdd(gro.ptrlist, &p);
+      }
+      lastwidth = p->width;
+      lastrgba[0] = p->verts[0].rgba[0];
+      lastrgba[1] = p->verts[0].rgba[1];
+      lastrgba[2] = p->verts[0].rgba[2];
+      break;
+    case GL2PS_TRIANGLE:
+      gl2psFillTriangleFromPrimitive(&tmpt, p, GL_TRUE);
+      lastTriangleWasNotSimpleWithSameColor =
+        !(tmpt.prop & T_CONST_COLOR && tmpt.prop & T_ALPHA_1) ||
+        !gl2psSameColor(tmpt.vertex[0].rgba, lastt.vertex[0].rgba);
+      if(lasttype == p->type && tmpt.prop == lastt.prop &&
+         lastTriangleWasNotSimpleWithSameColor){
+        /* TODO Check here for last alpha */
+        gl2psListAdd(gro.ptrlist, &p);
+      }
+      else{
+        gl2psPDFgroupObjectInit(&gro);
+        gro.ptrlist = gl2psListCreate(1, 2, sizeof(GL2PSprimitive*));
+        gl2psListAdd(gro.ptrlist, &p);
+        gl2psListAdd(gl2ps->pdfgrouplist, &gro);
+      }
+      lastt = tmpt;
+      break;
+    default:
+      break;
+    }
+    lasttype = p->type;
+  }
+}
+
+static void gl2psSortOutTrianglePDFgroup(GL2PSpdfgroup *gro)
+{
+  GL2PStriangle t;
+  GL2PSprimitive *prim = NULL;
+
+  if(!gro)
+    return;
+
+  if(!gl2psListNbr(gro->ptrlist))
+    return;
+
+  prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, 0);
+
+  if(prim->type != GL2PS_TRIANGLE)
+    return;
+
+  gl2psFillTriangleFromPrimitive(&t, prim, GL_TRUE);
+
+  if(t.prop & T_CONST_COLOR && t.prop & T_ALPHA_LESS_1){
+    gro->gsno = gl2ps->extgs_stack++;
+    gro->gsobjno = gl2ps->objects_stack ++;
+  }
+  else if(t.prop & T_CONST_COLOR && t.prop & T_VAR_ALPHA){
+    gro->gsno = gl2ps->extgs_stack++;
+    gro->gsobjno = gl2ps->objects_stack++;
+    gro->trgroupno = gl2ps->trgroupobjects_stack++;
+    gro->trgroupobjno = gl2ps->objects_stack++;
+    gro->maskshno = gl2ps->mshader_stack++;
+    gro->maskshobjno = gl2ps->objects_stack++;
+  }
+  else if(t.prop & T_VAR_COLOR && t.prop & T_ALPHA_1){
+    gro->shno = gl2ps->shader_stack++;
+    gro->shobjno = gl2ps->objects_stack++;
+  }
+  else if(t.prop & T_VAR_COLOR && t.prop & T_ALPHA_LESS_1){
+    gro->gsno = gl2ps->extgs_stack++;
+    gro->gsobjno = gl2ps->objects_stack++;
+    gro->shno = gl2ps->shader_stack++;
+    gro->shobjno = gl2ps->objects_stack++;
+  }
+  else if(t.prop & T_VAR_COLOR && t.prop & T_VAR_ALPHA){
+    gro->gsno = gl2ps->extgs_stack++;
+    gro->gsobjno = gl2ps->objects_stack++;
+    gro->shno = gl2ps->shader_stack++;
+    gro->shobjno = gl2ps->objects_stack++;
+    gro->trgroupno = gl2ps->trgroupobjects_stack++;
+    gro->trgroupobjno = gl2ps->objects_stack++;
+    gro->maskshno = gl2ps->mshader_stack++;
+    gro->maskshobjno = gl2ps->objects_stack++;
+  }
+}
+
+/* Main stream data */
+
+static void gl2psPDFgroupListWriteMainStream(void)
+{
+  int i, j, lastel;
+  GL2PSprimitive *prim = NULL, *prev = NULL;
+  GL2PSpdfgroup *gro;
+  GL2PStriangle t;
+
+  if(!gl2ps->pdfgrouplist)
+    return;
+
+  for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){
+    gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i);
+
+    lastel = gl2psListNbr(gro->ptrlist) - 1;
+    if(lastel < 0)
+      continue;
+
+    prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, 0);
+
+    switch(prim->type){
+    case GL2PS_POINT:
+      gl2ps->streamlength += gl2psPrintf("1 J\n");
+      gl2ps->streamlength += gl2psPrintPDFLineWidth(prim->width);
+      gl2ps->streamlength += gl2psPrintPDFStrokeColor(prim->verts[0].rgba);
+      for(j = 0; j <= lastel; ++j){
+        prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
+        gl2ps->streamlength +=
+          gl2psPrintf("%f %f m %f %f l\n",
+                      prim->verts[0].xyz[0], prim->verts[0].xyz[1],
+                      prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
+      }
+      gl2ps->streamlength += gl2psPrintf("S\n");
+      gl2ps->streamlength += gl2psPrintf("0 J\n");
+      break;
+    case GL2PS_LINE:
+      /* We try to use as few paths as possible to draw lines, in
+         order to get nice stippling even when the individual segments
+         are smaller than the stipple */
+      gl2ps->streamlength += gl2psPrintPDFLineWidth(prim->width);
+      gl2ps->streamlength += gl2psPrintPDFStrokeColor(prim->verts[0].rgba);
+      gl2ps->streamlength += gl2psPrintPostScriptDash(prim->pattern, prim->factor, "d");
+      /* start new path */
+      gl2ps->streamlength +=
+        gl2psPrintf("%f %f m\n",
+                    prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
+
+      for(j = 1; j <= lastel; ++j){
+        prev = prim;
+        prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
+        if(!gl2psSamePosition(prim->verts[0].xyz, prev->verts[1].xyz)){
+          /* the starting point of the new segment does not match the
+             end point of the previous line, so we end the current
+             path and start a new one */
+          gl2ps->streamlength +=
+            gl2psPrintf("%f %f l\n",
+                        prev->verts[1].xyz[0], prev->verts[1].xyz[1]);
+          gl2ps->streamlength +=
+            gl2psPrintf("%f %f m\n",
+                        prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
+        }
+        else{
+          /* the two segements are connected, so we just append to the
+             current path */
+          gl2ps->streamlength +=
+            gl2psPrintf("%f %f l\n",
+                        prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
+        }
+      }
+      /* end last path */
+      gl2ps->streamlength +=
+        gl2psPrintf("%f %f l\n",
+                    prim->verts[1].xyz[0], prim->verts[1].xyz[1]);
+      gl2ps->streamlength += gl2psPrintf("S\n");
+      break;
+    case GL2PS_TRIANGLE:
+      gl2psFillTriangleFromPrimitive(&t, prim, GL_TRUE);
+      gl2psSortOutTrianglePDFgroup(gro);
+
+      /* No alpha and const color: Simple PDF draw orders  */
+      if(t.prop & T_CONST_COLOR && t.prop & T_ALPHA_1){
+        gl2ps->streamlength += gl2psPrintPDFFillColor(t.vertex[0].rgba);
+        for(j = 0; j <= lastel; ++j){
+          prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
+          gl2psFillTriangleFromPrimitive(&t, prim, GL_FALSE);
+          gl2ps->streamlength
+            += gl2psPrintf("%f %f m\n"
+                           "%f %f l\n"
+                           "%f %f l\n"
+                           "h f\n",
+                           t.vertex[0].xyz[0], t.vertex[0].xyz[1],
+                           t.vertex[1].xyz[0], t.vertex[1].xyz[1],
+                           t.vertex[2].xyz[0], t.vertex[2].xyz[1]);
+        }
+      }
+      /* Const alpha < 1 and const color: Simple PDF draw orders
+         and an extra extended Graphics State for the alpha const */
+      else if(t.prop & T_CONST_COLOR && t.prop & T_ALPHA_LESS_1){
+        gl2ps->streamlength += gl2psPrintf("q\n"
+                                           "/GS%d gs\n",
+                                           gro->gsno);
+        gl2ps->streamlength += gl2psPrintPDFFillColor(prim->verts[0].rgba);
+        for(j = 0; j <= lastel; ++j){
+          prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
+          gl2psFillTriangleFromPrimitive(&t, prim, GL_FALSE);
+          gl2ps->streamlength
+            += gl2psPrintf("%f %f m\n"
+                           "%f %f l\n"
+                           "%f %f l\n"
+                           "h f\n",
+                           t.vertex[0].xyz[0], t.vertex[0].xyz[1],
+                           t.vertex[1].xyz[0], t.vertex[1].xyz[1],
+                           t.vertex[2].xyz[0], t.vertex[2].xyz[1]);
+        }
+        gl2ps->streamlength += gl2psPrintf("Q\n");
+      }
+      /* Variable alpha and const color: Simple PDF draw orders
+         and an extra extended Graphics State + Xobject + Shader
+         object for the alpha mask */
+      else if(t.prop & T_CONST_COLOR && t.prop & T_VAR_ALPHA){
+        gl2ps->streamlength += gl2psPrintf("q\n"
+                                           "/GS%d gs\n"
+                                           "/TrG%d Do\n",
+                                           gro->gsno, gro->trgroupno);
+        gl2ps->streamlength += gl2psPrintPDFFillColor(prim->verts[0].rgba);
+        for(j = 0; j <= lastel; ++j){
+          prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
+          gl2psFillTriangleFromPrimitive(&t, prim, GL_FALSE);
+          gl2ps->streamlength
+            += gl2psPrintf("%f %f m\n"
+                           "%f %f l\n"
+                           "%f %f l\n"
+                           "h f\n",
+                           t.vertex[0].xyz[0], t.vertex[0].xyz[1],
+                           t.vertex[1].xyz[0], t.vertex[1].xyz[1],
+                           t.vertex[2].xyz[0], t.vertex[2].xyz[1]);
+        }
+        gl2ps->streamlength += gl2psPrintf("Q\n");
+      }
+      /* Variable color and no alpha: Shader Object for the colored
+         triangle(s) */
+      else if(t.prop & T_VAR_COLOR && t.prop & T_ALPHA_1){
+        gl2ps->streamlength += gl2psPrintf("/Sh%d sh\n", gro->shno);
+      }
+      /* Variable color and const alpha < 1: Shader Object for the
+         colored triangle(s) and an extra extended Graphics State
+         for the alpha const */
+      else if(t.prop & T_VAR_COLOR && t.prop & T_ALPHA_LESS_1){
+        gl2ps->streamlength += gl2psPrintf("q\n"
+                                           "/GS%d gs\n"
+                                           "/Sh%d sh\n"
+                                           "Q\n",
+                                           gro->gsno, gro->shno);
+      }
+      /* Variable alpha and color: Shader Object for the colored
+         triangle(s) and an extra extended Graphics State
+         + Xobject + Shader object for the alpha mask */
+      else if(t.prop & T_VAR_COLOR && t.prop & T_VAR_ALPHA){
+        gl2ps->streamlength += gl2psPrintf("q\n"
+                                           "/GS%d gs\n"
+                                           "/TrG%d Do\n"
+                                           "/Sh%d sh\n"
+                                           "Q\n",
+                                           gro->gsno, gro->trgroupno, gro->shno);
+      }
+      break;
+    case GL2PS_PIXMAP:
+      for(j = 0; j <= lastel; ++j){
+        prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
+        gl2psPutPDFImage(prim->data.image, gro->imno, prim->verts[0].xyz[0],
+                         prim->verts[0].xyz[1]);
+      }
+      break;
+    case GL2PS_TEXT:
+      for(j = 0; j <= lastel; ++j){
+        prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
+        gl2ps->streamlength += gl2psPrintPDFFillColor(prim->verts[0].rgba);
+        gl2psPutPDFText(prim->data.text, gro->fontno, prim->verts[0].xyz[0],
+                        prim->verts[0].xyz[1]);
+      }
+      break;
+    default:
+      break;
+    }
+  }
+}
+
+/* Graphics State names */
+
+static int gl2psPDFgroupListWriteGStateResources(void)
+{
+  GL2PSpdfgroup *gro;
+  int offs = 0;
+  int i;
+
+  offs += fprintf(gl2ps->stream,
+                  "/ExtGState\n"
+                  "<<\n"
+                  "/GSa 7 0 R\n");
+  for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){
+    gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i);
+    if(gro->gsno >= 0)
+      offs += fprintf(gl2ps->stream, "/GS%d %d 0 R\n", gro->gsno, gro->gsobjno);
+  }
+  offs += fprintf(gl2ps->stream, ">>\n");
+  return offs;
+}
+
+/* Main Shader names */
+
+static int gl2psPDFgroupListWriteShaderResources(void)
+{
+  GL2PSpdfgroup *gro;
+  int offs = 0;
+  int i;
+
+  offs += fprintf(gl2ps->stream,
+                  "/Shading\n"
+                  "<<\n");
+  for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){
+    gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i);
+    if(gro->shno >= 0)
+      offs += fprintf(gl2ps->stream, "/Sh%d %d 0 R\n", gro->shno, gro->shobjno);
+    if(gro->maskshno >= 0)
+      offs += fprintf(gl2ps->stream, "/TrSh%d %d 0 R\n", gro->maskshno, gro->maskshobjno);
+  }
+  offs += fprintf(gl2ps->stream,">>\n");
+  return offs;
+}
+
+/* Images & Mask Shader XObject names */
+
+static int gl2psPDFgroupListWriteXObjectResources(void)
+{
+  int i;
+  GL2PSprimitive *p = NULL;
+  GL2PSpdfgroup *gro;
+  int offs = 0;
+
+  offs += fprintf(gl2ps->stream,
+                  "/XObject\n"
+                  "<<\n");
+
+  for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){
+    gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i);
+    if(!gl2psListNbr(gro->ptrlist))
+      continue;
+    p = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, 0);
+    switch(p->type){
+    case GL2PS_PIXMAP:
+      gro->imobjno = gl2ps->objects_stack++;
+      if(GL_RGBA == p->data.image->format)  /* reserve one object for image mask */
+        gl2ps->objects_stack++;
+      offs += fprintf(gl2ps->stream, "/Im%d %d 0 R\n", gro->imno, gro->imobjno);
+    case GL2PS_TRIANGLE:
+      if(gro->trgroupno >=0)
+        offs += fprintf(gl2ps->stream, "/TrG%d %d 0 R\n", gro->trgroupno, gro->trgroupobjno);
+      break;
+    default:
+      break;
+    }
+  }
+  offs += fprintf(gl2ps->stream,">>\n");
+  return offs;
+}
+
+/* Font names */
+
+static int gl2psPDFgroupListWriteFontResources(void)
+{
+  int i;
+  GL2PSpdfgroup *gro;
+  int offs = 0;
+
+  offs += fprintf(gl2ps->stream, "/Font\n<<\n");
+
+  for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){
+    gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i);
+    if(gro->fontno < 0)
+      continue;
+    gro->fontobjno = gl2ps->objects_stack++;
+    offs += fprintf(gl2ps->stream, "/F%d %d 0 R\n", gro->fontno, gro->fontobjno);
+  }
+  offs += fprintf(gl2ps->stream, ">>\n");
+
+  return offs;
+}
+
+static void gl2psPDFgroupListDelete(void)
+{
+  int i;
+  GL2PSpdfgroup *gro = NULL;
+
+  if(!gl2ps->pdfgrouplist)
+    return;
+
+  for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){
+    gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist,i);
+    gl2psListDelete(gro->ptrlist);
+  }
+
+  gl2psListDelete(gl2ps->pdfgrouplist);
+  gl2ps->pdfgrouplist = NULL;
+}
+
+/* Print 1st PDF object - file info */
+
+static int gl2psPrintPDFInfo(void)
+{
+  int offs;
+  time_t now;
+  struct tm *newtime;
+
+  time(&now);
+  newtime = gmtime(&now);
+
+  offs = fprintf(gl2ps->stream,
+                 "1 0 obj\n"
+                 "<<\n"
+                 "/Title (%s)\n"
+                 "/Creator (GL2PS %d.%d.%d%s, %s)\n"
+                 "/Producer (%s)\n",
+                 gl2ps->title, GL2PS_MAJOR_VERSION, GL2PS_MINOR_VERSION,
+                 GL2PS_PATCH_VERSION, GL2PS_EXTRA_VERSION, GL2PS_COPYRIGHT,
+                 gl2ps->producer);
+
+  if(!newtime){
+    offs += fprintf(gl2ps->stream,
+                    ">>\n"
+                    "endobj\n");
+    return offs;
+  }
+
+  offs += fprintf(gl2ps->stream,
+                  "/CreationDate (D:%d%02d%02d%02d%02d%02d)\n"
+                  ">>\n"
+                  "endobj\n",
+                  newtime->tm_year+1900,
+                  newtime->tm_mon+1,
+                  newtime->tm_mday,
+                  newtime->tm_hour,
+                  newtime->tm_min,
+                  newtime->tm_sec);
+  return offs;
+}
+
+/* Create catalog and page structure - 2nd and 3th PDF object */
+
+static int gl2psPrintPDFCatalog(void)
+{
+  return fprintf(gl2ps->stream,
+                 "2 0 obj\n"
+                 "<<\n"
+                 "/Type /Catalog\n"
+                 "/Pages 3 0 R\n"
+                 ">>\n"
+                 "endobj\n");
+}
+
+static int gl2psPrintPDFPages(void)
+{
+  return fprintf(gl2ps->stream,
+                 "3 0 obj\n"
+                 "<<\n"
+                 "/Type /Pages\n"
+                 "/Kids [6 0 R]\n"
+                 "/Count 1\n"
+                 ">>\n"
+                 "endobj\n");
+}
+
+/* Open stream for data - graphical objects, fonts etc. PDF object 4 */
+
+static int gl2psOpenPDFDataStream(void)
+{
+  int offs = 0;
+
+  offs += fprintf(gl2ps->stream,
+                  "4 0 obj\n"
+                  "<<\n"
+                  "/Length 5 0 R\n" );
+  offs += gl2psPrintPDFCompressorType();
+  offs += fprintf(gl2ps->stream,
+                  ">>\n"
+                  "stream\n");
+  return offs;
+}
+
+/* Stream setup - Graphics state, fill background if allowed */
+
+static int gl2psOpenPDFDataStreamWritePreface(void)
+{
+  int offs;
+
+  offs = gl2psPrintf("/GSa gs\n");
+
+  if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
+    offs += gl2psPrintPDFFillColor(gl2ps->bgcolor);
+    offs += gl2psPrintf("%d %d %d %d re\n",
+                        (int)gl2ps->viewport[0], (int)gl2ps->viewport[1],
+                        (int)gl2ps->viewport[2], (int)gl2ps->viewport[3]);
+    offs += gl2psPrintf("f\n");
+  }
+  return offs;
+}
+
+/* Use the functions above to create the first part of the PDF*/
+
+static void gl2psPrintPDFHeader(void)
+{
+  int offs = 0;
+  gl2ps->pdfprimlist = gl2psListCreate(500, 500, sizeof(GL2PSprimitive*));
+  gl2psPDFstacksInit();
+
+  gl2ps->xreflist = (int*)gl2psMalloc(sizeof(int) * gl2ps->objects_stack);
+
+#if defined(GL2PS_HAVE_ZLIB)
+  if(gl2ps->options & GL2PS_COMPRESS){
+    gl2psSetupCompress();
+  }
+#endif
+  gl2ps->xreflist[0] = 0;
+  offs += fprintf(gl2ps->stream, "%%PDF-1.4\n");
+  gl2ps->xreflist[1] = offs;
+
+  offs += gl2psPrintPDFInfo();
+  gl2ps->xreflist[2] = offs;
+
+  offs += gl2psPrintPDFCatalog();
+  gl2ps->xreflist[3] = offs;
+
+  offs += gl2psPrintPDFPages();
+  gl2ps->xreflist[4] = offs;
+
+  offs += gl2psOpenPDFDataStream();
+  gl2ps->xreflist[5] = offs; /* finished in gl2psPrintPDFFooter */
+  gl2ps->streamlength = gl2psOpenPDFDataStreamWritePreface();
+}
+
+/* The central primitive drawing */
+
+static void gl2psPrintPDFPrimitive(void *data)
+{
+  GL2PSprimitive *prim = *(GL2PSprimitive**)data;
+
+  if((gl2ps->options & GL2PS_OCCLUSION_CULL) && prim->culled)
+    return;
+
+  prim = gl2psCopyPrimitive(prim); /* deep copy */
+  gl2psListAdd(gl2ps->pdfprimlist, &prim);
+}
+
+/* close stream and ... */
+
+static int gl2psClosePDFDataStream(void)
+{
+  int offs = 0;
+
+#if defined(GL2PS_HAVE_ZLIB)
+  if(gl2ps->options & GL2PS_COMPRESS){
+    if(Z_OK != gl2psDeflate())
+      gl2psMsg(GL2PS_ERROR, "Zlib deflate error");
+    else
+      fwrite(gl2ps->compress->dest, gl2ps->compress->destLen, 1, gl2ps->stream);
+    gl2ps->streamlength += gl2ps->compress->destLen;
+
+    offs += gl2ps->streamlength;
+    gl2psFreeCompress();
+  }
+#endif
+
+  offs += fprintf(gl2ps->stream,
+                  "endstream\n"
+                  "endobj\n");
+  return offs;
+}
+
+/* ... write the now known length object */
+
+static int gl2psPrintPDFDataStreamLength(int val)
+{
+  return fprintf(gl2ps->stream,
+                 "5 0 obj\n"
+                 "%d\n"
+                 "endobj\n", val);
+}
+
+/* Put the info created before in PDF objects */
+
+static int gl2psPrintPDFOpenPage(void)
+{
+  int offs;
+
+  /* Write fixed part */
+
+  offs = fprintf(gl2ps->stream,
+                 "6 0 obj\n"
+                 "<<\n"
+                 "/Type /Page\n"
+                 "/Parent 3 0 R\n"
+                 "/MediaBox [%d %d %d %d]\n",
+                 (int)gl2ps->viewport[0], (int)gl2ps->viewport[1],
+                 (int)gl2ps->viewport[2], (int)gl2ps->viewport[3]);
+
+  if(gl2ps->options & GL2PS_LANDSCAPE)
+    offs += fprintf(gl2ps->stream, "/Rotate -90\n");
+
+  offs += fprintf(gl2ps->stream,
+                  "/Contents 4 0 R\n"
+                  "/Resources\n"
+                  "<<\n"
+                  "/ProcSet [/PDF /Text /ImageB /ImageC]  %%/ImageI\n");
+
+  return offs;
+
+  /* End fixed part, proceeds in gl2psPDFgroupListWriteVariableResources() */
+}
+
+static int gl2psPDFgroupListWriteVariableResources(void)
+{
+  int offs = 0;
+
+  /* a) Graphics States for shader alpha masks*/
+  offs += gl2psPDFgroupListWriteGStateResources();
+
+  /* b) Shader and shader masks */
+  offs += gl2psPDFgroupListWriteShaderResources();
+
+  /* c) XObjects (Images & Shader Masks) */
+  offs += gl2psPDFgroupListWriteXObjectResources();
+
+  /* d) Fonts */
+  offs += gl2psPDFgroupListWriteFontResources();
+
+  /* End resources and page */
+  offs += fprintf(gl2ps->stream,
+                  ">>\n"
+                  ">>\n"
+                  "endobj\n");
+  return offs;
+}
+
+/* Standard Graphics State */
+
+static int gl2psPrintPDFGSObject(void)
+{
+  return fprintf(gl2ps->stream,
+                 "7 0 obj\n"
+                 "<<\n"
+                 "/Type /ExtGState\n"
+                 "/SA false\n"
+                 "/SM 0.02\n"
+                 "/OP false\n"
+                 "/op false\n"
+                 "/OPM 0\n"
+                 "/BG2 /Default\n"
+                 "/UCR2 /Default\n"
+                 "/TR2 /Default\n"
+                 ">>\n"
+                 "endobj\n");
+}
+
+/* Put vertex' edge flag (8bit) and coordinates (32bit) in shader stream */
+
+static int gl2psPrintPDFShaderStreamDataCoord(GL2PSvertex *vertex,
+                                              int (*action)(unsigned long data, int size),
+                                              GLfloat dx, GLfloat dy,
+                                              GLfloat xmin, GLfloat ymin)
+{
+  int offs = 0;
+  unsigned long imap;
+  GLfloat diff;
+  double dmax = ~1UL;
+  char edgeflag = 0;
+
+  /* FIXME: temp bux fix for 64 bit archs: */
+  if(sizeof(unsigned long) == 8) dmax = dmax - 2048.;
+
+  offs += (*action)(edgeflag, 1);
+
+  /* The Shader stream in PDF requires to be in a 'big-endian'
+     order */
+
+  if(GL2PS_ZERO(dx * dy)){
+    offs += (*action)(0, 4);
+    offs += (*action)(0, 4);
+  }
+  else{
+    diff = (vertex->xyz[0] - xmin) / dx;
+    if(diff > 1)
+      diff = 1.0F;
+    else if(diff < 0)
+      diff = 0.0F;
+    imap = (unsigned long)(diff * dmax);
+    offs += (*action)(imap, 4);
+
+    diff = (vertex->xyz[1] - ymin) / dy;
+    if(diff > 1)
+      diff = 1.0F;
+    else if(diff < 0)
+      diff = 0.0F;
+    imap = (unsigned long)(diff * dmax);
+    offs += (*action)(imap, 4);
+  }
+
+  return offs;
+}
+
+/* Put vertex' rgb value (8bit for every component) in shader stream */
+
+static int gl2psPrintPDFShaderStreamDataRGB(GL2PSvertex *vertex,
+                                            int (*action)(unsigned long data, int size))
+{
+  int offs = 0;
+  unsigned long imap;
+  double dmax = ~1UL;
+
+  /* FIXME: temp bux fix for 64 bit archs: */
+  if(sizeof(unsigned long) == 8) dmax = dmax - 2048.;
+
+  imap = (unsigned long)((vertex->rgba[0]) * dmax);
+  offs += (*action)(imap, 1);
+
+  imap = (unsigned long)((vertex->rgba[1]) * dmax);
+  offs += (*action)(imap, 1);
+
+  imap = (unsigned long)((vertex->rgba[2]) * dmax);
+  offs += (*action)(imap, 1);
+
+  return offs;
+}
+
+/* Put vertex' alpha (8/16bit) in shader stream */
+
+static int gl2psPrintPDFShaderStreamDataAlpha(GL2PSvertex *vertex,
+                                              int (*action)(unsigned long data, int size),
+                                              int sigbyte)
+{
+  int offs = 0;
+  unsigned long imap;
+  double dmax = ~1UL;
+
+  /* FIXME: temp bux fix for 64 bit archs: */
+  if(sizeof(unsigned long) == 8) dmax = dmax - 2048.;
+
+  if(sigbyte != 8 && sigbyte != 16)
+    sigbyte = 8;
+
+  sigbyte /= 8;
+
+  imap = (unsigned long)((vertex->rgba[3]) * dmax);
+
+  offs += (*action)(imap, sigbyte);
+
+  return offs;
+}
+
+/* Put a triangles raw data in shader stream */
+
+static int gl2psPrintPDFShaderStreamData(GL2PStriangle *triangle,
+                                         GLfloat dx, GLfloat dy,
+                                         GLfloat xmin, GLfloat ymin,
+                                         int (*action)(unsigned long data, int size),
+                                         int gray)
+{
+  int i, offs = 0;
+  GL2PSvertex v;
+
+  if(gray && gray != 8 && gray != 16)
+    gray = 8;
+
+  for(i = 0; i < 3; ++i){
+    offs += gl2psPrintPDFShaderStreamDataCoord(&triangle->vertex[i], action,
+                                               dx, dy, xmin, ymin);
+    if(gray){
+      v = triangle->vertex[i];
+      offs += gl2psPrintPDFShaderStreamDataAlpha(&v, action, gray);
+    }
+    else{
+      offs += gl2psPrintPDFShaderStreamDataRGB(&triangle->vertex[i], action);
+    }
+  }
+
+  return offs;
+}
+
+static void gl2psPDFRectHull(GLfloat *xmin, GLfloat *xmax,
+                             GLfloat *ymin, GLfloat *ymax,
+                             GL2PStriangle *triangles, int cnt)
+{
+  int i, j;
+
+  *xmin = triangles[0].vertex[0].xyz[0];
+  *xmax = triangles[0].vertex[0].xyz[0];
+  *ymin = triangles[0].vertex[0].xyz[1];
+  *ymax = triangles[0].vertex[0].xyz[1];
+
+  for(i = 0; i < cnt; ++i){
+    for(j = 0; j < 3; ++j){
+      if(*xmin > triangles[i].vertex[j].xyz[0])
+        *xmin = triangles[i].vertex[j].xyz[0];
+      if(*xmax < triangles[i].vertex[j].xyz[0])
+        *xmax = triangles[i].vertex[j].xyz[0];
+      if(*ymin > triangles[i].vertex[j].xyz[1])
+        *ymin = triangles[i].vertex[j].xyz[1];
+      if(*ymax < triangles[i].vertex[j].xyz[1])
+        *ymax = triangles[i].vertex[j].xyz[1];
+    }
+  }
+}
+
+/* Writes shaded triangle
+   gray == 0 means write RGB triangles
+   gray == 8             8bit-grayscale (for alpha masks)
+   gray == 16            16bit-grayscale (for alpha masks) */
+
+static int gl2psPrintPDFShader(int obj, GL2PStriangle *triangles,
+                               int size, int gray)
+{
+  int i, offs = 0, vertexbytes, done = 0;
+  GLfloat xmin, xmax, ymin, ymax;
+
+  switch(gray){
+  case 0:
+    vertexbytes = 1+4+4+1+1+1;
+    break;
+  case 8:
+    vertexbytes = 1+4+4+1;
+    break;
+  case 16:
+    vertexbytes = 1+4+4+2;
+    break;
+  default:
+    gray = 8;
+    vertexbytes = 1+4+4+1;
+    break;
+  }
+
+  gl2psPDFRectHull(&xmin, &xmax, &ymin, &ymax, triangles, size);
+
+  offs += fprintf(gl2ps->stream,
+                  "%d 0 obj\n"
+                  "<< "
+                  "/ShadingType 4 "
+                  "/ColorSpace %s "
+                  "/BitsPerCoordinate 32 "
+                  "/BitsPerComponent %d "
+                  "/BitsPerFlag 8 "
+                  "/Decode [%f %f %f %f 0 1 %s] ",
+                  obj,
+                  (gray) ? "/DeviceGray" : "/DeviceRGB",
+                  (gray) ? gray : 8,
+                  xmin, xmax, ymin, ymax,
+                  (gray) ? "" : "0 1 0 1");
+
+#if defined(GL2PS_HAVE_ZLIB)
+  if(gl2ps->options & GL2PS_COMPRESS){
+    gl2psAllocCompress(vertexbytes * size * 3);
+
+    for(i = 0; i < size; ++i)
+      gl2psPrintPDFShaderStreamData(&triangles[i],
+                                    xmax-xmin, ymax-ymin, xmin, ymin,
+                                    gl2psWriteBigEndianCompress, gray);
+
+    if(Z_OK == gl2psDeflate() && 23 + gl2ps->compress->destLen < gl2ps->compress->srcLen){
+      offs += gl2psPrintPDFCompressorType();
+      offs += fprintf(gl2ps->stream,
+                      "/Length %d "
+                      ">>\n"
+                      "stream\n",
+                      (int)gl2ps->compress->destLen);
+      offs += gl2ps->compress->destLen * fwrite(gl2ps->compress->dest,
+                                                gl2ps->compress->destLen,
+                                                1, gl2ps->stream);
+      done = 1;
+    }
+    gl2psFreeCompress();
+  }
+#endif
+
+  if(!done){
+    /* no compression, or too long after compression, or compress error
+       -> write non-compressed entry */
+    offs += fprintf(gl2ps->stream,
+                    "/Length %d "
+                    ">>\n"
+                    "stream\n",
+                    vertexbytes * 3 * size);
+    for(i = 0; i < size; ++i)
+      offs += gl2psPrintPDFShaderStreamData(&triangles[i],
+                                            xmax-xmin, ymax-ymin, xmin, ymin,
+                                            gl2psWriteBigEndian, gray);
+  }
+
+  offs += fprintf(gl2ps->stream,
+                  "\nendstream\n"
+                  "endobj\n");
+
+  return offs;
+}
+
+/* Writes a XObject for a shaded triangle mask */
+
+static int gl2psPrintPDFShaderMask(int obj, int childobj)
+{
+  int offs = 0, len;
+
+  offs += fprintf(gl2ps->stream,
+                  "%d 0 obj\n"
+                  "<<\n"
+                  "/Type /XObject\n"
+                  "/Subtype /Form\n"
+                  "/BBox [ %d %d %d %d ]\n"
+                  "/Group \n<<\n/S /Transparency /CS /DeviceRGB\n"
+                  ">>\n",
+                  obj,
+                  (int)gl2ps->viewport[0], (int)gl2ps->viewport[1],
+                  (int)gl2ps->viewport[2], (int)gl2ps->viewport[3]);
+
+  len = (childobj>0)
+    ? strlen("/TrSh sh\n") + (int)log10((double)childobj)+1
+    : strlen("/TrSh0 sh\n");
+
+  offs += fprintf(gl2ps->stream,
+                  "/Length %d\n"
+                  ">>\n"
+                  "stream\n",
+                  len);
+  offs += fprintf(gl2ps->stream,
+                  "/TrSh%d sh\n",
+                  childobj);
+  offs += fprintf(gl2ps->stream,
+                  "endstream\n"
+                  "endobj\n");
+
+  return offs;
+}
+
+/* Writes a Extended graphics state for a shaded triangle mask if
+   simplealpha ist true the childobj argument is ignored and a /ca
+   statement will be written instead */
+
+static int gl2psPrintPDFShaderExtGS(int obj, int childobj)
+{
+  int offs = 0;
+
+  offs += fprintf(gl2ps->stream,
+                  "%d 0 obj\n"
+                  "<<\n",
+                  obj);
+
+  offs += fprintf(gl2ps->stream,
+                  "/SMask << /S /Alpha /G %d 0 R >> ",
+                  childobj);
+
+  offs += fprintf(gl2ps->stream,
+                  ">>\n"
+                  "endobj\n");
+  return offs;
+}
+
+/* a simple graphics state */
+
+static int gl2psPrintPDFShaderSimpleExtGS(int obj, GLfloat alpha)
+{
+  int offs = 0;
+
+  offs += fprintf(gl2ps->stream,
+                  "%d 0 obj\n"
+                  "<<\n"
+                  "/ca %g"
+                  ">>\n"
+                  "endobj\n",
+                  obj, alpha);
+  return offs;
+}
+
+/* Similar groups of functions for pixmaps and text */
+
+static int gl2psPrintPDFPixmapStreamData(GL2PSimage *im,
+                                         int (*action)(unsigned long data, int size),
+                                         int gray)
+{
+  int x, y, shift;
+  GLfloat r, g, b, a;
+
+  if(im->format != GL_RGBA && gray)
+    return 0;
+
+  if(gray && gray != 8 && gray != 16)
+    gray = 8;
+
+  gray /= 8;
+
+  shift = (sizeof(unsigned long) - 1) * 8;
+
+  for(y = 0; y < im->height; ++y){
+    for(x = 0; x < im->width; ++x){
+      a = gl2psGetRGB(im, x, y, &r, &g, &b);
+      if(im->format == GL_RGBA && gray){
+        (*action)((unsigned long)(a * 255) << shift, gray);
+      }
+      else{
+        (*action)((unsigned long)(r * 255) << shift, 1);
+        (*action)((unsigned long)(g * 255) << shift, 1);
+        (*action)((unsigned long)(b * 255) << shift, 1);
+      }
+    }
+  }
+
+  switch(gray){
+  case 0: return 3 * im->width * im->height;
+  case 1: return im->width * im->height;
+  case 2: return 2 * im->width * im->height;
+  default: return 3 * im->width * im->height;
+  }
+}
+
+static int gl2psPrintPDFPixmap(int obj, int childobj, GL2PSimage *im, int gray)
+{
+  int offs = 0, done = 0, sigbytes = 3;
+
+  if(gray && gray !=8 && gray != 16)
+    gray = 8;
+
+  if(gray)
+    sigbytes = gray / 8;
+
+  offs += fprintf(gl2ps->stream,
+                  "%d 0 obj\n"
+                  "<<\n"
+                  "/Type /XObject\n"
+                  "/Subtype /Image\n"
+                  "/Width %d\n"
+                  "/Height %d\n"
+                  "/ColorSpace %s \n"
+                  "/BitsPerComponent 8\n",
+                  obj,
+                  (int)im->width, (int)im->height,
+                  (gray) ? "/DeviceGray" : "/DeviceRGB" );
+  if(GL_RGBA == im->format && gray == 0){
+    offs += fprintf(gl2ps->stream,
+                    "/SMask %d 0 R\n",
+                    childobj);
+  }
+
+#if defined(GL2PS_HAVE_ZLIB)
+  if(gl2ps->options & GL2PS_COMPRESS){
+    gl2psAllocCompress((int)(im->width * im->height * sigbytes));
+
+    gl2psPrintPDFPixmapStreamData(im, gl2psWriteBigEndianCompress, gray);
+
+    if(Z_OK == gl2psDeflate() && 23 + gl2ps->compress->destLen < gl2ps->compress->srcLen){
+      offs += gl2psPrintPDFCompressorType();
+      offs += fprintf(gl2ps->stream,
+                      "/Length %d "
+                      ">>\n"
+                      "stream\n",
+                      (int)gl2ps->compress->destLen);
+      offs += gl2ps->compress->destLen * fwrite(gl2ps->compress->dest, gl2ps->compress->destLen,
+                                                1, gl2ps->stream);
+      done = 1;
+    }
+    gl2psFreeCompress();
+  }
+#endif
+
+  if(!done){
+    /* no compression, or too long after compression, or compress error
+       -> write non-compressed entry */
+    offs += fprintf(gl2ps->stream,
+                    "/Length %d "
+                    ">>\n"
+                    "stream\n",
+                    (int)(im->width * im->height * sigbytes));
+    offs += gl2psPrintPDFPixmapStreamData(im, gl2psWriteBigEndian, gray);
+  }
+
+  offs += fprintf(gl2ps->stream,
+                  "\nendstream\n"
+                  "endobj\n");
+
+  return offs;
+}
+
+static int gl2psPrintPDFText(int obj, GL2PSstring *s, int fontnumber)
+{
+  int offs = 0;
+
+  offs += fprintf(gl2ps->stream,
+                  "%d 0 obj\n"
+                  "<<\n"
+                  "/Type /Font\n"
+                  "/Subtype /Type1\n"
+                  "/Name /F%d\n"
+                  "/BaseFont /%s\n"
+                  "/Encoding /MacRomanEncoding\n"
+                  ">>\n"
+                  "endobj\n",
+                  obj, fontnumber, s->fontname);
+  return offs;
+}
+
+/* Write the physical objects */
+
+static int gl2psPDFgroupListWriteObjects(int entryoffs)
+{
+  int i,j;
+  GL2PSprimitive *p = NULL;
+  GL2PSpdfgroup *gro;
+  int offs = entryoffs;
+  GL2PStriangle *triangles;
+  int size = 0;
+
+  if(!gl2ps->pdfgrouplist)
+    return offs;
+
+  for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){
+    gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i);
+    if(!gl2psListNbr(gro->ptrlist))
+      continue;
+    p = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, 0);
+    switch(p->type){
+    case GL2PS_POINT:
+      break;
+    case GL2PS_LINE:
+      break;
+    case GL2PS_TRIANGLE:
+      size = gl2psListNbr(gro->ptrlist);
+      triangles = (GL2PStriangle*)gl2psMalloc(sizeof(GL2PStriangle) * size);
+      for(j = 0; j < size; ++j){
+        p = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
+        gl2psFillTriangleFromPrimitive(&triangles[j], p, GL_TRUE);
+      }
+      if(triangles[0].prop & T_VAR_COLOR){
+        gl2ps->xreflist[gro->shobjno] = offs;
+        offs += gl2psPrintPDFShader(gro->shobjno, triangles, size, 0);
+      }
+      if(triangles[0].prop & T_ALPHA_LESS_1){
+        gl2ps->xreflist[gro->gsobjno] = offs;
+        offs += gl2psPrintPDFShaderSimpleExtGS(gro->gsobjno, triangles[0].vertex[0].rgba[3]);
+      }
+      if(triangles[0].prop & T_VAR_ALPHA){
+        gl2ps->xreflist[gro->gsobjno] = offs;
+        offs += gl2psPrintPDFShaderExtGS(gro->gsobjno, gro->trgroupobjno);
+        gl2ps->xreflist[gro->trgroupobjno] = offs;
+        offs += gl2psPrintPDFShaderMask(gro->trgroupobjno, gro->maskshno);
+        gl2ps->xreflist[gro->maskshobjno] = offs;
+        offs += gl2psPrintPDFShader(gro->maskshobjno, triangles, size, 8);
+      }
+      gl2psFree(triangles);
+      break;
+    case GL2PS_PIXMAP:
+      gl2ps->xreflist[gro->imobjno] = offs;
+      offs += gl2psPrintPDFPixmap(gro->imobjno, gro->imobjno+1, p->data.image, 0);
+      if(p->data.image->format == GL_RGBA){
+        gl2ps->xreflist[gro->imobjno+1] = offs;
+        offs += gl2psPrintPDFPixmap(gro->imobjno+1, -1, p->data.image, 8);
+      }
+      break;
+    case GL2PS_TEXT:
+      gl2ps->xreflist[gro->fontobjno] = offs;
+      offs += gl2psPrintPDFText(gro->fontobjno,p->data.text,gro->fontno);
+      break;
+    case GL2PS_SPECIAL :
+      /* alignment contains the format for which the special output text
+         is intended */
+      if(p->data.text->alignment == GL2PS_PDF)
+        offs += fprintf(gl2ps->stream, "%s\n", p->data.text->str);
+      break;
+    default:
+      break;
+    }
+  }
+  return offs;
+}
+
+/* All variable data has been written at this point and all required
+   functioninality has been gathered, so we can write now file footer
+   with cross reference table and trailer */
+
+static void gl2psPrintPDFFooter(void)
+{
+  int i, offs;
+
+  gl2psPDFgroupListInit();
+  gl2psPDFgroupListWriteMainStream();
+
+  offs = gl2ps->xreflist[5] + gl2ps->streamlength;
+  offs += gl2psClosePDFDataStream();
+  gl2ps->xreflist[5] = offs;
+
+  offs += gl2psPrintPDFDataStreamLength(gl2ps->streamlength);
+  gl2ps->xreflist[6] = offs;
+  gl2ps->streamlength = 0;
+
+  offs += gl2psPrintPDFOpenPage();
+  offs += gl2psPDFgroupListWriteVariableResources();
+  gl2ps->xreflist = (int*)gl2psRealloc(gl2ps->xreflist,
+                                       sizeof(int) * (gl2ps->objects_stack + 1));
+  gl2ps->xreflist[7] = offs;
+
+  offs += gl2psPrintPDFGSObject();
+  gl2ps->xreflist[8] = offs;
+
+  gl2ps->xreflist[gl2ps->objects_stack] =
+    gl2psPDFgroupListWriteObjects(gl2ps->xreflist[8]);
+
+  /* Start cross reference table. The file has to been opened in
+     binary mode to preserve the 20 digit string length! */
+  fprintf(gl2ps->stream,
+          "xref\n"
+          "0 %d\n"
+          "%010d 65535 f \n", gl2ps->objects_stack, 0);
+
+  for(i = 1; i < gl2ps->objects_stack; ++i)
+    fprintf(gl2ps->stream, "%010d 00000 n \n", gl2ps->xreflist[i]);
+
+  fprintf(gl2ps->stream,
+          "trailer\n"
+          "<<\n"
+          "/Size %d\n"
+          "/Info 1 0 R\n"
+          "/Root 2 0 R\n"
+          ">>\n"
+          "startxref\n%d\n"
+          "%%%%EOF\n",
+          gl2ps->objects_stack, gl2ps->xreflist[gl2ps->objects_stack]);
+
+  /* Free auxiliary lists and arrays */
+  gl2psFree(gl2ps->xreflist);
+  gl2psListAction(gl2ps->pdfprimlist, gl2psFreePrimitive);
+  gl2psListDelete(gl2ps->pdfprimlist);
+  gl2psPDFgroupListDelete();
+
+#if defined(GL2PS_HAVE_ZLIB)
+  if(gl2ps->options & GL2PS_COMPRESS){
+    gl2psFreeCompress();
+    gl2psFree(gl2ps->compress);
+    gl2ps->compress = NULL;
+  }
+#endif
+}
+
+/* PDF begin viewport */
+
+static void gl2psPrintPDFBeginViewport(GLint viewport[4])
+{
+  int offs = 0;
+  GLint index;
+  GLfloat rgba[4];
+  int x = viewport[0], y = viewport[1], w = viewport[2], h = viewport[3];
+
+  glRenderMode(GL_FEEDBACK);
+
+  if(gl2ps->header){
+    gl2psPrintPDFHeader();
+    gl2ps->header = GL_FALSE;
+  }
+
+  offs += gl2psPrintf("q\n");
+
+  if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
+    if(gl2ps->colormode == GL_RGBA || gl2ps->colorsize == 0){
+      glGetFloatv(GL_COLOR_CLEAR_VALUE, rgba);
+    }
+    else{
+      glGetIntegerv(GL_INDEX_CLEAR_VALUE, &index);
+      rgba[0] = gl2ps->colormap[index][0];
+      rgba[1] = gl2ps->colormap[index][1];
+      rgba[2] = gl2ps->colormap[index][2];
+      rgba[3] = 1.0F;
+    }
+    offs += gl2psPrintPDFFillColor(rgba);
+    offs += gl2psPrintf("%d %d %d %d re\n"
+                        "W\n"
+                        "f\n",
+                        x, y, w, h);
+  }
+  else{
+    offs += gl2psPrintf("%d %d %d %d re\n"
+                        "W\n"
+                        "n\n",
+                        x, y, w, h);
+  }
+
+  gl2ps->streamlength += offs;
+}
+
+static GLint gl2psPrintPDFEndViewport(void)
+{
+  GLint res;
+
+  res = gl2psPrintPrimitives();
+  gl2ps->streamlength += gl2psPrintf("Q\n");
+  return res;
+}
+
+static void gl2psPrintPDFFinalPrimitive(void)
+{
+}
+
+/* definition of the PDF backend */
+
+static GL2PSbackend gl2psPDF = {
+  gl2psPrintPDFHeader,
+  gl2psPrintPDFFooter,
+  gl2psPrintPDFBeginViewport,
+  gl2psPrintPDFEndViewport,
+  gl2psPrintPDFPrimitive,
+  gl2psPrintPDFFinalPrimitive,
+  "pdf",
+  "Portable Document Format"
+};
+
+/*********************************************************************
+ *
+ * SVG routines
+ *
+ *********************************************************************/
+
+static void gl2psSVGGetCoordsAndColors(int n, GL2PSvertex *verts,
+                                       GL2PSxyz *xyz, GL2PSrgba *rgba)
+{
+  int i, j;
+
+  for(i = 0; i < n; i++){
+    xyz[i][0] = verts[i].xyz[0];
+    xyz[i][1] = gl2ps->viewport[3] - verts[i].xyz[1];
+    xyz[i][2] = 0.0F;
+    for(j = 0; j < 4; j++)
+      rgba[i][j] = verts[i].rgba[j];
+  }
+}
+
+static void gl2psSVGGetColorString(GL2PSrgba rgba, char str[32])
+{
+  int r = (int)(255. * rgba[0]);
+  int g = (int)(255. * rgba[1]);
+  int b = (int)(255. * rgba[2]);
+  int rc = (r < 0) ? 0 : (r > 255) ? 255 : r;
+  int gc = (g < 0) ? 0 : (g > 255) ? 255 : g;
+  int bc = (b < 0) ? 0 : (b > 255) ? 255 : b;
+  sprintf(str, "#%2.2x%2.2x%2.2x", rc, gc, bc);
+}
+
+static void gl2psPrintSVGHeader(void)
+{
+  int x, y, width, height;
+  char col[32];
+  time_t now;
+
+  time(&now);
+
+  if (gl2ps->options & GL2PS_LANDSCAPE){
+    x = (int)gl2ps->viewport[1];
+    y = (int)gl2ps->viewport[0];
+    width = (int)gl2ps->viewport[3];
+    height = (int)gl2ps->viewport[2];
+  }
+  else{
+    x = (int)gl2ps->viewport[0];
+    y = (int)gl2ps->viewport[1];
+    width = (int)gl2ps->viewport[2];
+    height = (int)gl2ps->viewport[3];
+  }
+
+  /* Compressed SVG files (.svgz) are simply gzipped SVG files */
+  gl2psPrintGzipHeader();
+
+  gl2psPrintf("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n");
+  gl2psPrintf("<svg xmlns=\"http://www.w3.org/2000/svg\"\n");
+  gl2psPrintf("     xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n"
+              "     width=\"%dpx\" height=\"%dpx\" viewBox=\"%d %d %d %d\">\n",
+              width, height, x, y, width, height);
+  gl2psPrintf("<title>%s</title>\n", gl2ps->title);
+  gl2psPrintf("<desc>\n");
+  gl2psPrintf("Creator: GL2PS %d.%d.%d%s, %s\n"
+              "For: %s\n"
+              "CreationDate: %s",
+              GL2PS_MAJOR_VERSION, GL2PS_MINOR_VERSION, GL2PS_PATCH_VERSION,
+              GL2PS_EXTRA_VERSION, GL2PS_COPYRIGHT, gl2ps->producer, ctime(&now));
+  gl2psPrintf("</desc>\n");
+  gl2psPrintf("<defs>\n");
+  gl2psPrintf("</defs>\n");
+
+  if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
+    gl2psSVGGetColorString(gl2ps->bgcolor, col);
+    gl2psPrintf("<polygon fill=\"%s\" points=\"%d,%d %d,%d %d,%d %d,%d\"/>\n", col,
+                (int)gl2ps->viewport[0], (int)gl2ps->viewport[1],
+                (int)gl2ps->viewport[2], (int)gl2ps->viewport[1],
+                (int)gl2ps->viewport[2], (int)gl2ps->viewport[3],
+                (int)gl2ps->viewport[0], (int)gl2ps->viewport[3]);
+  }
+
+  /* group all the primitives and disable antialiasing */
+  gl2psPrintf("<g shape-rendering=\"crispEdges\">\n");
+}
+
+static void gl2psPrintSVGSmoothTriangle(GL2PSxyz xyz[3], GL2PSrgba rgba[3])
+{
+  int i;
+  GL2PSxyz xyz2[3];
+  GL2PSrgba rgba2[3];
+  char col[32];
+
+  /* Apparently there is no easy way to do Gouraud shading in SVG
+     without explicitly pre-defining gradients, so for now we just do
+     recursive subdivision */
+
+  if(gl2psSameColorThreshold(3, rgba, gl2ps->threshold)){
+    gl2psSVGGetColorString(rgba[0], col);
+    gl2psPrintf("<polygon fill=\"%s\" ", col);
+    if(rgba[0][3] < 1.0F) gl2psPrintf("fill-opacity=\"%g\" ", rgba[0][3]);
+    gl2psPrintf("points=\"%g,%g %g,%g %g,%g\"/>\n", xyz[0][0], xyz[0][1],
+                xyz[1][0], xyz[1][1], xyz[2][0], xyz[2][1]);
+  }
+  else{
+    /* subdivide into 4 subtriangles */
+    for(i = 0; i < 3; i++){
+      xyz2[0][i] = xyz[0][i];
+      xyz2[1][i] = 0.5F * (xyz[0][i] + xyz[1][i]);
+      xyz2[2][i] = 0.5F * (xyz[0][i] + xyz[2][i]);
+    }
+    for(i = 0; i < 4; i++){
+      rgba2[0][i] = rgba[0][i];
+      rgba2[1][i] = 0.5F * (rgba[0][i] + rgba[1][i]);
+      rgba2[2][i] = 0.5F * (rgba[0][i] + rgba[2][i]);
+    }
+    gl2psPrintSVGSmoothTriangle(xyz2, rgba2);
+    for(i = 0; i < 3; i++){
+      xyz2[0][i] = 0.5F * (xyz[0][i] + xyz[1][i]);
+      xyz2[1][i] = xyz[1][i];
+      xyz2[2][i] = 0.5F * (xyz[1][i] + xyz[2][i]);
+    }
+    for(i = 0; i < 4; i++){
+      rgba2[0][i] = 0.5F * (rgba[0][i] + rgba[1][i]);
+      rgba2[1][i] = rgba[1][i];
+      rgba2[2][i] = 0.5F * (rgba[1][i] + rgba[2][i]);
+    }
+    gl2psPrintSVGSmoothTriangle(xyz2, rgba2);
+    for(i = 0; i < 3; i++){
+      xyz2[0][i] = 0.5F * (xyz[0][i] + xyz[2][i]);
+      xyz2[1][i] = xyz[2][i];
+      xyz2[2][i] = 0.5F * (xyz[1][i] + xyz[2][i]);
+    }
+    for(i = 0; i < 4; i++){
+      rgba2[0][i] = 0.5F * (rgba[0][i] + rgba[2][i]);
+      rgba2[1][i] = rgba[2][i];
+      rgba2[2][i] = 0.5F * (rgba[1][i] + rgba[2][i]);
+    }
+    gl2psPrintSVGSmoothTriangle(xyz2, rgba2);
+    for(i = 0; i < 3; i++){
+      xyz2[0][i] = 0.5F * (xyz[0][i] + xyz[1][i]);
+      xyz2[1][i] = 0.5F * (xyz[1][i] + xyz[2][i]);
+      xyz2[2][i] = 0.5F * (xyz[0][i] + xyz[2][i]);
+    }
+    for(i = 0; i < 4; i++){
+      rgba2[0][i] = 0.5F * (rgba[0][i] + rgba[1][i]);
+      rgba2[1][i] = 0.5F * (rgba[1][i] + rgba[2][i]);
+      rgba2[2][i] = 0.5F * (rgba[0][i] + rgba[2][i]);
+    }
+    gl2psPrintSVGSmoothTriangle(xyz2, rgba2);
+  }
+}
+
+static void gl2psPrintSVGDash(GLushort pattern, GLint factor)
+{
+  int i, n, array[10];
+
+  if(!pattern || !factor) return; /* solid line */
+
+  gl2psParseStipplePattern(pattern, factor, &n, array);
+  gl2psPrintf("stroke-dasharray=\"");
+  for(i = 0; i < n; i++){
+    if(i) gl2psPrintf(",");
+    gl2psPrintf("%d", array[i]);
+  }
+  gl2psPrintf("\" ");
+}
+
+static void gl2psEndSVGLine(void)
+{
+  int i;
+  if(gl2ps->lastvertex.rgba[0] >= 0.){
+    gl2psPrintf("%g,%g\"/>\n", gl2ps->lastvertex.xyz[0],
+                gl2ps->viewport[3] - gl2ps->lastvertex.xyz[1]);
+    for(i = 0; i < 3; i++)
+      gl2ps->lastvertex.xyz[i] = -1.;
+    for(i = 0; i < 4; i++)
+      gl2ps->lastvertex.rgba[i] = -1.;
+  }
+}
+
+static void gl2psPrintSVGPixmap(GLfloat x, GLfloat y, GL2PSimage *pixmap)
+{
+#if defined(GL2PS_HAVE_LIBPNG)
+  GL2PSlist *png;
+  unsigned char c;
+  int i;
+
+  /* The only image types supported by the SVG standard are JPEG, PNG
+     and SVG. Here we choose PNG, and since we want to embed the image
+     directly in the SVG stream (and not link to an external image
+     file), we need to encode the pixmap into PNG in memory, then
+     encode it into base64. */
+
+  png = gl2psListCreate(pixmap->width * pixmap->height * 3, 1000,
+                        sizeof(unsigned char));
+  gl2psConvertPixmapToPNG(pixmap, png);
+  gl2psListEncodeBase64(png);
+  gl2psPrintf("<image x=\"%g\" y=\"%g\" width=\"%d\" height=\"%d\"\n",
+              x, y - pixmap->height, pixmap->width, pixmap->height);
+  gl2psPrintf("xlink:href=\"data:image/png;base64,");
+  for(i = 0; i < gl2psListNbr(png); i++){
+    gl2psListRead(png, i, &c);
+    gl2psPrintf("%c", c);
+  }
+  gl2psPrintf("\"/>\n");
+  gl2psListDelete(png);
+#else
+  (void) x; (void) y; (void) pixmap;  /* not used */
+  gl2psMsg(GL2PS_WARNING, "GL2PS must be compiled with PNG support in "
+           "order to embed images in SVG streams");
+#endif
+}
+
+static void gl2psPrintSVGPrimitive(void *data)
+{
+  GL2PSprimitive *prim;
+  GL2PSxyz xyz[4];
+  GL2PSrgba rgba[4];
+  char col[32];
+  int newline;
+
+  prim = *(GL2PSprimitive**)data;
+
+  if((gl2ps->options & GL2PS_OCCLUSION_CULL) && prim->culled) return;
+
+  /* We try to draw connected lines as a single path to get nice line
+     joins and correct stippling. So if the primitive to print is not
+     a line we must first finish the current line (if any): */
+  if(prim->type != GL2PS_LINE) gl2psEndSVGLine();
+
+  gl2psSVGGetCoordsAndColors(prim->numverts, prim->verts, xyz, rgba);
+
+  switch(prim->type){
+  case GL2PS_POINT :
+    gl2psSVGGetColorString(rgba[0], col);
+    gl2psPrintf("<circle fill=\"%s\" ", col);
+    if(rgba[0][3] < 1.0F) gl2psPrintf("fill-opacity=\"%g\" ", rgba[0][3]);
+    gl2psPrintf("cx=\"%g\" cy=\"%g\" r=\"%g\"/>\n",
+                xyz[0][0], xyz[0][1], 0.5 * prim->width);
+    break;
+  case GL2PS_LINE :
+    if(!gl2psSamePosition(gl2ps->lastvertex.xyz, prim->verts[0].xyz) ||
+       !gl2psSameColor(gl2ps->lastrgba, prim->verts[0].rgba) ||
+       gl2ps->lastlinewidth != prim->width ||
+       gl2ps->lastpattern != prim->pattern ||
+       gl2ps->lastfactor != prim->factor){
+      /* End the current line if the new segment does not start where
+         the last one ended, or if the color, the width or the
+         stippling have changed (we will need to use multi-point
+         gradients for smooth-shaded lines) */
+      gl2psEndSVGLine();
+      newline = 1;
+    }
+    else{
+      newline = 0;
+    }
+    gl2ps->lastvertex = prim->verts[1];
+    gl2psSetLastColor(prim->verts[0].rgba);
+    gl2ps->lastlinewidth = prim->width;
+    gl2ps->lastpattern = prim->pattern;
+    gl2ps->lastfactor = prim->factor;
+    if(newline){
+      gl2psSVGGetColorString(rgba[0], col);
+      gl2psPrintf("<polyline fill=\"none\" stroke=\"%s\" stroke-width=\"%g\" ",
+                  col, prim->width);
+      if(rgba[0][3] < 1.0F) gl2psPrintf("stroke-opacity=\"%g\" ", rgba[0][3]);
+      gl2psPrintSVGDash(prim->pattern, prim->factor);
+      gl2psPrintf("points=\"%g,%g ", xyz[0][0], xyz[0][1]);
+    }
+    else{
+      gl2psPrintf("%g,%g ", xyz[0][0], xyz[0][1]);
+    }
+    break;
+  case GL2PS_TRIANGLE :
+    gl2psPrintSVGSmoothTriangle(xyz, rgba);
+    break;
+  case GL2PS_QUADRANGLE :
+    gl2psMsg(GL2PS_WARNING, "There should not be any quad left to print");
+    break;
+  case GL2PS_PIXMAP :
+    gl2psPrintSVGPixmap(xyz[0][0], xyz[0][1], prim->data.image);
+    break;
+  case GL2PS_TEXT :
+    gl2psSVGGetColorString(prim->verts[0].rgba, col);
+    gl2psPrintf("<text fill=\"%s\" x=\"%g\" y=\"%g\" font-size=\"%d\" ",
+                col, xyz[0][0], xyz[0][1], prim->data.text->fontsize);
+    if(prim->data.text->angle)
+      gl2psPrintf("transform=\"rotate(%g, %g, %g)\" ",
+                  -prim->data.text->angle, xyz[0][0], xyz[0][1]);
+    switch(prim->data.text->alignment){
+    case GL2PS_TEXT_C:
+      gl2psPrintf("text-anchor=\"middle\" baseline-shift=\"%d\" ",
+                  -prim->data.text->fontsize / 2);
+      break;
+    case GL2PS_TEXT_CL:
+      gl2psPrintf("text-anchor=\"start\" baseline-shift=\"%d\" ",
+                  -prim->data.text->fontsize / 2);
+      break;
+    case GL2PS_TEXT_CR:
+      gl2psPrintf("text-anchor=\"end\" baseline-shift=\"%d\" ",
+                  -prim->data.text->fontsize / 2);
+      break;
+    case GL2PS_TEXT_B:
+      gl2psPrintf("text-anchor=\"middle\" baseline-shift=\"0\" ");
+      break;
+    case GL2PS_TEXT_BR:
+      gl2psPrintf("text-anchor=\"end\" baseline-shift=\"0\" ");
+      break;
+    case GL2PS_TEXT_T:
+      gl2psPrintf("text-anchor=\"middle\" baseline-shift=\"%d\" ",
+                  -prim->data.text->fontsize);
+      break;
+    case GL2PS_TEXT_TL:
+      gl2psPrintf("text-anchor=\"start\" baseline-shift=\"%d\" ",
+                  -prim->data.text->fontsize);
+      break;
+    case GL2PS_TEXT_TR:
+      gl2psPrintf("text-anchor=\"end\" baseline-shift=\"%d\" ",
+                  -prim->data.text->fontsize);
+      break;
+    case GL2PS_TEXT_BL:
+    default: /* same as GL2PS_TEXT_BL */
+      gl2psPrintf("text-anchor=\"start\" baseline-shift=\"0\" ");
+      break;
+    }
+    if(!strcmp(prim->data.text->fontname, "Times-Roman"))
+      gl2psPrintf("font-family=\"Times\">");
+    else if(!strcmp(prim->data.text->fontname, "Times-Bold"))
+      gl2psPrintf("font-family=\"Times\" font-weight=\"bold\">");
+    else if(!strcmp(prim->data.text->fontname, "Times-Italic"))
+      gl2psPrintf("font-family=\"Times\" font-style=\"italic\">");
+    else if(!strcmp(prim->data.text->fontname, "Times-BoldItalic"))
+      gl2psPrintf("font-family=\"Times\" font-style=\"italic\" font-weight=\"bold\">");
+    else if(!strcmp(prim->data.text->fontname, "Helvetica-Bold"))
+      gl2psPrintf("font-family=\"Helvetica\" font-weight=\"bold\">");
+    else if(!strcmp(prim->data.text->fontname, "Helvetica-Oblique"))
+      gl2psPrintf("font-family=\"Helvetica\" font-style=\"oblique\">");
+    else if(!strcmp(prim->data.text->fontname, "Helvetica-BoldOblique"))
+      gl2psPrintf("font-family=\"Helvetica\" font-style=\"oblique\" font-weight=\"bold\">");
+    else if(!strcmp(prim->data.text->fontname, "Courier-Bold"))
+      gl2psPrintf("font-family=\"Courier\" font-weight=\"bold\">");
+    else if(!strcmp(prim->data.text->fontname, "Courier-Oblique"))
+      gl2psPrintf("font-family=\"Courier\" font-style=\"oblique\">");
+    else if(!strcmp(prim->data.text->fontname, "Courier-BoldOblique"))
+      gl2psPrintf("font-family=\"Courier\" font-style=\"oblique\" font-weight=\"bold\">");
+    else
+      gl2psPrintf("font-family=\"%s\">", prim->data.text->fontname);
+    gl2psPrintf("%s</text>\n", prim->data.text->str);
+    break;
+  case GL2PS_SPECIAL :
+    /* alignment contains the format for which the special output text
+       is intended */
+    if(prim->data.text->alignment == GL2PS_SVG)
+      gl2psPrintf("%s\n", prim->data.text->str);
+    break;
+  default :
+    break;
+  }
+}
+
+static void gl2psPrintSVGFooter(void)
+{
+  gl2psPrintf("</g>\n");
+  gl2psPrintf("</svg>\n");
+
+  gl2psPrintGzipFooter();
+}
+
+static void gl2psPrintSVGBeginViewport(GLint viewport[4])
+{
+  GLint index;
+  char col[32];
+  GLfloat rgba[4];
+  int x = viewport[0], y = viewport[1], w = viewport[2], h = viewport[3];
+
+  glRenderMode(GL_FEEDBACK);
+
+  if(gl2ps->header){
+    gl2psPrintSVGHeader();
+    gl2ps->header = GL_FALSE;
+  }
+
+  if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
+    if(gl2ps->colormode == GL_RGBA || gl2ps->colorsize == 0){
+      glGetFloatv(GL_COLOR_CLEAR_VALUE, rgba);
+    }
+    else{
+      glGetIntegerv(GL_INDEX_CLEAR_VALUE, &index);
+      rgba[0] = gl2ps->colormap[index][0];
+      rgba[1] = gl2ps->colormap[index][1];
+      rgba[2] = gl2ps->colormap[index][2];
+      rgba[3] = 1.0F;
+    }
+    gl2psSVGGetColorString(rgba, col);
+    gl2psPrintf("<polygon fill=\"%s\" points=\"%d,%d %d,%d %d,%d %d,%d\"/>\n", col,
+                x, gl2ps->viewport[3] - y,
+                x + w, gl2ps->viewport[3] - y,
+                x + w, gl2ps->viewport[3] - (y + h),
+                x, gl2ps->viewport[3] - (y + h));
+  }
+
+  gl2psPrintf("<clipPath id=\"cp%d%d%d%d\">\n", x, y, w, h);
+  gl2psPrintf("  <polygon points=\"%d,%d %d,%d %d,%d %d,%d\"/>\n",
+              x, gl2ps->viewport[3] - y,
+              x + w, gl2ps->viewport[3] - y,
+              x + w, gl2ps->viewport[3] - (y + h),
+              x, gl2ps->viewport[3] - (y + h));
+  gl2psPrintf("</clipPath>\n");
+  gl2psPrintf("<g clip-path=\"url(#cp%d%d%d%d)\">\n", x, y, w, h);
+}
+
+static GLint gl2psPrintSVGEndViewport(void)
+{
+  GLint res;
+
+  res = gl2psPrintPrimitives();
+  gl2psPrintf("</g>\n");
+  return res;
+}
+
+static void gl2psPrintSVGFinalPrimitive(void)
+{
+  /* End any remaining line, if any */
+  gl2psEndSVGLine();
+}
+
+/* definition of the SVG backend */
+
+static GL2PSbackend gl2psSVG = {
+  gl2psPrintSVGHeader,
+  gl2psPrintSVGFooter,
+  gl2psPrintSVGBeginViewport,
+  gl2psPrintSVGEndViewport,
+  gl2psPrintSVGPrimitive,
+  gl2psPrintSVGFinalPrimitive,
+  "svg",
+  "Scalable Vector Graphics"
+};
+
+/*********************************************************************
+ *
+ * PGF routines
+ *
+ *********************************************************************/
+
+static void gl2psPrintPGFColor(GL2PSrgba rgba)
+{
+  if(!gl2psSameColor(gl2ps->lastrgba, rgba)){
+    gl2psSetLastColor(rgba);
+    fprintf(gl2ps->stream, "\\color[rgb]{%f,%f,%f}\n", rgba[0], rgba[1], rgba[2]);
+  }
+}
+
+static void gl2psPrintPGFHeader(void)
+{
+  time_t now;
+
+  time(&now);
+
+  fprintf(gl2ps->stream,
+          "%% Title: %s\n"
+          "%% Creator: GL2PS %d.%d.%d%s, %s\n"
+          "%% For: %s\n"
+          "%% CreationDate: %s",
+          gl2ps->title, GL2PS_MAJOR_VERSION, GL2PS_MINOR_VERSION,
+          GL2PS_PATCH_VERSION, GL2PS_EXTRA_VERSION, GL2PS_COPYRIGHT,
+          gl2ps->producer, ctime(&now));
+
+  fprintf(gl2ps->stream, "\\begin{pgfpicture}\n");
+  if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
+    gl2psPrintPGFColor(gl2ps->bgcolor);
+    fprintf(gl2ps->stream,
+            "\\pgfpathrectanglecorners{"
+            "\\pgfpoint{%dpt}{%dpt}}{\\pgfpoint{%dpt}{%dpt}}\n"
+            "\\pgfusepath{fill}\n",
+            (int)gl2ps->viewport[0], (int)gl2ps->viewport[1],
+            (int)gl2ps->viewport[2], (int)gl2ps->viewport[3]);
+  }
+}
+
+static void gl2psPrintPGFDash(GLushort pattern, GLint factor)
+{
+  int i, n, array[10];
+
+  if(pattern == gl2ps->lastpattern && factor == gl2ps->lastfactor)
+    return;
+
+  gl2ps->lastpattern = pattern;
+  gl2ps->lastfactor = factor;
+
+  if(!pattern || !factor){
+    /* solid line */
+    fprintf(gl2ps->stream, "\\pgfsetdash{}{0pt}\n");
+  }
+  else{
+    gl2psParseStipplePattern(pattern, factor, &n, array);
+    fprintf(gl2ps->stream, "\\pgfsetdash{");
+    for(i = 0; i < n; i++) fprintf(gl2ps->stream, "{%dpt}", array[i]);
+    fprintf(gl2ps->stream, "}{0pt}\n");
+  }
+}
+
+static const char *gl2psPGFTextAlignment(int align)
+{
+  switch(align){
+  case GL2PS_TEXT_C  : return "center";
+  case GL2PS_TEXT_CL : return "west";
+  case GL2PS_TEXT_CR : return "east";
+  case GL2PS_TEXT_B  : return "south";
+  case GL2PS_TEXT_BR : return "south east";
+  case GL2PS_TEXT_T  : return "north";
+  case GL2PS_TEXT_TL : return "north west";
+  case GL2PS_TEXT_TR : return "north east";
+  case GL2PS_TEXT_BL :
+  default            : return "south west";
+  }
+}
+
+static void gl2psPrintPGFPrimitive(void *data)
+{
+  GL2PSprimitive *prim;
+
+  prim = *(GL2PSprimitive**)data;
+
+  switch(prim->type){
+  case GL2PS_POINT :
+    /* Points in openGL are rectangular */
+    gl2psPrintPGFColor(prim->verts[0].rgba);
+    fprintf(gl2ps->stream,
+            "\\pgfpathrectangle{\\pgfpoint{%fpt}{%fpt}}"
+            "{\\pgfpoint{%fpt}{%fpt}}\n\\pgfusepath{fill}\n",
+            prim->verts[0].xyz[0]-0.5*prim->width,
+            prim->verts[0].xyz[1]-0.5*prim->width,
+            prim->width,prim->width);
+    break;
+  case GL2PS_LINE :
+    gl2psPrintPGFColor(prim->verts[0].rgba);
+    if(gl2ps->lastlinewidth != prim->width){
+      gl2ps->lastlinewidth = prim->width;
+      fprintf(gl2ps->stream, "\\pgfsetlinewidth{%fpt}\n", gl2ps->lastlinewidth);
+    }
+    gl2psPrintPGFDash(prim->pattern, prim->factor);
+    fprintf(gl2ps->stream,
+            "\\pgfpathmoveto{\\pgfpoint{%fpt}{%fpt}}\n"
+            "\\pgflineto{\\pgfpoint{%fpt}{%fpt}}\n"
+            "\\pgfusepath{stroke}\n",
+            prim->verts[1].xyz[0], prim->verts[1].xyz[1],
+            prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
+    break;
+  case GL2PS_TRIANGLE :
+    if(gl2ps->lastlinewidth != 0){
+      gl2ps->lastlinewidth = 0;
+      fprintf(gl2ps->stream, "\\pgfsetlinewidth{0.01pt}\n");
+    }
+    gl2psPrintPGFColor(prim->verts[0].rgba);
+    fprintf(gl2ps->stream,
+            "\\pgfpathmoveto{\\pgfpoint{%fpt}{%fpt}}\n"
+            "\\pgflineto{\\pgfpoint{%fpt}{%fpt}}\n"
+            "\\pgflineto{\\pgfpoint{%fpt}{%fpt}}\n"
+            "\\pgfpathclose\n"
+            "\\pgfusepath{fill,stroke}\n",
+            prim->verts[2].xyz[0], prim->verts[2].xyz[1],
+            prim->verts[1].xyz[0], prim->verts[1].xyz[1],
+            prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
+    break;
+  case GL2PS_TEXT :
+    fprintf(gl2ps->stream, "{\n\\pgftransformshift{\\pgfpoint{%fpt}{%fpt}}\n",
+            prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
+
+    if(prim->data.text->angle)
+      fprintf(gl2ps->stream, "\\pgftransformrotate{%f}{", prim->data.text->angle);
+
+    fprintf(gl2ps->stream, "\\pgfnode{rectangle}{%s}{\\fontsize{%d}{0}\\selectfont",
+            gl2psPGFTextAlignment(prim->data.text->alignment),
+            prim->data.text->fontsize);
+
+    fprintf(gl2ps->stream, "\\textcolor[rgb]{%g,%g,%g}{{%s}}",
+            prim->verts[0].rgba[0], prim->verts[0].rgba[1],
+            prim->verts[0].rgba[2], prim->data.text->str);
+
+    fprintf(gl2ps->stream, "}{}{\\pgfusepath{discard}}}\n");
+    break;
+  case GL2PS_SPECIAL :
+    /* alignment contains the format for which the special output text
+       is intended */
+    if (prim->data.text->alignment == GL2PS_PGF)
+      fprintf(gl2ps->stream, "%s\n", prim->data.text->str);
+    break;
+  default :
+    break;
+  }
+}
+
+static void gl2psPrintPGFFooter(void)
+{
+  fprintf(gl2ps->stream, "\\end{pgfpicture}\n");
+}
+
+static void gl2psPrintPGFBeginViewport(GLint viewport[4])
+{
+  GLint index;
+  GLfloat rgba[4];
+  int x = viewport[0], y = viewport[1], w = viewport[2], h = viewport[3];
+
+  glRenderMode(GL_FEEDBACK);
+
+  if(gl2ps->header){
+    gl2psPrintPGFHeader();
+    gl2ps->header = GL_FALSE;
+  }
+
+  fprintf(gl2ps->stream, "\\begin{pgfscope}\n");
+  if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
+    if(gl2ps->colormode == GL_RGBA || gl2ps->colorsize == 0){
+      glGetFloatv(GL_COLOR_CLEAR_VALUE, rgba);
+    }
+    else{
+      glGetIntegerv(GL_INDEX_CLEAR_VALUE, &index);
+      rgba[0] = gl2ps->colormap[index][0];
+      rgba[1] = gl2ps->colormap[index][1];
+      rgba[2] = gl2ps->colormap[index][2];
+      rgba[3] = 1.0F;
+    }
+    gl2psPrintPGFColor(rgba);
+    fprintf(gl2ps->stream,
+            "\\pgfpathrectangle{\\pgfpoint{%dpt}{%dpt}}"
+            "{\\pgfpoint{%dpt}{%dpt}}\n"
+            "\\pgfusepath{fill}\n",
+            x, y, w, h);
+  }
+
+  fprintf(gl2ps->stream,
+          "\\pgfpathrectangle{\\pgfpoint{%dpt}{%dpt}}"
+          "{\\pgfpoint{%dpt}{%dpt}}\n"
+          "\\pgfusepath{clip}\n",
+          x, y, w, h);
+}
+
+static GLint gl2psPrintPGFEndViewport(void)
+{
+  GLint res;
+  res = gl2psPrintPrimitives();
+  fprintf(gl2ps->stream, "\\end{pgfscope}\n");
+  return res;
+}
+
+static void gl2psPrintPGFFinalPrimitive(void)
+{
+}
+
+/* definition of the PGF backend */
+
+static GL2PSbackend gl2psPGF = {
+  gl2psPrintPGFHeader,
+  gl2psPrintPGFFooter,
+  gl2psPrintPGFBeginViewport,
+  gl2psPrintPGFEndViewport,
+  gl2psPrintPGFPrimitive,
+  gl2psPrintPGFFinalPrimitive,
+  "tex",
+  "PGF Latex Graphics"
+};
+
+/*********************************************************************
+ *
+ * General primitive printing routine
+ *
+ *********************************************************************/
+
+/* Warning: the ordering of the backends must match the format
+   #defines in gl2ps.h */
+
+static GL2PSbackend *gl2psbackends[] = {
+  &gl2psPS,  /* 0 */
+  &gl2psEPS, /* 1 */
+  &gl2psTEX, /* 2 */
+  &gl2psPDF, /* 3 */
+  &gl2psSVG, /* 4 */
+  &gl2psPGF  /* 5 */
+};
+
+static void gl2psComputeTightBoundingBox(void *data)
+{
+  GL2PSprimitive *prim;
+  int i;
+
+  prim = *(GL2PSprimitive**)data;
+
+  for(i = 0; i < prim->numverts; i++){
+    if(prim->verts[i].xyz[0] < gl2ps->viewport[0])
+      gl2ps->viewport[0] = (GLint)prim->verts[i].xyz[0];
+    if(prim->verts[i].xyz[0] > gl2ps->viewport[2])
+      gl2ps->viewport[2] = (GLint)(prim->verts[i].xyz[0] + 0.5F);
+    if(prim->verts[i].xyz[1] < gl2ps->viewport[1])
+      gl2ps->viewport[1] = (GLint)prim->verts[i].xyz[1];
+    if(prim->verts[i].xyz[1] > gl2ps->viewport[3])
+      gl2ps->viewport[3] = (GLint)(prim->verts[i].xyz[1] + 0.5F);
+  }
+}
+
+static GLint gl2psPrintPrimitives(void)
+{
+  GL2PSbsptree *root;
+  GL2PSxyz eye = {0.0F, 0.0F, 100.0F * GL2PS_ZSCALE};
+  GLint used;
+
+  used = glRenderMode(GL_RENDER);
+
+  if(used < 0){
+    gl2psMsg(GL2PS_INFO, "OpenGL feedback buffer overflow");
+    return GL2PS_OVERFLOW;
+  }
+
+  if(used > 0)
+    gl2psParseFeedbackBuffer(used);
+
+  gl2psRescaleAndOffset();
+
+  if(gl2ps->header){
+    if(gl2psListNbr(gl2ps->primitives) &&
+       (gl2ps->options & GL2PS_TIGHT_BOUNDING_BOX)){
+      gl2ps->viewport[0] = gl2ps->viewport[1] = 100000;
+      gl2ps->viewport[2] = gl2ps->viewport[3] = -100000;
+      gl2psListAction(gl2ps->primitives, gl2psComputeTightBoundingBox);
+    }
+    (gl2psbackends[gl2ps->format]->printHeader)();
+    gl2ps->header = GL_FALSE;
+  }
+
+  if(!gl2psListNbr(gl2ps->primitives)){
+    /* empty feedback buffer and/or nothing else to print */
+    return GL2PS_NO_FEEDBACK;
+  }
+
+  switch(gl2ps->sort){
+  case GL2PS_NO_SORT :
+    gl2psListAction(gl2ps->primitives, gl2psbackends[gl2ps->format]->printPrimitive);
+    gl2psListAction(gl2ps->primitives, gl2psFreePrimitive);
+    /* reset the primitive list, waiting for the next viewport */
+    gl2psListReset(gl2ps->primitives);
+    break;
+  case GL2PS_SIMPLE_SORT :
+    gl2psListSort(gl2ps->primitives, gl2psCompareDepth);
+    if(gl2ps->options & GL2PS_OCCLUSION_CULL){
+      gl2psListActionInverse(gl2ps->primitives, gl2psAddInImageTree);
+      gl2psFreeBspImageTree(&gl2ps->imagetree);
+    }
+    gl2psListAction(gl2ps->primitives, gl2psbackends[gl2ps->format]->printPrimitive);
+    gl2psListAction(gl2ps->primitives, gl2psFreePrimitive);
+    /* reset the primitive list, waiting for the next viewport */
+    gl2psListReset(gl2ps->primitives);
+    break;
+  case GL2PS_BSP_SORT :
+    root = (GL2PSbsptree*)gl2psMalloc(sizeof(GL2PSbsptree));
+    gl2psBuildBspTree(root, gl2ps->primitives);
+    if(GL_TRUE == gl2ps->boundary) gl2psBuildPolygonBoundary(root);
+    if(gl2ps->options & GL2PS_OCCLUSION_CULL){
+      gl2psTraverseBspTree(root, eye, -GL2PS_EPSILON, gl2psLess,
+                           gl2psAddInImageTree, 1);
+      gl2psFreeBspImageTree(&gl2ps->imagetree);
+    }
+    gl2psTraverseBspTree(root, eye, GL2PS_EPSILON, gl2psGreater,
+                         gl2psbackends[gl2ps->format]->printPrimitive, 0);
+    gl2psFreeBspTree(&root);
+    /* reallocate the primitive list (it's been deleted by
+       gl2psBuildBspTree) in case there is another viewport */
+    gl2ps->primitives = gl2psListCreate(500, 500, sizeof(GL2PSprimitive*));
+    break;
+  }
+  gl2psbackends[gl2ps->format]->printFinalPrimitive();
+
+  return GL2PS_SUCCESS;
+}
+
+/*********************************************************************
+ *
+ * Public routines
+ *
+ *********************************************************************/
+
+GL2PSDLL_API GLint gl2psBeginPage(const char *title, const char *producer,
+                                  GLint viewport[4], GLint format, GLint sort,
+                                  GLint options, GLint colormode,
+                                  GLint colorsize, GL2PSrgba *colormap,
+                                  GLint nr, GLint ng, GLint nb, GLint buffersize,
+                                  FILE *stream, const char *filename)
+{
+  GLint index;
+  int i;
+
+  if(gl2ps){
+    gl2psMsg(GL2PS_ERROR, "gl2psBeginPage called in wrong program state");
+    return GL2PS_ERROR;
+  }
+
+  gl2ps = (GL2PScontext*)gl2psMalloc(sizeof(GL2PScontext));
+
+  if(format >= 0 && format < (GLint)(sizeof(gl2psbackends) / sizeof(gl2psbackends[0]))){
+    gl2ps->format = format;
+  }
+  else {
+    gl2psMsg(GL2PS_ERROR, "Unknown output format: %d", format);
+    gl2psFree(gl2ps);
+    gl2ps = NULL;
+    return GL2PS_ERROR;
+  }
+
+  switch(sort){
+  case GL2PS_NO_SORT :
+  case GL2PS_SIMPLE_SORT :
+  case GL2PS_BSP_SORT :
+    gl2ps->sort = sort;
+    break;
+  default :
+    gl2psMsg(GL2PS_ERROR, "Unknown sorting algorithm: %d", sort);
+    gl2psFree(gl2ps);
+    gl2ps = NULL;
+    return GL2PS_ERROR;
+  }
+
+  if(stream){
+    gl2ps->stream = stream;
+  }
+  else{
+    gl2psMsg(GL2PS_ERROR, "Bad file pointer");
+    gl2psFree(gl2ps);
+    gl2ps = NULL;
+    return GL2PS_ERROR;
+  }
+
+  gl2ps->header = GL_TRUE;
+  gl2ps->maxbestroot = 10;
+  gl2ps->options = options;
+  gl2ps->compress = NULL;
+  gl2ps->imagemap_head = NULL;
+  gl2ps->imagemap_tail = NULL;
+
+  if(gl2ps->options & GL2PS_USE_CURRENT_VIEWPORT){
+    glGetIntegerv(GL_VIEWPORT, gl2ps->viewport);
+  }
+  else{
+    for(i = 0; i < 4; i++){
+      gl2ps->viewport[i] = viewport[i];
+    }
+  }
+
+  if(!gl2ps->viewport[2] || !gl2ps->viewport[3]){
+    gl2psMsg(GL2PS_ERROR, "Incorrect viewport (x=%d, y=%d, width=%d, height=%d)",
+             gl2ps->viewport[0], gl2ps->viewport[1],
+             gl2ps->viewport[2], gl2ps->viewport[3]);
+    gl2psFree(gl2ps);
+    gl2ps = NULL;
+    return GL2PS_ERROR;
+  }
+
+  gl2ps->threshold[0] = nr ? 1.0F / (GLfloat)nr : 0.064F;
+  gl2ps->threshold[1] = ng ? 1.0F / (GLfloat)ng : 0.034F;
+  gl2ps->threshold[2] = nb ? 1.0F / (GLfloat)nb : 0.100F;
+  gl2ps->colormode = colormode;
+  gl2ps->buffersize = buffersize > 0 ? buffersize : 2048 * 2048;
+  for(i = 0; i < 3; i++){
+    gl2ps->lastvertex.xyz[i] = -1.0F;
+  }
+  for(i = 0; i < 4; i++){
+    gl2ps->lastvertex.rgba[i] = -1.0F;
+    gl2ps->lastrgba[i] = -1.0F;
+  }
+  gl2ps->lastlinewidth = -1.0F;
+  gl2ps->lastpattern = 0;
+  gl2ps->lastfactor = 0;
+  gl2ps->imagetree = NULL;
+  gl2ps->primitivetoadd = NULL;
+  gl2ps->zerosurfacearea = GL_FALSE;
+  gl2ps->pdfprimlist = NULL;
+  gl2ps->pdfgrouplist = NULL;
+  gl2ps->xreflist = NULL;
+
+  /* get default blending mode from current OpenGL state (enabled by
+     default for SVG) */
+  gl2ps->blending = (gl2ps->format == GL2PS_SVG) ? GL_TRUE : glIsEnabled(GL_BLEND);
+  glGetIntegerv(GL_BLEND_SRC, &gl2ps->blendfunc[0]);
+  glGetIntegerv(GL_BLEND_DST, &gl2ps->blendfunc[1]);
+
+  if(gl2ps->colormode == GL_RGBA){
+    gl2ps->colorsize = 0;
+    gl2ps->colormap = NULL;
+    glGetFloatv(GL_COLOR_CLEAR_VALUE, gl2ps->bgcolor);
+  }
+  else if(gl2ps->colormode == GL_COLOR_INDEX){
+    if(!colorsize || !colormap){
+      gl2psMsg(GL2PS_ERROR, "Missing colormap for GL_COLOR_INDEX rendering");
+      gl2psFree(gl2ps);
+      gl2ps = NULL;
+      return GL2PS_ERROR;
+    }
+    gl2ps->colorsize = colorsize;
+    gl2ps->colormap = (GL2PSrgba*)gl2psMalloc(gl2ps->colorsize * sizeof(GL2PSrgba));
+    memcpy(gl2ps->colormap, colormap, gl2ps->colorsize * sizeof(GL2PSrgba));
+    glGetIntegerv(GL_INDEX_CLEAR_VALUE, &index);
+    gl2ps->bgcolor[0] = gl2ps->colormap[index][0];
+    gl2ps->bgcolor[1] = gl2ps->colormap[index][1];
+    gl2ps->bgcolor[2] = gl2ps->colormap[index][2];
+    gl2ps->bgcolor[3] = 1.0F;
+  }
+  else{
+    gl2psMsg(GL2PS_ERROR, "Unknown color mode in gl2psBeginPage");
+    gl2psFree(gl2ps);
+    gl2ps = NULL;
+    return GL2PS_ERROR;
+  }
+
+  if(!title){
+    gl2ps->title = (char*)gl2psMalloc(sizeof(char));
+    gl2ps->title[0] = '\0';
+  }
+  else{
+    gl2ps->title = (char*)gl2psMalloc((strlen(title)+1)*sizeof(char));
+    strcpy(gl2ps->title, title);
+  }
+
+  if(!producer){
+    gl2ps->producer = (char*)gl2psMalloc(sizeof(char));
+    gl2ps->producer[0] = '\0';
+  }
+  else{
+    gl2ps->producer = (char*)gl2psMalloc((strlen(producer)+1)*sizeof(char));
+    strcpy(gl2ps->producer, producer);
+  }
+
+  if(!filename){
+    gl2ps->filename = (char*)gl2psMalloc(sizeof(char));
+    gl2ps->filename[0] = '\0';
+  }
+  else{
+    gl2ps->filename = (char*)gl2psMalloc((strlen(filename)+1)*sizeof(char));
+    strcpy(gl2ps->filename, filename);
+  }
+
+  gl2ps->primitives = gl2psListCreate(500, 500, sizeof(GL2PSprimitive*));
+  gl2ps->auxprimitives = gl2psListCreate(100, 100, sizeof(GL2PSprimitive*));
+  gl2ps->feedback = (GLfloat*)gl2psMalloc(gl2ps->buffersize * sizeof(GLfloat));
+  glFeedbackBuffer(gl2ps->buffersize, GL_3D_COLOR, gl2ps->feedback);
+  glRenderMode(GL_FEEDBACK);
+
+  return GL2PS_SUCCESS;
+}
+
+GL2PSDLL_API GLint gl2psEndPage(void)
+{
+  GLint res;
+
+  if(!gl2ps) return GL2PS_UNINITIALIZED;
+
+  res = gl2psPrintPrimitives();
+
+  if(res != GL2PS_OVERFLOW)
+    (gl2psbackends[gl2ps->format]->printFooter)();
+
+  fflush(gl2ps->stream);
+
+  gl2psListDelete(gl2ps->primitives);
+  gl2psListDelete(gl2ps->auxprimitives);
+  gl2psFreeImagemap(gl2ps->imagemap_head);
+  gl2psFree(gl2ps->colormap);
+  gl2psFree(gl2ps->title);
+  gl2psFree(gl2ps->producer);
+  gl2psFree(gl2ps->filename);
+  gl2psFree(gl2ps->feedback);
+  gl2psFree(gl2ps);
+  gl2ps = NULL;
+
+  return res;
+}
+
+GL2PSDLL_API GLint gl2psBeginViewport(GLint viewport[4])
+{
+  if(!gl2ps) return GL2PS_UNINITIALIZED;
+
+  (gl2psbackends[gl2ps->format]->beginViewport)(viewport);
+
+  return GL2PS_SUCCESS;
+}
+
+GL2PSDLL_API GLint gl2psEndViewport(void)
+{
+  GLint res;
+
+  if(!gl2ps) return GL2PS_UNINITIALIZED;
+
+  res = (gl2psbackends[gl2ps->format]->endViewport)();
+
+  /* reset last used colors, line widths */
+  gl2ps->lastlinewidth = -1.0F;
+
+  return res;
+}
+
+GL2PSDLL_API GLint gl2psTextOpt(const char *str, const char *fontname,
+                                GLshort fontsize, GLint alignment, GLfloat angle)
+{
+  return gl2psAddText(GL2PS_TEXT, str, fontname, fontsize, alignment, angle);
+}
+
+GL2PSDLL_API GLint gl2psText(const char *str, const char *fontname, GLshort fontsize)
+{
+  return gl2psAddText(GL2PS_TEXT, str, fontname, fontsize, GL2PS_TEXT_BL, 0.0F);
+}
+
+GL2PSDLL_API GLint gl2psSpecial(GLint format, const char *str)
+{
+  return gl2psAddText(GL2PS_SPECIAL, str, "", 0, format, 0.0F);
+}
+
+GL2PSDLL_API GLint gl2psDrawPixels(GLsizei width, GLsizei height,
+                                   GLint xorig, GLint yorig,
+                                   GLenum format, GLenum type,
+                                   const void *pixels)
+{
+  int size, i;
+  const GLfloat *piv;
+  GLfloat pos[4], zoom_x, zoom_y;
+  GL2PSprimitive *prim;
+  GLboolean valid;
+
+  if(!gl2ps || !pixels) return GL2PS_UNINITIALIZED;
+
+  if((width <= 0) || (height <= 0)) return GL2PS_ERROR;
+
+  if(gl2ps->options & GL2PS_NO_PIXMAP) return GL2PS_SUCCESS;
+
+  if((format != GL_RGB && format != GL_RGBA) || type != GL_FLOAT){
+    gl2psMsg(GL2PS_ERROR, "gl2psDrawPixels only implemented for "
+             "GL_RGB/GL_RGBA, GL_FLOAT pixels");
+    return GL2PS_ERROR;
+  }
+
+  glGetBooleanv(GL_CURRENT_RASTER_POSITION_VALID, &valid);
+  if(GL_FALSE == valid) return GL2PS_SUCCESS; /* the primitive is culled */
+
+  glGetFloatv(GL_CURRENT_RASTER_POSITION, pos);
+  glGetFloatv(GL_ZOOM_X, &zoom_x);
+  glGetFloatv(GL_ZOOM_Y, &zoom_y);
+
+  prim = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
+  prim->type = GL2PS_PIXMAP;
+  prim->boundary = 0;
+  prim->numverts = 1;
+  prim->verts = (GL2PSvertex*)gl2psMalloc(sizeof(GL2PSvertex));
+  prim->verts[0].xyz[0] = pos[0] + xorig;
+  prim->verts[0].xyz[1] = pos[1] + yorig;
+  prim->verts[0].xyz[2] = pos[2];
+  prim->culled = 0;
+  prim->offset = 0;
+  prim->pattern = 0;
+  prim->factor = 0;
+  prim->width = 1;
+  glGetFloatv(GL_CURRENT_RASTER_COLOR, prim->verts[0].rgba);
+  prim->data.image = (GL2PSimage*)gl2psMalloc(sizeof(GL2PSimage));
+  prim->data.image->width = width;
+  prim->data.image->height = height;
+  prim->data.image->zoom_x = zoom_x;
+  prim->data.image->zoom_y = zoom_y;
+  prim->data.image->format = format;
+  prim->data.image->type = type;
+
+  switch(format){
+  case GL_RGBA:
+    if(gl2ps->options & GL2PS_NO_BLENDING || !gl2ps->blending){
+      /* special case: blending turned off */
+      prim->data.image->format = GL_RGB;
+      size = height * width * 3;
+      prim->data.image->pixels = (GLfloat*)gl2psMalloc(size * sizeof(GLfloat));
+      piv = (const GLfloat*)pixels;
+      for(i = 0; i < size; ++i, ++piv){
+        prim->data.image->pixels[i] = *piv;
+        if(!((i + 1) % 3))
+          ++piv;
+      }
+    }
+    else{
+      size = height * width * 4;
+      prim->data.image->pixels = (GLfloat*)gl2psMalloc(size * sizeof(GLfloat));
+      memcpy(prim->data.image->pixels, pixels, size * sizeof(GLfloat));
+    }
+    break;
+  case GL_RGB:
+  default:
+    size = height * width * 3;
+    prim->data.image->pixels = (GLfloat*)gl2psMalloc(size * sizeof(GLfloat));
+    memcpy(prim->data.image->pixels, pixels, size * sizeof(GLfloat));
+    break;
+  }
+
+  gl2psListAdd(gl2ps->auxprimitives, &prim);
+  glPassThrough(GL2PS_DRAW_PIXELS_TOKEN);
+
+  return GL2PS_SUCCESS;
+}
+
+GL2PSDLL_API GLint gl2psDrawImageMap(GLsizei width, GLsizei height,
+                                     const GLfloat position[3],
+                                     const unsigned char *imagemap){
+  int size, i;
+  int sizeoffloat = sizeof(GLfloat);
+
+  if(!gl2ps || !imagemap) return GL2PS_UNINITIALIZED;
+
+  if((width <= 0) || (height <= 0)) return GL2PS_ERROR;
+
+  size = height + height * ((width - 1) / 8);
+  glPassThrough(GL2PS_IMAGEMAP_TOKEN);
+  glBegin(GL_POINTS);
+  glVertex3f(position[0], position[1],position[2]);
+  glEnd();
+  glPassThrough((GLfloat)width);
+  glPassThrough((GLfloat)height);
+  for(i = 0; i < size; i += sizeoffloat){
+    const float *value = (const float*)imagemap;
+    glPassThrough(*value);
+    imagemap += sizeoffloat;
+  }
+  return GL2PS_SUCCESS;
+}
+
+GL2PSDLL_API GLint gl2psEnable(GLint mode)
+{
+  GLint tmp;
+
+  if(!gl2ps) return GL2PS_UNINITIALIZED;
+
+  switch(mode){
+  case GL2PS_POLYGON_OFFSET_FILL :
+    glPassThrough(GL2PS_BEGIN_OFFSET_TOKEN);
+    glGetFloatv(GL_POLYGON_OFFSET_FACTOR, &gl2ps->offset[0]);
+    glGetFloatv(GL_POLYGON_OFFSET_UNITS, &gl2ps->offset[1]);
+    break;
+  case GL2PS_POLYGON_BOUNDARY :
+    glPassThrough(GL2PS_BEGIN_BOUNDARY_TOKEN);
+    break;
+  case GL2PS_LINE_STIPPLE :
+    glPassThrough(GL2PS_BEGIN_STIPPLE_TOKEN);
+    glGetIntegerv(GL_LINE_STIPPLE_PATTERN, &tmp);
+    glPassThrough((GLfloat)tmp);
+    glGetIntegerv(GL_LINE_STIPPLE_REPEAT, &tmp);
+    glPassThrough((GLfloat)tmp);
+    break;
+  case GL2PS_BLEND :
+    glPassThrough(GL2PS_BEGIN_BLEND_TOKEN);
+    break;
+  default :
+    gl2psMsg(GL2PS_WARNING, "Unknown mode in gl2psEnable: %d", mode);
+    return GL2PS_WARNING;
+  }
+
+  return GL2PS_SUCCESS;
+}
+
+GL2PSDLL_API GLint gl2psDisable(GLint mode)
+{
+  if(!gl2ps) return GL2PS_UNINITIALIZED;
+
+  switch(mode){
+  case GL2PS_POLYGON_OFFSET_FILL :
+    glPassThrough(GL2PS_END_OFFSET_TOKEN);
+    break;
+  case GL2PS_POLYGON_BOUNDARY :
+    glPassThrough(GL2PS_END_BOUNDARY_TOKEN);
+    break;
+  case GL2PS_LINE_STIPPLE :
+    glPassThrough(GL2PS_END_STIPPLE_TOKEN);
+    break;
+  case GL2PS_BLEND :
+    glPassThrough(GL2PS_END_BLEND_TOKEN);
+    break;
+  default :
+    gl2psMsg(GL2PS_WARNING, "Unknown mode in gl2psDisable: %d", mode);
+    return GL2PS_WARNING;
+  }
+
+  return GL2PS_SUCCESS;
+}
+
+GL2PSDLL_API GLint gl2psPointSize(GLfloat value)
+{
+  if(!gl2ps) return GL2PS_UNINITIALIZED;
+
+  glPassThrough(GL2PS_POINT_SIZE_TOKEN);
+  glPassThrough(value);
+
+  return GL2PS_SUCCESS;
+}
+
+GL2PSDLL_API GLint gl2psLineWidth(GLfloat value)
+{
+  if(!gl2ps) return GL2PS_UNINITIALIZED;
+
+  glPassThrough(GL2PS_LINE_WIDTH_TOKEN);
+  glPassThrough(value);
+
+  return GL2PS_SUCCESS;
+}
+
+GL2PSDLL_API GLint gl2psBlendFunc(GLenum sfactor, GLenum dfactor)
+{
+  if(!gl2ps) return GL2PS_UNINITIALIZED;
+
+  if(GL_FALSE == gl2psSupportedBlendMode(sfactor, dfactor))
+    return GL2PS_WARNING;
+
+  glPassThrough(GL2PS_SRC_BLEND_TOKEN);
+  glPassThrough((GLfloat)sfactor);
+  glPassThrough(GL2PS_DST_BLEND_TOKEN);
+  glPassThrough((GLfloat)dfactor);
+
+  return GL2PS_SUCCESS;
+}
+
+GL2PSDLL_API GLint gl2psSetOptions(GLint options)
+{
+  if(!gl2ps) return GL2PS_UNINITIALIZED;
+
+  gl2ps->options = options;
+
+  return GL2PS_SUCCESS;
+}
+
+GL2PSDLL_API GLint gl2psGetOptions(GLint *options)
+{
+  if(!gl2ps) {
+    *options = 0;
+    return GL2PS_UNINITIALIZED;
+  }
+
+  *options = gl2ps->options;
+
+  return GL2PS_SUCCESS;
+}
+
+GL2PSDLL_API const char *gl2psGetFileExtension(GLint format)
+{
+  if(format >= 0 && format < (GLint)(sizeof(gl2psbackends) / sizeof(gl2psbackends[0])))
+    return gl2psbackends[format]->file_extension;
+  else
+    return "Unknown format";
+}
+
+GL2PSDLL_API const char *gl2psGetFormatDescription(GLint format)
+{
+  if(format >= 0 && format < (GLint)(sizeof(gl2psbackends) / sizeof(gl2psbackends[0])))
+    return gl2psbackends[format]->description;
+  else
+    return "Unknown format";
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/gl2ps.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,200 @@
+/*
+ * GL2PS, an OpenGL to PostScript Printing Library
+ * Copyright (C) 1999-2011 C. Geuzaine
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of either:
+ *
+ * a) the GNU Library General Public License as published by the Free
+ * Software Foundation, either version 2 of the License, or (at your
+ * option) any later version; or
+ *
+ * b) the GL2PS License as published by Christophe Geuzaine, either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program 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 either
+ * the GNU Library General Public License or the GL2PS License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library in the file named "COPYING.LGPL";
+ * if not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+ * Cambridge, MA 02139, USA.
+ *
+ * You should have received a copy of the GL2PS License with this
+ * library in the file named "COPYING.GL2PS"; if not, I will be glad
+ * to provide one.
+ *
+ * For the latest info about gl2ps and a full list of contributors,
+ * see http://www.geuz.org/gl2ps/.
+ *
+ * Please report all bugs and problems to <gl2ps@geuz.org>.
+ */
+
+#ifndef __GL2PS_H__
+#define __GL2PS_H__
+
+#include <stdio.h>
+#include <stdlib.h>
+
+/* Define GL2PSDLL at compile time to build a Windows DLL */
+
+#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
+#  if defined(_MSC_VER)
+#    pragma warning(disable:4115)
+#    pragma warning(disable:4996)
+#  endif
+#  define WIN32_LEAN_AND_MEAN
+#  include <windows.h>
+#  if defined(GL2PSDLL)
+#    if defined(GL2PSDLL_EXPORTS)
+#      define GL2PSDLL_API __declspec(dllexport)
+#    else
+#      define GL2PSDLL_API __declspec(dllimport)
+#    endif
+#  else
+#    define GL2PSDLL_API
+#  endif
+#else
+#  define GL2PSDLL_API
+#endif
+
+#if defined(__APPLE__) || defined(HAVE_OPENGL_GL_H)
+#  include <OpenGL/gl.h>
+#else
+#  include <GL/gl.h>
+#endif
+
+/* Support for compressed PostScript/PDF/SVG and for embedded PNG
+   images in SVG */
+
+#if defined(HAVE_ZLIB) || defined(HAVE_LIBZ)
+#  define GL2PS_HAVE_ZLIB
+#  if defined(HAVE_LIBPNG) || defined(HAVE_PNG)
+#    define GL2PS_HAVE_LIBPNG
+#  endif
+#endif
+
+/* Version number */
+
+#define GL2PS_MAJOR_VERSION 1
+#define GL2PS_MINOR_VERSION 3
+#define GL2PS_PATCH_VERSION 6
+#define GL2PS_EXTRA_VERSION ""
+
+#define GL2PS_VERSION (GL2PS_MAJOR_VERSION + \
+                       0.01 * GL2PS_MINOR_VERSION + \
+                       0.0001 * GL2PS_PATCH_VERSION)
+
+#define GL2PS_COPYRIGHT "(C) 1999-2011 C. Geuzaine"
+
+/* Output file formats (the values and the ordering are important!) */
+
+#define GL2PS_PS  0
+#define GL2PS_EPS 1
+#define GL2PS_TEX 2
+#define GL2PS_PDF 3
+#define GL2PS_SVG 4
+#define GL2PS_PGF 5
+
+/* Sorting algorithms */
+
+#define GL2PS_NO_SORT     1
+#define GL2PS_SIMPLE_SORT 2
+#define GL2PS_BSP_SORT    3
+
+/* Message levels and error codes */
+
+#define GL2PS_SUCCESS       0
+#define GL2PS_INFO          1
+#define GL2PS_WARNING       2
+#define GL2PS_ERROR         3
+#define GL2PS_NO_FEEDBACK   4
+#define GL2PS_OVERFLOW      5
+#define GL2PS_UNINITIALIZED 6
+
+/* Options for gl2psBeginPage */
+
+#define GL2PS_NONE                 0
+#define GL2PS_DRAW_BACKGROUND      (1<<0)
+#define GL2PS_SIMPLE_LINE_OFFSET   (1<<1)
+#define GL2PS_SILENT               (1<<2)
+#define GL2PS_BEST_ROOT            (1<<3)
+#define GL2PS_OCCLUSION_CULL       (1<<4)
+#define GL2PS_NO_TEXT              (1<<5)
+#define GL2PS_LANDSCAPE            (1<<6)
+#define GL2PS_NO_PS3_SHADING       (1<<7)
+#define GL2PS_NO_PIXMAP            (1<<8)
+#define GL2PS_USE_CURRENT_VIEWPORT (1<<9)
+#define GL2PS_COMPRESS             (1<<10)
+#define GL2PS_NO_BLENDING          (1<<11)
+#define GL2PS_TIGHT_BOUNDING_BOX   (1<<12)
+
+/* Arguments for gl2psEnable/gl2psDisable */
+
+#define GL2PS_POLYGON_OFFSET_FILL 1
+#define GL2PS_POLYGON_BOUNDARY    2
+#define GL2PS_LINE_STIPPLE        3
+#define GL2PS_BLEND               4
+
+/* Text alignment (o=raster position; default mode is BL):
+   +---+ +---+ +---+ +---+ +---+ +---+ +-o-+ o---+ +---o
+   | o | o   | |   o |   | |   | |   | |   | |   | |   |
+   +---+ +---+ +---+ +-o-+ o---+ +---o +---+ +---+ +---+
+    C     CL    CR    B     BL    BR    T     TL    TR */
+
+#define GL2PS_TEXT_C  1
+#define GL2PS_TEXT_CL 2
+#define GL2PS_TEXT_CR 3
+#define GL2PS_TEXT_B  4
+#define GL2PS_TEXT_BL 5
+#define GL2PS_TEXT_BR 6
+#define GL2PS_TEXT_T  7
+#define GL2PS_TEXT_TL 8
+#define GL2PS_TEXT_TR 9
+
+typedef GLfloat GL2PSrgba[4];
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+GL2PSDLL_API GLint gl2psBeginPage(const char *title, const char *producer,
+                                  GLint viewport[4], GLint format, GLint sort,
+                                  GLint options, GLint colormode,
+                                  GLint colorsize, GL2PSrgba *colormap,
+                                  GLint nr, GLint ng, GLint nb, GLint buffersize,
+                                  FILE *stream, const char *filename);
+GL2PSDLL_API GLint gl2psEndPage(void);
+GL2PSDLL_API GLint gl2psSetOptions(GLint options);
+GL2PSDLL_API GLint gl2psGetOptions(GLint *options);
+GL2PSDLL_API GLint gl2psBeginViewport(GLint viewport[4]);
+GL2PSDLL_API GLint gl2psEndViewport(void);
+GL2PSDLL_API GLint gl2psText(const char *str, const char *fontname,
+                             GLshort fontsize);
+GL2PSDLL_API GLint gl2psTextOpt(const char *str, const char *fontname,
+                                GLshort fontsize, GLint align, GLfloat angle);
+GL2PSDLL_API GLint gl2psSpecial(GLint format, const char *str);
+GL2PSDLL_API GLint gl2psDrawPixels(GLsizei width, GLsizei height,
+                                   GLint xorig, GLint yorig,
+                                   GLenum format, GLenum type, const void *pixels);
+GL2PSDLL_API GLint gl2psEnable(GLint mode);
+GL2PSDLL_API GLint gl2psDisable(GLint mode);
+GL2PSDLL_API GLint gl2psPointSize(GLfloat value);
+GL2PSDLL_API GLint gl2psLineWidth(GLfloat value);
+GL2PSDLL_API GLint gl2psBlendFunc(GLenum sfactor, GLenum dfactor);
+
+/* undocumented */
+GL2PSDLL_API GLint gl2psDrawImageMap(GLsizei width, GLsizei height,
+                                     const GLfloat position[3],
+                                     const unsigned char *imagemap);
+GL2PSDLL_API const char *gl2psGetFileExtension(GLint format);
+GL2PSDLL_API const char *gl2psGetFormatDescription(GLint format);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __GL2PS_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/gripes.cc	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,238 @@
+/*
+
+Copyright (C) 1993-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "defun.h"
+#include "error.h"
+#include "gripes.h"
+#include "oct-obj.h"
+#include "utils.h"
+
+void
+gripe_not_supported (const char *fcn)
+{
+  error ("%s: not supported on this system", fcn);
+}
+
+void
+gripe_not_implemented (const char *fcn)
+{
+  error ("%s: not implemented", fcn);
+}
+
+void
+gripe_string_invalid (void)
+{
+  error ("std::string constant used in invalid context");
+}
+
+void
+gripe_range_invalid (void)
+{
+  error ("range constant used in invalid context");
+}
+
+void
+gripe_nonconformant (void)
+{
+  error ("nonconformant matrices");
+}
+
+void
+gripe_nonconformant (octave_idx_type r1, octave_idx_type c1, octave_idx_type r2, octave_idx_type c2)
+{
+  error ("nonconformant matrices (op1 is %dx%d, op2 is %dx%d)",
+         r1, c1, r2, c2);
+}
+
+void
+gripe_empty_arg (const char *name, bool is_error)
+{
+  if (is_error)
+    error ("%s: empty matrix is invalid as an argument", name);
+  else
+    warning ("%s: argument is empty matrix", name);
+}
+
+void
+gripe_square_matrix_required (const char *name)
+{
+  error ("%s: argument must be a square matrix", name);
+}
+
+void
+gripe_user_supplied_eval (const char *name)
+{
+  error ("%s: evaluation of user-supplied function failed", name);
+}
+
+void
+gripe_user_returned_invalid (const char *name)
+{
+  error ("%s: user-supplied function returned invalid value", name);
+}
+
+void
+gripe_invalid_conversion (const std::string& from, const std::string& to)
+{
+  error ("invalid conversion from %s to %s", from.c_str (), to.c_str ());
+}
+
+void
+gripe_invalid_value_specified (const char *name)
+{
+  warning ("invalid value specified for `%s'", name);
+}
+
+void
+gripe_2_or_3_dim_plot (void)
+{
+  error ("plot: can only plot in 2 or 3 dimensions");
+}
+
+void
+gripe_unrecognized_float_fmt (void)
+{
+  error ("unrecognized floating point format requested");
+}
+
+void
+gripe_unrecognized_data_fmt (const char *warn_for)
+{
+  error ("%s: unrecognized data format requested", warn_for);
+}
+
+void
+gripe_data_conversion (const char *from, const char *to)
+{
+  error ("unable to convert from %s to %s format", from, to);
+}
+
+void
+gripe_wrong_type_arg (const char *name, const char *s, bool is_error)
+{
+  if (is_error)
+    error ("%s: wrong type argument `%s'", name, s);
+  else
+    warning ("%s: wrong type argument `%s'", name, s);
+}
+
+void
+gripe_wrong_type_arg (const char *name, const std::string& s, bool is_error)
+{
+  gripe_wrong_type_arg (name, s.c_str (), is_error);
+}
+
+void
+gripe_wrong_type_arg (const char *name, const octave_value& tc,
+                      bool is_error)
+{
+  std::string type = tc.type_name ();
+
+  gripe_wrong_type_arg (name, type, is_error);
+}
+
+void
+gripe_wrong_type_arg (const std::string& name, const octave_value& tc,
+                      bool is_error)
+{
+  gripe_wrong_type_arg (name.c_str (), tc, is_error);
+}
+
+void
+gripe_wrong_type_arg_for_unary_op (const octave_value& op)
+{
+  std::string type = op.type_name ();
+  error ("invalid operand `%s' for unary operator", type.c_str ());
+}
+
+void
+gripe_wrong_type_arg_for_binary_op (const octave_value& op)
+{
+  std::string type = op.type_name ();
+  error ("invalid operand `%s' for binary operator", type.c_str ());
+}
+
+void
+gripe_implicit_conversion (const char *id, const char *from, const char *to)
+{
+  warning_with_id (id, "implicit conversion from %s to %s", from, to);
+}
+
+void
+gripe_implicit_conversion (const std::string& id,
+                           const std::string& from, const std::string& to)
+{
+  warning_with_id (id.c_str (),
+                   "implicit conversion from %s to %s",
+                   from.c_str (), to.c_str ());
+}
+
+void
+gripe_divide_by_zero (void)
+{
+  warning_with_id ("Octave:divide-by-zero", "division by zero");
+}
+
+void
+gripe_logical_conversion (void)
+{
+  warning_with_id ("Octave:logical-conversion",
+                   "value not equal to 1 or 0 converted to logical 1");
+}
+
+void
+gripe_library_execution_error (void)
+{
+  octave_exception_state = octave_no_exception;
+
+  if (! error_state)
+    error ("caught execution error in library function");
+}
+
+void
+gripe_invalid_inquiry_subscript (void)
+{
+  error ("invalid dimension inquiry of a non-existent value");
+}
+
+void
+gripe_indexed_cs_list (void)
+{
+  error ("a cs-list cannot be further indexed");
+}
+
+void
+gripe_nonbraced_cs_list_assignment (void)
+{
+  error ("invalid assignment to cs-list outside multiple assignment");
+}
+
+void
+gripe_warn_complex_cmp (void)
+{
+  warning_with_id ("Octave:matlab-incompatible",
+                   "potential Matlab compatibility problem: comparing complex numbers");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/gripes.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,130 @@
+/*
+
+Copyright (C) 1993-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if !defined (octave_gripes_h)
+#define octave_gripes_h 1
+
+#include <string>
+
+#include "lo-array-gripes.h"
+
+class octave_value;
+
+extern OCTINTERP_API void
+gripe_not_supported (const char *);
+
+extern OCTINTERP_API void
+gripe_not_implemented (const char *);
+
+extern OCTINTERP_API void
+gripe_string_invalid (void);
+
+extern OCTINTERP_API void
+gripe_range_invalid (void);
+
+extern OCTINTERP_API void
+gripe_nonconformant (void);
+
+extern OCTINTERP_API void
+gripe_nonconformant (octave_idx_type r1, octave_idx_type c1, octave_idx_type r2, octave_idx_type c2);
+
+extern OCTINTERP_API void
+gripe_empty_arg (const char *name, bool is_error);
+
+extern OCTINTERP_API void
+gripe_square_matrix_required (const char *name);
+
+extern OCTINTERP_API void
+gripe_user_supplied_eval (const char *name);
+
+extern OCTINTERP_API void
+gripe_user_returned_invalid (const char *name);
+
+extern OCTINTERP_API void
+gripe_invalid_conversion (const std::string& from, const std::string& to);
+
+extern OCTINTERP_API void
+gripe_invalid_value_specified (const char *name);
+
+extern OCTINTERP_API void
+gripe_2_or_3_dim_plot (void);
+
+extern OCTINTERP_API void
+gripe_unrecognized_float_fmt (void);
+
+extern OCTINTERP_API void
+gripe_unrecognized_data_fmt (const char *warn_for);
+
+extern OCTINTERP_API void
+gripe_data_conversion (const char *from, const char *to);
+
+extern OCTINTERP_API void
+gripe_wrong_type_arg (const char *name, const char *s,
+                      bool is_error = true);
+
+extern OCTINTERP_API void
+gripe_wrong_type_arg (const char *name, const std::string& s,
+                      bool is_error = true);
+
+extern OCTINTERP_API void
+gripe_wrong_type_arg (const char *name, const octave_value& tc,
+                      bool is_error = true);
+
+extern OCTINTERP_API void
+gripe_wrong_type_arg (const std::string& name, const octave_value& tc,
+                      bool is_error = true);
+
+extern OCTINTERP_API void
+gripe_wrong_type_arg_for_unary_op (const octave_value& op);
+
+extern OCTINTERP_API void
+gripe_wrong_type_arg_for_binary_op (const octave_value& op);
+
+extern OCTINTERP_API void
+gripe_implicit_conversion (const char *id, const char *from, const char *to);
+
+extern OCTINTERP_API void
+gripe_implicit_conversion (const std::string& id, const std::string& from,
+                           const std::string& to);
+
+extern OCTINTERP_API void
+gripe_divide_by_zero (void);
+
+extern OCTINTERP_API void
+gripe_logical_conversion (void);
+
+extern OCTINTERP_API void
+gripe_library_execution_error (void);
+
+extern OCTINTERP_API void
+gripe_invalid_inquiry_subscript (void);
+
+extern OCTINTERP_API void
+gripe_indexed_cs_list (void);
+
+extern OCTINTERP_API void
+gripe_nonbraced_cs_list_assignment (void);
+
+extern OCTINTERP_API void
+gripe_warn_complex_cmp (void);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/jit-ir.cc	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,649 @@
+/*
+
+Copyright (C) 2012 Max Brister <max@2bass.com>
+
+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/>.
+
+*/
+
+// defines required by llvm
+#define __STDC_LIMIT_MACROS
+#define __STDC_CONSTANT_MACROS
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_LLVM
+
+#include "jit-ir.h"
+
+#include <llvm/BasicBlock.h>
+#include <llvm/Instructions.h>
+
+#include "error.h"
+#include "pt-jit.h"
+
+// -------------------- jit_use --------------------
+jit_block *
+jit_use::user_parent (void) const
+{
+  return muser->parent ();
+}
+
+// -------------------- jit_value --------------------
+jit_value::~jit_value (void)
+{}
+
+jit_block *
+jit_value::first_use_block (void)
+{
+  jit_use *use = first_use ();
+  while (use)
+    {
+      if (! isa<jit_error_check> (use->user ()))
+        return use->user_parent ();
+
+      use = use->next ();
+    }
+
+  return 0;
+}
+
+void
+jit_value::replace_with (jit_value *value)
+{
+  while (first_use ())
+    {
+      jit_instruction *user = first_use ()->user ();
+      size_t idx = first_use ()->index ();
+      user->stash_argument (idx, value);
+    }
+}
+
+#define JIT_METH(clname)                                \
+  void                                                  \
+  jit_ ## clname::accept (jit_ir_walker& walker)        \
+  {                                                     \
+    walker.visit (*this);                               \
+  }
+
+JIT_VISIT_IR_NOTEMPLATE
+#undef JIT_METH
+
+std::ostream&
+operator<< (std::ostream& os, const jit_value& value)
+{
+  return value.short_print (os);
+}
+
+std::ostream&
+jit_print (std::ostream& os, jit_value *avalue)
+{
+  if (avalue)
+    return avalue->print (os);
+  return os << "NULL";
+}
+
+// -------------------- jit_instruction --------------------
+void
+jit_instruction::remove (void)
+{
+  if (mparent)
+    mparent->remove (mlocation);
+  resize_arguments (0);
+}
+
+llvm::BasicBlock *
+jit_instruction::parent_llvm (void) const
+{
+  return mparent->to_llvm ();
+}
+
+std::ostream&
+jit_instruction::short_print (std::ostream& os) const
+{
+  if (type ())
+    jit_print (os, type ()) << ": ";
+  return os << "#" << mid;
+}
+
+void
+jit_instruction::do_construct_ssa (size_t start, size_t end)
+{
+  for (size_t i = start; i < end; ++i)
+    {
+      jit_value *arg = argument (i);
+      jit_variable *var = dynamic_cast<jit_variable *> (arg);
+      if (var && var->has_top ())
+        stash_argument (i, var->top ());
+    }
+}
+
+// -------------------- jit_block --------------------
+void
+jit_block::replace_with (jit_value *value)
+{
+  assert (isa<jit_block> (value));
+  jit_block *block = static_cast<jit_block *> (value);
+
+  jit_value::replace_with (block);
+
+  while (ILIST_T::first_use ())
+    {
+      jit_phi_incomming *incomming = ILIST_T::first_use ();
+      incomming->stash_value (block);
+    }
+}
+
+void
+jit_block::replace_in_phi (jit_block *ablock, jit_block *with)
+{
+  jit_phi_incomming *node = ILIST_T::first_use ();
+  while (node)
+    {
+      jit_phi_incomming *prev = node;
+      node = node->next ();
+
+      if (prev->user_parent () == ablock)
+        prev->stash_value (with);
+    }
+}
+
+jit_block *
+jit_block::maybe_merge ()
+{
+  if (successor_count () == 1 && successor (0) != this
+      && (successor (0)->use_count () == 1 || instructions.size () == 1))
+    {
+      jit_block *to_merge = successor (0);
+      merge (*to_merge);
+      return to_merge;
+    }
+
+  return 0;
+}
+
+void
+jit_block::merge (jit_block& block)
+{
+  // the merge block will contain a new terminator
+  jit_terminator *old_term = terminator ();
+  if (old_term)
+    old_term->remove ();
+
+  bool was_empty = end () == begin ();
+  iterator merge_begin = end ();
+  if (! was_empty)
+    --merge_begin;
+
+  instructions.splice (end (), block.instructions);
+  if (was_empty)
+    merge_begin = begin ();
+  else
+    ++merge_begin;
+
+  // now merge_begin points to the start of the new instructions, we must
+  // update their parent information
+  for (iterator iter = merge_begin; iter != end (); ++iter)
+    {
+      jit_instruction *instr = *iter;
+      instr->stash_parent (this, iter);
+    }
+
+  block.replace_with (this);
+}
+
+jit_instruction *
+jit_block::prepend (jit_instruction *instr)
+{
+  instructions.push_front (instr);
+  instr->stash_parent (this, instructions.begin ());
+  return instr;
+}
+
+jit_instruction *
+jit_block::prepend_after_phi (jit_instruction *instr)
+{
+  // FIXME: Make this O(1)
+  for (iterator iter = begin (); iter != end (); ++iter)
+    {
+      jit_instruction *temp = *iter;
+      if (! isa<jit_phi> (temp))
+        {
+          insert_before (iter, instr);
+          return instr;
+        }
+    }
+
+  return append (instr);
+}
+
+void
+jit_block::internal_append (jit_instruction *instr)
+{
+  instructions.push_back (instr);
+  instr->stash_parent (this, --instructions.end ());
+}
+
+jit_instruction *
+jit_block::insert_before (iterator loc, jit_instruction *instr)
+{
+  iterator iloc = instructions.insert (loc, instr);
+  instr->stash_parent (this, iloc);
+  return instr;
+}
+
+jit_instruction *
+jit_block::insert_after (iterator loc, jit_instruction *instr)
+{
+  ++loc;
+  iterator iloc = instructions.insert (loc, instr);
+  instr->stash_parent (this, iloc);
+  return instr;
+}
+
+jit_terminator *
+jit_block::terminator (void) const
+{
+  assert (this);
+  if (instructions.empty ())
+    return 0;
+
+  jit_instruction *last = instructions.back ();
+  return dynamic_cast<jit_terminator *> (last);
+}
+
+bool
+jit_block::branch_alive (jit_block *asucc) const
+{
+  return terminator ()->alive (asucc);
+}
+
+jit_block *
+jit_block::successor (size_t i) const
+{
+  jit_terminator *term = terminator ();
+  return term->successor (i);
+}
+
+size_t
+jit_block::successor_count (void) const
+{
+  jit_terminator *term = terminator ();
+  return term ? term->successor_count () : 0;
+}
+
+llvm::BasicBlock *
+jit_block::to_llvm (void) const
+{
+  return llvm::cast<llvm::BasicBlock> (llvm_value);
+}
+
+std::ostream&
+jit_block::print_dom (std::ostream& os) const
+{
+  short_print (os);
+  os << ":\n";
+  os << "  mid: " << mid << std::endl;
+  os << "  predecessors: ";
+  for (jit_use *use = first_use (); use; use = use->next ())
+    os << *use->user_parent () << " ";
+  os << std::endl;
+
+  os << "  successors: ";
+  for (size_t i = 0; i < successor_count (); ++i)
+    os << *successor (i) << " ";
+  os << std::endl;
+
+  os << "  idom: ";
+  if (idom)
+    os << *idom;
+  else
+    os << "NULL";
+  os << std::endl;
+  os << "  df: ";
+  for (df_iterator iter = df_begin (); iter != df_end (); ++iter)
+    os << **iter << " ";
+  os << std::endl;
+
+  os << "  dom_succ: ";
+  for (size_t i = 0; i < dom_succ.size (); ++i)
+    os << *dom_succ[i] << " ";
+
+  return os << std::endl;
+}
+
+void
+jit_block::compute_df (size_t avisit_count)
+{
+  if (visited (avisit_count))
+    return;
+
+  if (use_count () >= 2)
+    {
+      for (jit_use *use = first_use (); use; use = use->next ())
+        {
+          jit_block *runner = use->user_parent ();
+          while (runner != idom)
+            {
+              runner->mdf.insert (this);
+              runner = runner->idom;
+            }
+        }
+    }
+
+  for (size_t i = 0; i < successor_count (); ++i)
+    successor (i)->compute_df (avisit_count);
+}
+
+bool
+jit_block::update_idom (size_t avisit_count)
+{
+  if (visited (avisit_count) || ! use_count ())
+    return false;
+
+  bool changed = false;
+  for (jit_use *use = first_use (); use; use = use->next ())
+    {
+      jit_block *pred = use->user_parent ();
+      changed = pred->update_idom (avisit_count) || changed;
+    }
+
+  jit_use *use = first_use ();
+  jit_block *new_idom = use->user_parent ();
+  use = use->next ();
+
+  for (; use; use = use->next ())
+    {
+      jit_block *pred = use->user_parent ();
+      jit_block *pidom = pred->idom;
+      if (pidom)
+        new_idom = idom_intersect (pidom, new_idom);
+    }
+
+  if (idom != new_idom)
+    {
+      idom = new_idom;
+      return true;
+    }
+
+  return changed;
+}
+
+void
+jit_block::pop_all (void)
+{
+  for (iterator iter = begin (); iter != end (); ++iter)
+    {
+      jit_instruction *instr = *iter;
+      instr->pop_variable ();
+    }
+}
+
+jit_block *
+jit_block::maybe_split (jit_convert& convert, jit_block *asuccessor)
+{
+  if (successor_count () > 1)
+    {
+      jit_terminator *term = terminator ();
+      size_t idx = term->successor_index (asuccessor);
+      jit_block *split = convert.create<jit_block> ("phi_split", mvisit_count);
+
+      // try to place splits where they make sense
+      if (id () < asuccessor->id ())
+        convert.insert_before (asuccessor, split);
+      else
+        convert.insert_after (this, split);
+
+      term->stash_argument (idx, split);
+      jit_branch *br = split->append (convert.create<jit_branch> (asuccessor));
+      replace_in_phi (asuccessor, split);
+
+      if (alive ())
+        {
+          split->mark_alive ();
+          br->infer ();
+        }
+
+      return split;
+    }
+
+  return this;
+}
+
+void
+jit_block::create_dom_tree (size_t avisit_count)
+{
+  if (visited (avisit_count))
+    return;
+
+  if (idom != this)
+    idom->dom_succ.push_back (this);
+
+  for (size_t i = 0; i < successor_count (); ++i)
+    successor (i)->create_dom_tree (avisit_count);
+}
+
+jit_block *
+jit_block::idom_intersect (jit_block *i, jit_block *j)
+{
+  while (i && j && i != j)
+    {
+      while (i && i->id () > j->id ())
+        i = i->idom;
+
+      while (i && j && j->id () > i->id ())
+        j = j->idom;
+    }
+
+  return i ? i : j;
+}
+
+// -------------------- jit_phi_incomming --------------------
+
+jit_block *
+jit_phi_incomming::user_parent (void) const
+{ return muser->parent (); }
+
+// -------------------- jit_phi --------------------
+bool
+jit_phi::prune (void)
+{
+  jit_block *p = parent ();
+  size_t new_idx = 0;
+  jit_value *unique = argument (1);
+
+  for (size_t i = 0; i < argument_count (); ++i)
+    {
+      jit_block *inc = incomming (i);
+      if (inc->branch_alive (p))
+        {
+          if (unique != argument (i))
+            unique = 0;
+
+          if (new_idx != i)
+            {
+              stash_argument (new_idx, argument (i));
+              mincomming[new_idx].stash_value (inc);
+            }
+
+          ++new_idx;
+        }
+    }
+
+  if (new_idx != argument_count ())
+    {
+      resize_arguments (new_idx);
+      mincomming.resize (new_idx);
+    }
+
+  assert (argument_count () > 0);
+  if (unique)
+    {
+      replace_with (unique);
+      return true;
+    }
+
+  return false;
+}
+
+bool
+jit_phi::infer (void)
+{
+  jit_block *p = parent ();
+  if (! p->alive ())
+    return false;
+
+  jit_type *infered = 0;
+  for (size_t i = 0; i < argument_count (); ++i)
+    {
+      jit_block *inc = incomming (i);
+      if (inc->branch_alive (p))
+        infered = jit_typeinfo::join (infered, argument_type (i));
+    }
+
+  if (infered != type ())
+    {
+      stash_type (infered);
+      return true;
+    }
+
+  return false;
+}
+
+llvm::PHINode *
+jit_phi::to_llvm (void) const
+{
+  return llvm::cast<llvm::PHINode> (jit_value::to_llvm ());
+}
+
+// -------------------- jit_terminator --------------------
+size_t
+jit_terminator::successor_index (const jit_block *asuccessor) const
+{
+  size_t scount = successor_count ();
+  for (size_t i = 0; i < scount; ++i)
+    if (successor (i) == asuccessor)
+      return i;
+
+  panic_impossible ();
+}
+
+bool
+jit_terminator::infer (void)
+{
+  if (! parent ()->alive ())
+    return false;
+
+  bool changed = false;
+  for (size_t i = 0; i < malive.size (); ++i)
+    if (! malive[i] && check_alive (i))
+      {
+        changed = true;
+        malive[i] = true;
+        successor (i)->mark_alive ();
+      }
+
+  return changed;
+}
+
+llvm::TerminatorInst *
+jit_terminator::to_llvm (void) const
+{
+  return llvm::cast<llvm::TerminatorInst> (jit_value::to_llvm ());
+}
+
+// -------------------- jit_call --------------------
+bool
+jit_call::infer (void)
+{
+  // FIXME: explain algorithm
+  for (size_t i = 0; i < argument_count (); ++i)
+    {
+      already_infered[i] = argument_type (i);
+      if (! already_infered[i])
+        return false;
+    }
+
+  jit_type *infered = moperation.result (already_infered);
+  if (! infered && use_count ())
+    {
+      std::stringstream ss;
+      ss << "Missing overload in type inference for ";
+      print (ss, 0);
+      throw jit_fail_exception (ss.str ());
+    }
+
+  if (infered != type ())
+    {
+      stash_type (infered);
+      return true;
+    }
+
+  return false;
+}
+
+// -------------------- jit_magic_end --------------------
+jit_magic_end::jit_magic_end (const std::vector<context>& full_context)
+{
+  // for now we only support end in 1 dimensional indexing
+  resize_arguments (full_context.size ());
+
+  size_t i;
+  std::vector<context>::const_iterator iter;
+  for (iter = full_context.begin (), i = 0; iter != full_context.end (); ++iter,
+         ++i)
+    {
+      if (iter->count != 1)
+        throw jit_fail_exception ("end is only supported in linear contexts");
+      stash_argument (i, iter->value);
+    }
+}
+
+const jit_function&
+jit_magic_end::overload () const
+{
+  jit_value *ctx = resolve_context ();
+  if (ctx)
+    return jit_typeinfo::end (ctx->type ());
+
+  static jit_function null_ret;
+  return null_ret;
+}
+
+jit_value *
+jit_magic_end::resolve_context (void) const
+{
+  // FIXME: We need to have a way of marking functions so we can skip them here
+  return argument_count () ? argument (0) : 0;
+}
+
+bool
+jit_magic_end::infer (void)
+{
+  jit_type *new_type = overload ().result ();
+  if (new_type != type ())
+    {
+      stash_type (new_type);
+      return true;
+    }
+
+  return false;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/jit-ir.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,1302 @@
+/*
+
+Copyright (C) 2012 Max Brister <max@2bass.com>
+
+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/>.
+
+*/
+
+#if !defined (octave_jit_ir_h)
+#define octave_jit_ir_h 1
+
+#ifdef HAVE_LLVM
+
+#include <list>
+#include <stack>
+#include <set>
+
+#include "jit-typeinfo.h"
+
+// The low level octave jit ir
+// this ir is close to llvm, but contains information for doing type inference.
+// We convert the octave parse tree to this IR directly.
+
+#define JIT_VISIT_IR_NOTEMPLATE                 \
+  JIT_METH(block);                              \
+  JIT_METH(branch);                             \
+  JIT_METH(cond_branch);                        \
+  JIT_METH(call);                               \
+  JIT_METH(extract_argument);                   \
+  JIT_METH(store_argument);                     \
+  JIT_METH(phi);                                \
+  JIT_METH(variable);                           \
+  JIT_METH(error_check);                        \
+  JIT_METH(assign)                              \
+  JIT_METH(argument)                            \
+  JIT_METH(magic_end)
+
+#define JIT_VISIT_IR_CONST                      \
+  JIT_METH(const_bool);                         \
+  JIT_METH(const_scalar);                       \
+  JIT_METH(const_complex);                      \
+  JIT_METH(const_index);                        \
+  JIT_METH(const_string);                       \
+  JIT_METH(const_range)
+
+#define JIT_VISIT_IR_CLASSES                    \
+  JIT_VISIT_IR_NOTEMPLATE                       \
+  JIT_VISIT_IR_CONST
+
+// forward declare all ir classes
+#define JIT_METH(cname)                         \
+  class jit_ ## cname;
+
+JIT_VISIT_IR_NOTEMPLATE
+
+#undef JIT_METH
+
+class jit_convert;
+
+// ABCs which aren't included in  JIT_VISIT_IR_ALL
+class jit_instruction;
+class jit_terminator;
+
+template <typename T, jit_type *(*EXTRACT_T)(void), typename PASS_T = T,
+          bool QUOTE=false>
+class jit_const;
+
+typedef jit_const<bool, jit_typeinfo::get_bool> jit_const_bool;
+typedef jit_const<double, jit_typeinfo::get_scalar> jit_const_scalar;
+typedef jit_const<Complex, jit_typeinfo::get_complex> jit_const_complex;
+typedef jit_const<octave_idx_type, jit_typeinfo::get_index> jit_const_index;
+
+typedef jit_const<std::string, jit_typeinfo::get_string, const std::string&,
+                  true> jit_const_string;
+typedef jit_const<jit_range, jit_typeinfo::get_range, const jit_range&>
+jit_const_range;
+
+class jit_ir_walker;
+class jit_use;
+
+class
+jit_value : public jit_internal_list<jit_value, jit_use>
+{
+public:
+  jit_value (void) : llvm_value (0), ty (0), mlast_use (0),
+                     min_worklist (false) {}
+
+  virtual ~jit_value (void);
+
+  bool in_worklist (void) const
+  {
+    return min_worklist;
+  }
+
+  void stash_in_worklist (bool ain_worklist)
+  {
+    min_worklist = ain_worklist;
+  }
+
+  // The block of the first use which is not a jit_error_check
+  // So this is not necessarily first_use ()->parent ().
+  jit_block *first_use_block (void);
+
+  // replace all uses with
+  virtual void replace_with (jit_value *value);
+
+  jit_type *type (void) const { return ty; }
+
+  llvm::Type *type_llvm (void) const
+  {
+    return ty ? ty->to_llvm () : 0;
+  }
+
+  const std::string& type_name (void) const
+  {
+    return ty->name ();
+  }
+
+  void stash_type (jit_type *new_ty) { ty = new_ty; }
+
+  std::string print_string (void)
+  {
+    std::stringstream ss;
+    print (ss);
+    return ss.str ();
+  }
+
+  jit_instruction *last_use (void) const { return mlast_use; }
+
+  void stash_last_use (jit_instruction *alast_use)
+  {
+    mlast_use = alast_use;
+  }
+
+  virtual bool needs_release (void) const { return false; }
+
+  virtual std::ostream& print (std::ostream& os, size_t indent = 0) const = 0;
+
+  virtual std::ostream& short_print (std::ostream& os) const
+  { return print (os); }
+
+  virtual void accept (jit_ir_walker& walker) = 0;
+
+  bool has_llvm (void) const
+  {
+    return llvm_value;
+  }
+
+  llvm::Value *to_llvm (void) const
+  {
+    assert (llvm_value);
+    return llvm_value;
+  }
+
+  void stash_llvm (llvm::Value *compiled)
+  {
+    llvm_value = compiled;
+  }
+
+protected:
+  std::ostream& print_indent (std::ostream& os, size_t indent = 0) const
+  {
+    for (size_t i = 0; i < indent * 8; ++i)
+      os << " ";
+    return os;
+  }
+
+  llvm::Value *llvm_value;
+private:
+  jit_type *ty;
+  jit_instruction *mlast_use;
+  bool min_worklist;
+};
+
+std::ostream& operator<< (std::ostream& os, const jit_value& value);
+std::ostream& jit_print (std::ostream& os, jit_value *avalue);
+
+class
+jit_use : public jit_internal_node<jit_value, jit_use>
+{
+public:
+  jit_use (void) : muser (0), mindex (0) {}
+
+  // we should really have a move operator, but not until c++11 :(
+  jit_use (const jit_use& use) : muser (0), mindex (0)
+  {
+    *this = use;
+  }
+
+  jit_use& operator= (const jit_use& use)
+  {
+    stash_value (use.value (), use.user (), use.index ());
+    return *this;
+  }
+
+  size_t index (void) const { return mindex; }
+
+  jit_instruction *user (void) const { return muser; }
+
+  jit_block *user_parent (void) const;
+
+  std::list<jit_block *> user_parent_location (void) const;
+
+  void stash_value (jit_value *avalue, jit_instruction *auser = 0,
+                    size_t aindex = -1)
+  {
+    jit_internal_node::stash_value (avalue);
+    mindex = aindex;
+    muser = auser;
+  }
+private:
+  jit_instruction *muser;
+  size_t mindex;
+};
+
+class
+jit_instruction : public jit_value
+{
+public:
+  // FIXME: this code could be so much pretier with varadic templates...
+  jit_instruction (void) : mid (next_id ()), mparent (0)
+  {}
+
+  jit_instruction (size_t nargs) : mid (next_id ()), mparent (0)
+  {
+    already_infered.reserve (nargs);
+    marguments.reserve (nargs);
+  }
+
+#define STASH_ARG(i) stash_argument (i, arg ## i);
+#define JIT_INSTRUCTION_CTOR(N)                                         \
+  jit_instruction (OCT_MAKE_DECL_LIST (jit_value *, arg, N))            \
+  : already_infered (N), marguments (N), mid (next_id ()), mparent (0)  \
+  {                                                                     \
+    OCT_ITERATE_MACRO (STASH_ARG, N);                                   \
+  }
+
+  JIT_INSTRUCTION_CTOR(1)
+  JIT_INSTRUCTION_CTOR(2)
+  JIT_INSTRUCTION_CTOR(3)
+  JIT_INSTRUCTION_CTOR(4)
+
+#undef STASH_ARG
+#undef JIT_INSTRUCTION_CTOR
+
+  jit_instruction (const std::vector<jit_value *>& aarguments)
+  : already_infered (aarguments.size ()), marguments (aarguments.size ()),
+    mid (next_id ()), mparent (0)
+  {
+    for (size_t i = 0; i < aarguments.size (); ++i)
+      stash_argument (i, aarguments[i]);
+  }
+
+  static void reset_ids (void)
+  {
+    next_id (true);
+  }
+
+  jit_value *argument (size_t i) const
+  {
+    return marguments[i].value ();
+  }
+
+  llvm::Value *argument_llvm (size_t i) const
+  {
+    assert (argument (i));
+    return argument (i)->to_llvm ();
+  }
+
+  jit_type *argument_type (size_t i) const
+  {
+    return argument (i)->type ();
+  }
+
+  llvm::Type *argument_type_llvm (size_t i) const
+  {
+    assert (argument (i));
+    return argument_type (i)->to_llvm ();
+  }
+
+  std::ostream& print_argument (std::ostream& os, size_t i) const
+  {
+    if (argument (i))
+      return argument (i)->short_print (os);
+    else
+      return os << "NULL";
+  }
+
+  void stash_argument (size_t i, jit_value *arg)
+  {
+    marguments[i].stash_value (arg, this, i);
+  }
+
+  void push_argument (jit_value *arg)
+  {
+    marguments.push_back (jit_use ());
+    stash_argument (marguments.size () - 1, arg);
+    already_infered.push_back (0);
+  }
+
+  size_t argument_count (void) const
+  {
+    return marguments.size ();
+  }
+
+  void resize_arguments (size_t acount, jit_value *adefault = 0)
+  {
+    size_t old = marguments.size ();
+    marguments.resize (acount);
+    already_infered.resize (acount);
+
+    if (adefault)
+      for (size_t i = old; i < acount; ++i)
+        stash_argument (i, adefault);
+  }
+
+  const std::vector<jit_use>& arguments (void) const { return marguments; }
+
+  // argument types which have been infered already
+  const std::vector<jit_type *>& argument_types (void) const
+  { return already_infered; }
+
+  virtual void push_variable (void) {}
+
+  virtual void pop_variable (void) {}
+
+  virtual void construct_ssa (void)
+  {
+    do_construct_ssa (0, argument_count ());
+  }
+
+  virtual bool infer (void) { return false; }
+
+  void remove (void);
+
+  virtual std::ostream& short_print (std::ostream& os) const;
+
+  jit_block *parent (void) const { return mparent; }
+
+  std::list<jit_instruction *>::iterator location (void) const
+  {
+    return mlocation;
+  }
+
+  llvm::BasicBlock *parent_llvm (void) const;
+
+  void stash_parent (jit_block *aparent,
+                     std::list<jit_instruction *>::iterator alocation)
+  {
+    mparent = aparent;
+    mlocation = alocation;
+  }
+
+  size_t id (void) const { return mid; }
+protected:
+
+  // Do SSA replacement on arguments in [start, end)
+  void do_construct_ssa (size_t start, size_t end);
+
+  std::vector<jit_type *> already_infered;
+private:
+  static size_t next_id (bool reset = false)
+  {
+    static size_t ret = 0;
+    if (reset)
+      return ret = 0;
+
+    return ret++;
+  }
+
+  std::vector<jit_use> marguments;
+
+  size_t mid;
+  jit_block *mparent;
+  std::list<jit_instruction *>::iterator mlocation;
+};
+
+// defnie accept methods for subclasses
+#define JIT_VALUE_ACCEPT                        \
+  virtual void accept (jit_ir_walker& walker);
+
+// for use as a dummy argument during conversion to LLVM
+class
+jit_argument : public jit_value
+{
+public:
+  jit_argument (jit_type *atype, llvm::Value *avalue)
+  {
+    stash_type (atype);
+    stash_llvm (avalue);
+  }
+
+  virtual std::ostream& print (std::ostream& os, size_t indent = 0) const
+  {
+    print_indent (os, indent);
+    return jit_print (os, type ()) << ": DUMMY";
+  }
+
+  JIT_VALUE_ACCEPT;
+};
+
+template <typename T, jit_type *(*EXTRACT_T)(void), typename PASS_T,
+          bool QUOTE>
+class
+jit_const : public jit_value
+{
+public:
+  typedef PASS_T pass_t;
+
+  jit_const (PASS_T avalue) : mvalue (avalue)
+  {
+    stash_type (EXTRACT_T ());
+  }
+
+  PASS_T value (void) const { return mvalue; }
+
+  virtual std::ostream& print (std::ostream& os, size_t indent = 0) const
+  {
+    print_indent (os, indent);
+    jit_print (os, type ()) << ": ";
+    if (QUOTE)
+      os << "\"";
+    os << mvalue;
+    if (QUOTE)
+      os << "\"";
+    return os;
+  }
+
+  JIT_VALUE_ACCEPT;
+private:
+  T mvalue;
+};
+
+class jit_phi_incomming;
+
+class
+jit_block : public jit_value, public jit_internal_list<jit_block,
+                                                       jit_phi_incomming>
+{
+  typedef jit_internal_list<jit_block, jit_phi_incomming> ILIST_T;
+public:
+  typedef std::list<jit_instruction *> instruction_list;
+  typedef instruction_list::iterator iterator;
+  typedef instruction_list::const_iterator const_iterator;
+
+  typedef std::set<jit_block *> df_set;
+  typedef df_set::const_iterator df_iterator;
+
+  static const size_t NO_ID = static_cast<size_t> (-1);
+
+  jit_block (const std::string& aname, size_t avisit_count = 0)
+    : mvisit_count (avisit_count), mid (NO_ID), idom (0), mname (aname),
+      malive (false)
+  {}
+
+  virtual void replace_with (jit_value *value);
+
+  void replace_in_phi (jit_block *ablock, jit_block *with);
+
+  // we have a new internal list, but we want to stay compatable with jit_value
+  jit_use *first_use (void) const { return jit_value::first_use (); }
+
+  size_t use_count (void) const { return jit_value::use_count (); }
+
+  // if a block is alive, then it might be visited during execution
+  bool alive (void) const { return malive; }
+
+  void mark_alive (void) { malive = true; }
+
+  // If we can merge with a successor, do so and return the now empty block
+  jit_block *maybe_merge ();
+
+  // merge another block into this block, leaving the merge block empty
+  void merge (jit_block& merge);
+
+  const std::string& name (void) const { return mname; }
+
+  jit_instruction *prepend (jit_instruction *instr);
+
+  jit_instruction *prepend_after_phi (jit_instruction *instr);
+
+  template <typename T>
+  T *append (T *instr)
+  {
+    internal_append (instr);
+    return instr;
+  }
+
+  jit_instruction *insert_before (iterator loc, jit_instruction *instr);
+
+  jit_instruction *insert_before (jit_instruction *loc, jit_instruction *instr)
+  {
+    return insert_before (loc->location (), instr);
+  }
+
+  jit_instruction *insert_after (iterator loc, jit_instruction *instr);
+
+  jit_instruction *insert_after (jit_instruction *loc, jit_instruction *instr)
+  {
+    return insert_after (loc->location (), instr);
+  }
+
+  iterator remove (iterator iter)
+  {
+    jit_instruction *instr = *iter;
+    iter = instructions.erase (iter);
+    instr->stash_parent (0, instructions.end ());
+    return iter;
+  }
+
+  jit_terminator *terminator (void) const;
+
+  // is the jump from pred alive?
+  bool branch_alive (jit_block *asucc) const;
+
+  jit_block *successor (size_t i) const;
+
+  size_t successor_count (void) const;
+
+  iterator begin (void) { return instructions.begin (); }
+
+  const_iterator begin (void) const { return instructions.begin (); }
+
+  iterator end (void) { return instructions.end (); }
+
+  const_iterator end (void) const { return instructions.end (); }
+
+  iterator phi_begin (void);
+
+  iterator phi_end (void);
+
+  iterator nonphi_begin (void);
+
+  // must label before id is valid
+  size_t id (void) const { return mid; }
+
+  // dominance frontier
+  const df_set& df (void) const { return mdf; }
+
+  df_iterator df_begin (void) const { return mdf.begin (); }
+
+  df_iterator df_end (void) const { return mdf.end (); }
+
+  // label with a RPO walk
+  void label (void)
+  {
+    size_t number = 0;
+    label (mvisit_count, number);
+  }
+
+  void label (size_t avisit_count, size_t& number)
+  {
+    if (visited (avisit_count))
+      return;
+
+    for (jit_use *use = first_use (); use; use = use->next ())
+      {
+        jit_block *pred = use->user_parent ();
+        pred->label (avisit_count, number);
+      }
+
+    mid = number++;
+  }
+
+  // See for idom computation algorithm
+  // Cooper, Keith D.; Harvey, Timothy J; and Kennedy, Ken (2001).
+  // "A Simple, Fast Dominance Algorithm"
+  void compute_idom (jit_block *entry_block)
+  {
+    bool changed;
+    entry_block->idom = entry_block;
+    do
+      changed = update_idom (mvisit_count);
+    while (changed);
+  }
+
+  // compute dominance frontier
+  void compute_df (void)
+  {
+    compute_df (mvisit_count);
+  }
+
+  void create_dom_tree (void)
+  {
+    create_dom_tree (mvisit_count);
+  }
+
+  jit_block *dom_successor (size_t idx) const
+  {
+    return dom_succ[idx];
+  }
+
+  size_t dom_successor_count (void) const
+  {
+    return dom_succ.size ();
+  }
+
+  // call pop_varaible on all instructions
+  void pop_all (void);
+
+  virtual std::ostream& print (std::ostream& os, size_t indent = 0) const
+  {
+    print_indent (os, indent);
+    short_print (os) << ":        %pred = ";
+    for (jit_use *use = first_use (); use; use = use->next ())
+      {
+        jit_block *pred = use->user_parent ();
+        os << *pred;
+        if (use->next ())
+          os << ", ";
+      }
+    os << std::endl;
+
+    for (const_iterator iter = begin (); iter != end (); ++iter)
+      {
+        jit_instruction *instr = *iter;
+        instr->print (os, indent + 1) << std::endl;
+      }
+    return os;
+  }
+
+  // ...
+  jit_block *maybe_split (jit_convert& convert, jit_block *asuccessor);
+
+  jit_block *maybe_split (jit_convert& convert, jit_block& asuccessor)
+  {
+    return maybe_split (convert, &asuccessor);
+  }
+
+  // print dominator infomration
+  std::ostream& print_dom (std::ostream& os) const;
+
+  virtual std::ostream& short_print (std::ostream& os) const
+  {
+    os << mname;
+    if (mid != NO_ID)
+      os << mid;
+    return os;
+  }
+
+  llvm::BasicBlock *to_llvm (void) const;
+
+  std::list<jit_block *>::iterator location (void) const
+  { return mlocation; }
+
+  void stash_location (std::list<jit_block *>::iterator alocation)
+  { mlocation = alocation; }
+
+  // used to prevent visiting the same node twice in the graph
+  size_t visit_count (void) const { return mvisit_count; }
+
+  // check if this node has been visited yet at the given visit count. If we
+  // have not been visited yet, mark us as visited.
+  bool visited (size_t avisit_count)
+  {
+    if (mvisit_count <= avisit_count)
+      {
+        mvisit_count = avisit_count + 1;
+        return false;
+      }
+
+    return true;
+  }
+
+  JIT_VALUE_ACCEPT;
+private:
+  void internal_append (jit_instruction *instr);
+
+  void compute_df (size_t avisit_count);
+
+  bool update_idom (size_t avisit_count);
+
+  void create_dom_tree (size_t avisit_count);
+
+  static jit_block *idom_intersect (jit_block *i, jit_block *j);
+
+  size_t mvisit_count;
+  size_t mid;
+  jit_block *idom;
+  df_set mdf;
+  std::vector<jit_block *> dom_succ;
+  std::string mname;
+  instruction_list instructions;
+  bool malive;
+  std::list<jit_block *>::iterator mlocation;
+};
+
+// keeps track of phi functions that use a block on incomming edges
+class
+jit_phi_incomming : public jit_internal_node<jit_block, jit_phi_incomming>
+{
+public:
+  jit_phi_incomming (void) : muser (0) {}
+
+  jit_phi_incomming (jit_phi *auser) : muser (auser) {}
+
+  jit_phi_incomming (const jit_phi_incomming& use) : jit_internal_node ()
+  {
+    *this = use;
+  }
+
+  jit_phi_incomming& operator= (const jit_phi_incomming& use)
+  {
+    stash_value (use.value ());
+    muser = use.muser;
+    return *this;
+  }
+
+  jit_phi *user (void) const { return muser; }
+
+  jit_block *user_parent (void) const;
+private:
+  jit_phi *muser;
+};
+
+// A non-ssa variable
+class
+jit_variable : public jit_value
+{
+public:
+  jit_variable (const std::string& aname) : mname (aname), mlast_use (0) {}
+
+  const std::string &name (void) const { return mname; }
+
+  // manipulate the value_stack, for use during SSA construction. The top of the
+  // value stack represents the current value for this variable
+  bool has_top (void) const
+  {
+    return ! value_stack.empty ();
+  }
+
+  jit_value *top (void) const
+  {
+    return value_stack.top ();
+  }
+
+  void push (jit_instruction *v)
+  {
+    value_stack.push (v);
+    mlast_use = v;
+  }
+
+  void pop (void)
+  {
+    value_stack.pop ();
+  }
+
+  jit_instruction *last_use (void) const
+  {
+    return mlast_use;
+  }
+
+  void stash_last_use (jit_instruction *instr)
+  {
+    mlast_use = instr;
+  }
+
+  // blocks in which we are used
+  void use_blocks (jit_block::df_set& result)
+  {
+    jit_use *use = first_use ();
+    while (use)
+      {
+        result.insert (use->user_parent ());
+        use = use->next ();
+      }
+  }
+
+  virtual std::ostream& print (std::ostream& os, size_t indent = 0) const
+  {
+    return print_indent (os, indent) << mname;
+  }
+
+  JIT_VALUE_ACCEPT;
+private:
+  std::string mname;
+  std::stack<jit_value *> value_stack;
+  jit_instruction *mlast_use;
+};
+
+class
+jit_assign_base : public jit_instruction
+{
+public:
+  jit_assign_base (jit_variable *adest) : jit_instruction (), mdest (adest) {}
+
+  jit_assign_base (jit_variable *adest, size_t npred) : jit_instruction (npred),
+                                                        mdest (adest) {}
+
+  jit_assign_base (jit_variable *adest, jit_value *arg0, jit_value *arg1)
+    : jit_instruction (arg0, arg1), mdest (adest) {}
+
+  jit_variable *dest (void) const { return mdest; }
+
+  virtual void push_variable (void)
+  {
+    mdest->push (this);
+  }
+
+  virtual void pop_variable (void)
+  {
+    mdest->pop ();
+  }
+
+  virtual std::ostream& short_print (std::ostream& os) const
+  {
+    if (type ())
+      jit_print (os, type ()) << ": ";
+
+    dest ()->short_print (os);
+    return os << "#" << id ();
+  }
+private:
+  jit_variable *mdest;
+};
+
+class
+jit_assign : public jit_assign_base
+{
+public:
+  jit_assign (jit_variable *adest, jit_value *asrc)
+    : jit_assign_base (adest, adest, asrc), martificial (false) {}
+
+  jit_value *overwrite (void) const
+  {
+    return argument (0);
+  }
+
+  jit_value *src (void) const
+  {
+    return argument (1);
+  }
+
+  // variables don't get modified in an SSA, but COW requires we modify
+  // variables. An artificial assign is for when a variable gets modified. We
+  // need an assign in the SSA, but the reference counts shouldn't be updated.
+  bool artificial (void) const { return martificial; }
+
+  void mark_artificial (void) { martificial = true; }
+
+  virtual bool infer (void)
+  {
+    jit_type *stype = src ()->type ();
+    if (stype != type())
+      {
+        stash_type (stype);
+        return true;
+      }
+
+    return false;
+  }
+
+  virtual std::ostream& print (std::ostream& os, size_t indent = 0) const
+  {
+    print_indent (os, indent) << *this << " = " << *src ();
+
+    if (artificial ())
+      os << " [artificial]";
+
+    return os;
+  }
+
+  JIT_VALUE_ACCEPT;
+private:
+  bool martificial;
+};
+
+class
+jit_phi : public jit_assign_base
+{
+public:
+  jit_phi (jit_variable *adest, size_t npred)
+    : jit_assign_base (adest, npred)
+  {
+    mincomming.reserve (npred);
+  }
+
+  // removes arguments form dead incomming jumps
+  bool prune (void);
+
+  void add_incomming (jit_block *from, jit_value *value)
+  {
+    push_argument (value);
+    mincomming.push_back (jit_phi_incomming (this));
+    mincomming[mincomming.size () - 1].stash_value (from);
+  }
+
+  jit_block *incomming (size_t i) const
+  {
+    return mincomming[i].value ();
+  }
+
+  llvm::BasicBlock *incomming_llvm (size_t i) const
+  {
+    return incomming (i)->to_llvm ();
+  }
+
+  virtual void construct_ssa (void) {}
+
+  virtual bool infer (void);
+
+  virtual std::ostream& print (std::ostream& os, size_t indent = 0) const
+  {
+    std::stringstream ss;
+    print_indent (ss, indent);
+    short_print (ss) << " phi ";
+    std::string ss_str = ss.str ();
+    std::string indent_str (ss_str.size (), ' ');
+    os << ss_str;
+
+    for (size_t i = 0; i < argument_count (); ++i)
+      {
+        if (i > 0)
+          os << indent_str;
+        os << "| ";
+
+        os << *incomming (i) << " -> ";
+        os << *argument (i);
+
+        if (i + 1 < argument_count ())
+          os << std::endl;
+      }
+
+    return os;
+  }
+
+  llvm::PHINode *to_llvm (void) const;
+
+  JIT_VALUE_ACCEPT;
+private:
+  std::vector<jit_phi_incomming> mincomming;
+};
+
+class
+jit_terminator : public jit_instruction
+{
+public:
+#define JIT_TERMINATOR_CONST(N)                                         \
+  jit_terminator (size_t asuccessor_count,                              \
+                  OCT_MAKE_DECL_LIST (jit_value *, arg, N))             \
+    : jit_instruction (OCT_MAKE_ARG_LIST (arg, N)),                     \
+      malive (asuccessor_count, false) {}
+
+  JIT_TERMINATOR_CONST (1)
+  JIT_TERMINATOR_CONST (2)
+  JIT_TERMINATOR_CONST (3)
+
+#undef JIT_TERMINATOR_CONST
+
+  jit_block *successor (size_t idx = 0) const
+  {
+    return static_cast<jit_block *> (argument (idx));
+  }
+
+  llvm::BasicBlock *successor_llvm (size_t idx = 0) const
+  {
+    return successor (idx)->to_llvm ();
+  }
+
+  size_t successor_index (const jit_block *asuccessor) const;
+
+  std::ostream& print_successor (std::ostream& os, size_t idx = 0) const
+  {
+    if (alive (idx))
+      os << "[live] ";
+    else
+      os << "[dead] ";
+
+    return successor (idx)->short_print (os);
+  }
+
+  // Check if the jump to successor is live
+  bool alive (const jit_block *asuccessor) const
+  {
+    return alive (successor_index (asuccessor));
+  }
+
+  bool alive (size_t idx) const { return malive[idx]; }
+
+  bool alive (int idx) const { return malive[idx]; }
+
+  size_t successor_count (void) const { return malive.size (); }
+
+  virtual bool infer (void);
+
+  llvm::TerminatorInst *to_llvm (void) const;
+protected:
+  virtual bool check_alive (size_t) const { return true; }
+private:
+  std::vector<bool> malive;
+};
+
+class
+jit_branch : public jit_terminator
+{
+public:
+  jit_branch (jit_block *succ) : jit_terminator (1, succ) {}
+
+  virtual size_t successor_count (void) const { return 1; }
+
+  virtual std::ostream& print (std::ostream& os, size_t indent = 0) const
+  {
+    print_indent (os, indent) << "branch: ";
+    return print_successor (os);
+  }
+
+  JIT_VALUE_ACCEPT;
+};
+
+class
+jit_cond_branch : public jit_terminator
+{
+public:
+  jit_cond_branch (jit_value *c, jit_block *ctrue, jit_block *cfalse)
+    : jit_terminator (2, ctrue, cfalse, c) {}
+
+  jit_value *cond (void) const { return argument (2); }
+
+  std::ostream& print_cond (std::ostream& os) const
+  {
+    return cond ()->short_print (os);
+  }
+
+  llvm::Value *cond_llvm (void) const
+  {
+    return cond ()->to_llvm ();
+  }
+
+  virtual size_t successor_count (void) const { return 2; }
+
+  virtual std::ostream& print (std::ostream& os, size_t indent = 0) const
+  {
+    print_indent (os, indent) << "cond_branch: ";
+    print_cond (os) << ", ";
+    print_successor (os, 0) << ", ";
+    return print_successor (os, 1);
+  }
+
+  JIT_VALUE_ACCEPT;
+};
+
+class
+jit_call : public jit_instruction
+{
+public:
+#define JIT_CALL_CONST(N)                                               \
+  jit_call (const jit_operation& aoperation,                            \
+            OCT_MAKE_DECL_LIST (jit_value *, arg, N))                   \
+    : jit_instruction (OCT_MAKE_ARG_LIST (arg, N)), moperation (aoperation) {} \
+                                                                        \
+  jit_call (const jit_operation& (*aoperation) (void),                  \
+            OCT_MAKE_DECL_LIST (jit_value *, arg, N))                   \
+    : jit_instruction (OCT_MAKE_ARG_LIST (arg, N)), moperation (aoperation ()) \
+  {}
+
+  JIT_CALL_CONST (1)
+  JIT_CALL_CONST (2)
+  JIT_CALL_CONST (3)
+  JIT_CALL_CONST (4)
+
+#undef JIT_CALL_CONST
+
+  jit_call (const jit_operation& aoperation,
+            const std::vector<jit_value *>& args)
+  : jit_instruction (args), moperation (aoperation)
+  {}
+
+  const jit_operation& operation (void) const { return moperation; }
+
+  bool can_error (void) const
+  {
+    return overload ().can_error ();
+  }
+
+  const jit_function& overload (void) const
+  {
+    return moperation.overload (argument_types ());
+  }
+
+  virtual bool needs_release (void) const
+  {
+    return type () && jit_typeinfo::get_release (type ()).valid ();
+  }
+
+  virtual std::ostream& print (std::ostream& os, size_t indent = 0) const
+  {
+    print_indent (os, indent);
+
+    if (use_count ())
+      short_print (os) << " = ";
+    os << "call " << moperation.name () << " (";
+
+    for (size_t i = 0; i < argument_count (); ++i)
+      {
+        print_argument (os, i);
+        if (i + 1 < argument_count ())
+          os << ", ";
+      }
+    return os << ")";
+  }
+
+  virtual bool infer (void);
+
+  JIT_VALUE_ACCEPT;
+private:
+  const jit_operation& moperation;
+};
+
+// FIXME: This is just ugly...
+// checks error_state, if error_state is false then goto the normal branche,
+// otherwise goto the error branch
+class
+jit_error_check : public jit_terminator
+{
+public:
+  jit_error_check (jit_call *acheck_for, jit_block *normal, jit_block *error)
+    : jit_terminator (2, error, normal, acheck_for) {}
+
+  jit_call *check_for (void) const
+  {
+    return static_cast<jit_call *> (argument (2));
+  }
+
+  virtual std::ostream& print (std::ostream& os, size_t indent = 0) const
+  {
+    print_indent (os, indent) << "error_check " << *check_for () << ", ";
+    print_successor (os, 1) << ", ";
+    return print_successor (os, 0);
+  }
+
+  JIT_VALUE_ACCEPT;
+protected:
+  virtual bool check_alive (size_t idx) const
+  {
+    return idx == 1 ? true : check_for ()->can_error ();
+  }
+};
+
+// for now only handles the 1D case
+class
+jit_magic_end : public jit_instruction
+{
+public:
+  class
+  context
+  {
+  public:
+    context (void) : value (0), index (0), count (0)
+    {}
+
+    context (jit_value *avalue, size_t aindex, size_t acount)
+      : value (avalue), index (aindex), count (acount)
+    {}
+
+    jit_value *value;
+    size_t index;
+    size_t count;
+  };
+
+  jit_magic_end (const std::vector<context>& full_context);
+
+  const jit_function& overload () const;
+
+  jit_value *resolve_context (void) const;
+
+  virtual bool infer (void);
+
+  virtual std::ostream& short_print (std::ostream& os) const
+  {
+    return os << "magic_end";
+  }
+
+  virtual std::ostream& print (std::ostream& os, size_t indent = 0) const
+  {
+    return short_print (print_indent (os, indent));
+  }
+
+  JIT_VALUE_ACCEPT;
+};
+
+class
+jit_extract_argument : public jit_assign_base
+{
+public:
+  jit_extract_argument (jit_type *atype, jit_variable *adest)
+    : jit_assign_base (adest)
+  {
+    stash_type (atype);
+  }
+
+  const std::string& name (void) const
+  {
+    return dest ()->name ();
+  }
+
+  const jit_function& overload (void) const
+  {
+    return jit_typeinfo::cast (type (), jit_typeinfo::get_any ());
+  }
+
+  virtual std::ostream& print (std::ostream& os, size_t indent = 0) const
+  {
+    print_indent (os, indent);
+
+    return short_print (os) << " = extract " << name ();
+  }
+
+  JIT_VALUE_ACCEPT;
+};
+
+class
+jit_store_argument : public jit_instruction
+{
+public:
+  jit_store_argument (jit_variable *var)
+  : jit_instruction (var), dest (var)
+  {}
+
+  const std::string& name (void) const
+  {
+    return dest->name ();
+  }
+
+  const jit_function& overload (void) const
+  {
+    return jit_typeinfo::cast (jit_typeinfo::get_any (), result_type ());
+  }
+
+  jit_value *result (void) const
+  {
+    return argument (0);
+  }
+
+  jit_type *result_type (void) const
+  {
+    return result ()->type ();
+  }
+
+  llvm::Value *result_llvm (void) const
+  {
+    return result ()->to_llvm ();
+  }
+
+  virtual std::ostream& print (std::ostream& os, size_t indent = 0) const
+  {
+    jit_value *res = result ();
+    print_indent (os, indent) << "store ";
+    dest->short_print (os);
+
+    if (! isa<jit_variable> (res))
+      {
+        os << " = ";
+        res->short_print (os);
+      }
+
+    return os;
+  }
+
+  JIT_VALUE_ACCEPT;
+private:
+  jit_variable *dest;
+};
+
+class
+jit_ir_walker
+{
+public:
+  virtual ~jit_ir_walker () {}
+
+#define JIT_METH(clname) \
+  virtual void visit (jit_ ## clname&) = 0;
+
+  JIT_VISIT_IR_CLASSES;
+
+#undef JIT_METH
+};
+
+template <typename T, jit_type *(*EXTRACT_T)(void), typename PASS_T, bool QUOTE>
+void
+jit_const<T, EXTRACT_T, PASS_T, QUOTE>::accept (jit_ir_walker& walker)
+{
+  walker.visit (*this);
+}
+
+#undef JIT_VALUE_ACCEPT
+
+#endif
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/jit-typeinfo.cc	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,2071 @@
+/*
+
+Copyright (C) 2012 Max Brister <max@2bass.com>
+
+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/>.
+
+*/
+
+// defines required by llvm
+#define __STDC_LIMIT_MACROS
+#define __STDC_CONSTANT_MACROS
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_LLVM
+
+#include "jit-typeinfo.h"
+
+#include <llvm/Analysis/Verifier.h>
+#include <llvm/GlobalVariable.h>
+#include <llvm/ExecutionEngine/ExecutionEngine.h>
+#include <llvm/LLVMContext.h>
+#include <llvm/Function.h>
+#include <llvm/Instructions.h>
+#include <llvm/Intrinsics.h>
+#include <llvm/Support/IRBuilder.h>
+#include <llvm/Support/raw_os_ostream.h>
+
+#include "jit-ir.h"
+#include "ov.h"
+#include "ov-builtin.h"
+#include "ov-complex.h"
+#include "ov-scalar.h"
+#include "pager.h"
+
+static llvm::LLVMContext& context = llvm::getGlobalContext ();
+
+jit_typeinfo *jit_typeinfo::instance = 0;
+
+std::ostream& jit_print (std::ostream& os, jit_type *atype)
+{
+  if (! atype)
+    return os << "null";
+  return os << atype->name ();
+}
+
+// function that jit code calls
+extern "C" void
+octave_jit_print_any (const char *name, octave_base_value *obv)
+{
+  obv->print_with_name (octave_stdout, name, true);
+}
+
+extern "C" void
+octave_jit_print_scalar (const char *name, double value)
+{
+  // FIXME: We should avoid allocating a new octave_scalar each time
+  octave_value ov (value);
+  ov.print_with_name (octave_stdout, name);
+}
+
+extern "C" octave_base_value*
+octave_jit_binary_any_any (octave_value::binary_op op, octave_base_value *lhs,
+                           octave_base_value *rhs)
+{
+  octave_value olhs (lhs, true);
+  octave_value orhs (rhs, true);
+  octave_value result = do_binary_op (op, olhs, orhs);
+  octave_base_value *rep = result.internal_rep ();
+  rep->grab ();
+  return rep;
+}
+
+extern "C" octave_idx_type
+octave_jit_compute_nelem (double base, double limit, double inc)
+{
+  Range rng = Range (base, limit, inc);
+  return rng.nelem ();
+}
+
+extern "C" void
+octave_jit_release_any (octave_base_value *obv)
+{
+  obv->release ();
+}
+
+extern "C" void
+octave_jit_release_matrix (jit_matrix *m)
+{
+  delete m->array;
+}
+
+extern "C" octave_base_value *
+octave_jit_grab_any (octave_base_value *obv)
+{
+  obv->grab ();
+  return obv;
+}
+
+extern "C" void
+octave_jit_grab_matrix (jit_matrix *result, jit_matrix *m)
+{
+  *result = *m->array;
+}
+
+extern "C" octave_base_value *
+octave_jit_cast_any_matrix (jit_matrix *m)
+{
+  octave_value ret (*m->array);
+  octave_base_value *rep = ret.internal_rep ();
+  rep->grab ();
+  delete m->array;
+
+  return rep;
+}
+
+extern "C" void
+octave_jit_cast_matrix_any (jit_matrix *ret, octave_base_value *obv)
+{
+  NDArray m = obv->array_value ();
+  *ret = m;
+  obv->release ();
+}
+
+extern "C" octave_base_value *
+octave_jit_cast_any_range (jit_range *rng)
+{
+  Range temp (*rng);
+  octave_value ret (temp);
+  octave_base_value *rep = ret.internal_rep ();
+  rep->grab ();
+
+  return rep;
+}
+extern "C" void
+octave_jit_cast_range_any (jit_range *ret, octave_base_value *obv)
+{
+
+  jit_range r (obv->range_value ());
+  *ret = r;
+  obv->release ();
+}
+
+extern "C" double
+octave_jit_cast_scalar_any (octave_base_value *obv)
+{
+  double ret = obv->double_value ();
+  obv->release ();
+  return ret;
+}
+
+extern "C" octave_base_value *
+octave_jit_cast_any_scalar (double value)
+{
+  return new octave_scalar (value);
+}
+
+extern "C" Complex
+octave_jit_cast_complex_any (octave_base_value *obv)
+{
+  Complex ret = obv->complex_value ();
+  obv->release ();
+  return ret;
+}
+
+extern "C" octave_base_value *
+octave_jit_cast_any_complex (Complex c)
+{
+  if (c.imag () == 0)
+    return new octave_scalar (c.real ());
+  else
+    return new octave_complex (c);
+}
+
+extern "C" void
+octave_jit_gripe_nan_to_logical_conversion (void)
+{
+  try
+    {
+      gripe_nan_to_logical_conversion ();
+    }
+  catch (const octave_execution_exception&)
+    {
+      gripe_library_execution_error ();
+    }
+}
+
+extern "C" void
+octave_jit_ginvalid_index (void)
+{
+  try
+    {
+      gripe_invalid_index ();
+    }
+  catch (const octave_execution_exception&)
+    {
+      gripe_library_execution_error ();
+    }
+}
+
+extern "C" void
+octave_jit_gindex_range (int nd, int dim, octave_idx_type iext,
+                         octave_idx_type ext)
+{
+  try
+    {
+      gripe_index_out_of_range (nd, dim, iext, ext);
+    }
+  catch (const octave_execution_exception&)
+    {
+      gripe_library_execution_error ();
+    }
+}
+
+extern "C" void
+octave_jit_paren_subsasgn_impl (jit_matrix *ret, jit_matrix *mat,
+                                octave_idx_type index, double value)
+{
+  NDArray *array = mat->array;
+  if (array->nelem () < index)
+    array->resize1 (index);
+
+  double *data = array->fortran_vec ();
+  data[index - 1] = value;
+
+  mat->update ();
+  *ret = *mat;
+}
+
+static void
+make_indices (double *indices, octave_idx_type idx_count,
+              Array<idx_vector>& result)
+{
+  result.resize (dim_vector (1, idx_count));
+  for (octave_idx_type i = 0; i < idx_count; ++i)
+    result(i) = idx_vector (indices[i]);
+}
+
+extern "C" double
+octave_jit_paren_scalar (jit_matrix *mat, double *indicies,
+                         octave_idx_type idx_count)
+{
+  // FIXME: Replace this with a more optimal version
+  try
+    {
+      Array<idx_vector> idx;
+      make_indices (indicies, idx_count, idx);
+
+      Array<double> ret = mat->array->index (idx);
+      return ret.xelem (0);
+    }
+  catch (const octave_execution_exception&)
+    {
+      gripe_library_execution_error ();
+      return 0;
+    }
+}
+
+extern "C" void
+octave_jit_paren_scalar_subsasgn (jit_matrix *ret, jit_matrix *mat,
+                                  double *indices, octave_idx_type idx_count,
+                                  double value)
+{
+  // FIXME: Replace this with a more optimal version
+  try
+    {
+      Array<idx_vector> idx;
+      make_indices (indices, idx_count, idx);
+
+      Matrix temp (1, 1);
+      temp.xelem(0) = value;
+      mat->array->assign (idx, temp);
+      ret->update (mat->array);
+    }
+  catch (const octave_execution_exception&)
+    {
+      gripe_library_execution_error ();
+    }
+}
+
+extern "C" void
+octave_jit_paren_subsasgn_matrix_range (jit_matrix *result, jit_matrix *mat,
+                                        jit_range *index, double value)
+{
+  NDArray *array = mat->array;
+  bool done = false;
+
+  // optimize for the simple case (no resizing and no errors)
+  if (*array->jit_ref_count () == 1
+      && index->all_elements_are_ints ())
+    {
+      // this code is similar to idx_vector::fill, but we avoid allocating an
+      // idx_vector and its associated rep
+      octave_idx_type start = static_cast<octave_idx_type> (index->base) - 1;
+      octave_idx_type step = static_cast<octave_idx_type> (index->inc);
+      octave_idx_type nelem = index->nelem;
+      octave_idx_type final = start + nelem * step;
+      if (step < 0)
+        {
+          step = -step;
+          std::swap (final, start);
+        }
+
+      if (start >= 0 && final < mat->slice_len)
+        {
+          done = true;
+
+          double *data = array->jit_slice_data ();
+          if (step == 1)
+            std::fill (data + start, data + start + nelem, value);
+          else
+            {
+              for (octave_idx_type i = start; i < final; i += step)
+                data[i] = value;
+            }
+        }
+    }
+
+  if (! done)
+    {
+      idx_vector idx (*index);
+      NDArray avalue (dim_vector (1, 1));
+      avalue.xelem (0) = value;
+      array->assign (idx, avalue);
+    }
+
+  result->update (array);
+}
+
+extern "C" Complex
+octave_jit_complex_div (Complex lhs, Complex rhs)
+{
+  // see src/OPERATORS/op-cs-cs.cc
+  if (rhs == 0.0)
+    gripe_divide_by_zero ();
+
+  return lhs / rhs;
+}
+
+// FIXME: CP form src/xpow.cc
+static inline int
+xisint (double x)
+{
+  return (D_NINT (x) == x
+          && ((x >= 0 && x < INT_MAX)
+              || (x <= 0 && x > INT_MIN)));
+}
+
+extern "C" Complex
+octave_jit_pow_scalar_scalar (double lhs, double rhs)
+{
+  // FIXME: almost CP from src/xpow.cc
+  if (lhs < 0.0 && ! xisint (rhs))
+    return std::pow (Complex (lhs), rhs);
+  return std::pow (lhs, rhs);
+}
+
+extern "C" Complex
+octave_jit_pow_complex_complex (Complex lhs, Complex rhs)
+{
+  if (lhs.imag () == 0 && rhs.imag () == 0)
+    return octave_jit_pow_scalar_scalar (lhs.real (), rhs.real ());
+  return std::pow (lhs, rhs);
+}
+
+extern "C" Complex
+octave_jit_pow_complex_scalar (Complex lhs, double rhs)
+{
+  if (lhs.imag () == 0)
+    return octave_jit_pow_scalar_scalar (lhs.real (), rhs);
+  return std::pow (lhs, rhs);
+}
+
+extern "C" Complex
+octave_jit_pow_scalar_complex (double lhs, Complex rhs)
+{
+  if (rhs.imag () == 0)
+    return octave_jit_pow_scalar_scalar (lhs, rhs.real ());
+  return std::pow (lhs, rhs);
+}
+
+extern "C" void
+octave_jit_print_matrix (jit_matrix *m)
+{
+  std::cout << *m << std::endl;
+}
+
+static void
+gripe_bad_result (void)
+{
+  error ("incorrect type information given to the JIT compiler");
+}
+
+// FIXME: Add support for multiple outputs
+extern "C" octave_base_value *
+octave_jit_call (octave_builtin::fcn fn, size_t nargin,
+                 octave_base_value **argin, jit_type *result_type)
+{
+  octave_value_list ovl (nargin);
+  for (size_t i = 0; i < nargin; ++i)
+    ovl.xelem (i) = octave_value (argin[i]);
+
+  ovl = fn (ovl, 1);
+
+  // These type checks are not strictly required, but I'm guessing that
+  // incorrect types will be entered on occasion. This will be very difficult to
+  // debug unless we do the sanity check here.
+  if (result_type)
+    {
+      if (ovl.length () != 1)
+        {
+          gripe_bad_result ();
+          return 0;
+        }
+
+      octave_value& result = ovl.xelem (0);
+      jit_type *jtype = jit_typeinfo::join (jit_typeinfo::type_of (result),
+                                            result_type);
+      if (jtype != result_type)
+        {
+          gripe_bad_result ();
+          return 0;
+        }
+
+      octave_base_value *ret = result.internal_rep ();
+      ret->grab ();
+      return ret;
+    }
+
+  if (! (ovl.length () == 0
+         || (ovl.length () == 1 && ovl.xelem (0).is_undefined ())))
+    gripe_bad_result ();
+
+  return 0;
+}
+
+// -------------------- jit_range --------------------
+bool
+jit_range::all_elements_are_ints () const
+{
+  Range r (*this);
+  return r.all_elements_are_ints ();
+}
+
+std::ostream&
+operator<< (std::ostream& os, const jit_range& rng)
+{
+  return os << "Range[" << rng.base << ", " << rng.limit << ", " << rng.inc
+            << ", " << rng.nelem << "]";
+}
+
+// -------------------- jit_matrix --------------------
+
+std::ostream&
+operator<< (std::ostream& os, const jit_matrix& mat)
+{
+  return os << "Matrix[" << mat.ref_count << ", " << mat.slice_data << ", "
+            << mat.slice_len << ", " << mat.dimensions << ", "
+            << mat.array << "]";
+}
+
+// -------------------- jit_type --------------------
+jit_type::jit_type (const std::string& aname, jit_type *aparent,
+                    llvm::Type *allvm_type, int aid) :
+  mname (aname), mparent (aparent), llvm_type (allvm_type), mid (aid),
+  mdepth (aparent ? aparent->mdepth + 1 : 0)
+{
+  std::memset (msret, 0, sizeof (msret));
+  std::memset (mpointer_arg, 0, sizeof (mpointer_arg));
+  std::memset (mpack, 0, sizeof (mpack));
+  std::memset (munpack, 0, sizeof (munpack));
+
+  for (size_t i = 0; i < jit_convention::length; ++i)
+    mpacked_type[i] = llvm_type;
+}
+
+llvm::Type *
+jit_type::to_llvm_arg (void) const
+{
+  return llvm_type ? llvm_type->getPointerTo () : 0;
+}
+
+// -------------------- jit_function --------------------
+jit_function::jit_function () : module (0), llvm_function (0), mresult (0),
+                                call_conv (jit_convention::length),
+                                mcan_error (false)
+{}
+
+jit_function::jit_function (llvm::Module *amodule,
+                            jit_convention::type acall_conv,
+                            const llvm::Twine& aname, jit_type *aresult,
+                            const std::vector<jit_type *>& aargs)
+  : module (amodule), mresult (aresult), args (aargs), call_conv (acall_conv),
+    mcan_error (false)
+{
+  llvm::SmallVector<llvm::Type *, 15> llvm_args;
+
+  llvm::Type *rtype = llvm::Type::getVoidTy (context);
+  if (mresult)
+    {
+      rtype = mresult->packed_type (call_conv);
+      if (sret ())
+        {
+          llvm_args.push_back (rtype->getPointerTo ());
+          rtype = llvm::Type::getVoidTy (context);
+        }
+    }
+
+  for (std::vector<jit_type *>::const_iterator iter = args.begin ();
+       iter != args.end (); ++iter)
+    {
+      jit_type *ty = *iter;
+      assert (ty);
+      llvm::Type *argty = ty->packed_type (call_conv);
+      if (ty->pointer_arg (call_conv))
+        argty = argty->getPointerTo ();
+
+      llvm_args.push_back (argty);
+    }
+
+  // we mark all functinos as external linkage because this prevents llvm
+  // from getting rid of always inline functions
+  llvm::FunctionType *ft = llvm::FunctionType::get (rtype, llvm_args, false);
+  llvm_function = llvm::Function::Create (ft, llvm::Function::ExternalLinkage,
+                                          aname, module);
+  if (call_conv == jit_convention::internal)
+    llvm_function->addFnAttr (llvm::Attribute::AlwaysInline);
+}
+
+jit_function::jit_function (const jit_function& fn, jit_type *aresult,
+                            const std::vector<jit_type *>& aargs)
+  : module (fn.module), llvm_function (fn.llvm_function), mresult (aresult),
+    args (aargs), call_conv (fn.call_conv), mcan_error (fn.mcan_error)
+{
+}
+
+jit_function::jit_function (const jit_function& fn)
+  : module (fn.module), llvm_function (fn.llvm_function), mresult (fn.mresult),
+    args (fn.args), call_conv (fn.call_conv), mcan_error (fn.mcan_error)
+{}
+
+std::string
+jit_function::name (void) const
+{
+  return llvm_function->getName ();
+}
+
+llvm::BasicBlock *
+jit_function::new_block (const std::string& aname,
+                         llvm::BasicBlock *insert_before)
+{
+  return llvm::BasicBlock::Create (context, aname, llvm_function,
+                                   insert_before);
+}
+
+llvm::Value *
+jit_function::call (llvm::IRBuilderD& builder,
+                    const std::vector<jit_value *>& in_args) const
+{
+  if (! valid ())
+    throw jit_fail_exception ("Call not implemented");
+
+  assert (in_args.size () == args.size ());
+  std::vector<llvm::Value *> llvm_args (args.size ());
+  for (size_t i = 0; i < in_args.size (); ++i)
+    llvm_args[i] = in_args[i]->to_llvm ();
+
+  return call (builder, llvm_args);
+}
+
+llvm::Value *
+jit_function::call (llvm::IRBuilderD& builder,
+                    const std::vector<llvm::Value *>& in_args) const
+{
+  if (! valid ())
+    throw jit_fail_exception ("Call not implemented");
+
+  assert (in_args.size () == args.size ());
+  llvm::Function *stacksave
+    = llvm::Intrinsic::getDeclaration (module, llvm::Intrinsic::stacksave);
+  llvm::SmallVector<llvm::Value *, 10> llvm_args;
+  llvm_args.reserve (in_args.size () + sret ());
+
+  llvm::Value *sret_mem = 0;
+  llvm::Value *saved_stack = 0;
+  if (sret ())
+    {
+      saved_stack = builder.CreateCall (stacksave);
+      sret_mem = builder.CreateAlloca (mresult->packed_type (call_conv));
+      llvm_args.push_back (sret_mem);
+    }
+
+  for (size_t i = 0; i < in_args.size (); ++i)
+    {
+      llvm::Value *arg = in_args[i];
+      jit_type::convert_fn convert = args[i]->pack (call_conv);
+      if (convert)
+        arg = convert (builder, arg);
+
+      if (args[i]->pointer_arg (call_conv))
+        {
+          if (! saved_stack)
+            saved_stack = builder.CreateCall (stacksave);
+
+          arg = builder.CreateAlloca (args[i]->to_llvm ());
+          builder.CreateStore (in_args[i], arg);
+        }
+
+      llvm_args.push_back (arg);
+    }
+
+  llvm::Value *ret = builder.CreateCall (llvm_function, llvm_args);
+  if (sret_mem)
+    ret = builder.CreateLoad (sret_mem);
+
+  if (mresult)
+    {
+      jit_type::convert_fn unpack = mresult->unpack (call_conv);
+      if (unpack)
+        ret = unpack (builder, ret);
+    }
+
+  if (saved_stack)
+    {
+      llvm::Function *stackrestore
+        = llvm::Intrinsic::getDeclaration (module,
+                                           llvm::Intrinsic::stackrestore);
+      builder.CreateCall (stackrestore, saved_stack);
+    }
+
+  return ret;
+}
+
+llvm::Value *
+jit_function::argument (llvm::IRBuilderD& builder, size_t idx) const
+{
+  assert (idx < args.size ());
+
+  // FIXME: We should be treating arguments like a list, not a vector. Shouldn't
+  // matter much for now, as the number of arguments shouldn't be much bigger
+  // than 4
+  llvm::Function::arg_iterator iter = llvm_function->arg_begin ();
+  if (sret ())
+    ++iter;
+
+  for (size_t i = 0; i < idx; ++i, ++iter);
+
+  if (args[idx]->pointer_arg (call_conv))
+    return builder.CreateLoad (iter);
+
+  return iter;
+}
+
+void
+jit_function::do_return (llvm::IRBuilderD& builder, llvm::Value *rval)
+{
+  assert (! rval == ! mresult);
+
+  if (rval)
+    {
+      jit_type::convert_fn convert = mresult->pack (call_conv);
+      if (convert)
+        rval = convert (builder, rval);
+
+      if (sret ())
+        builder.CreateStore (rval, llvm_function->arg_begin ());
+      else
+        builder.CreateRet (rval);
+    }
+  else
+    builder.CreateRetVoid ();
+
+  llvm::verifyFunction (*llvm_function);
+}
+
+void
+jit_function::do_add_mapping (llvm::ExecutionEngine *engine, void *fn)
+{
+  assert (valid ());
+  engine->addGlobalMapping (llvm_function, fn);
+}
+
+std::ostream&
+operator<< (std::ostream& os, const jit_function& fn)
+{
+  llvm::Function *lfn = fn.to_llvm ();
+  os << "jit_function: cc=" << fn.call_conv;
+  llvm::raw_os_ostream llvm_out (os);
+  lfn->print (llvm_out);
+  llvm_out.flush ();
+  return os;
+}
+
+// -------------------- jit_operation --------------------
+jit_operation::~jit_operation (void)
+{
+  for (generated_map::iterator iter = generated.begin ();
+       iter != generated.end (); ++iter)
+    {
+      delete iter->first;
+      delete iter->second;
+    }
+}
+
+void
+jit_operation::add_overload (const jit_function& func,
+                            const std::vector<jit_type*>& args)
+{
+  if (args.size () >= overloads.size ())
+    overloads.resize (args.size () + 1);
+
+  Array<jit_function>& over = overloads[args.size ()];
+  dim_vector dv (over.dims ());
+  Array<octave_idx_type> idx = to_idx (args);
+  bool must_resize = false;
+
+  if (dv.length () != idx.numel ())
+    {
+      dv.resize (idx.numel ());
+      must_resize = true;
+    }
+
+  for (octave_idx_type i = 0; i < dv.length (); ++i)
+    if (dv(i) <= idx(i))
+      {
+        must_resize = true;
+        dv(i) = idx(i) + 1;
+      }
+
+  if (must_resize)
+    over.resize (dv);
+
+  over(idx) = func;
+}
+
+const jit_function&
+jit_operation::overload (const std::vector<jit_type*>& types) const
+{
+  static jit_function null_overload;
+  for (size_t i  =0; i < types.size (); ++i)
+    if (! types[i])
+      return null_overload;
+
+  if (types.size () >= overloads.size ())
+    return do_generate (types);
+
+  const Array<jit_function>& over = overloads[types.size ()];
+  dim_vector dv (over.dims ());
+  Array<octave_idx_type> idx = to_idx (types);
+  for (octave_idx_type i = 0; i < dv.length (); ++i)
+    if (idx(i) >= dv(i))
+      return do_generate (types);
+
+  const jit_function& ret = over(idx);
+  if (! ret.valid ())
+    return do_generate (types);
+
+  return ret;
+}
+
+Array<octave_idx_type>
+jit_operation::to_idx (const std::vector<jit_type*>& types) const
+{
+  octave_idx_type numel = types.size ();
+  if (numel == 1)
+    numel = 2;
+
+  Array<octave_idx_type> idx (dim_vector (1, numel));
+  for (octave_idx_type i = 0; i < static_cast<octave_idx_type> (types.size ());
+       ++i)
+    idx(i) = types[i]->type_id ();
+
+  if (types.size () == 1)
+    {
+      idx(1) = idx(0);
+      idx(0) = 0;
+    }
+
+  return idx;
+}
+
+const jit_function&
+jit_operation::do_generate (const signature_vec& types) const
+{
+  static jit_function null_overload;
+  generated_map::const_iterator find = generated.find (&types);
+  if (find != generated.end ())
+    {
+      if (find->second)
+        return *find->second;
+      else
+        return null_overload;
+    }
+
+  jit_function *ret = generate (types);
+  generated[new signature_vec (types)] = ret;
+  return ret ? *ret : null_overload;
+}
+
+jit_function *
+jit_operation::generate (const signature_vec& types) const
+{
+  return 0;
+}
+
+bool
+jit_operation::signature_cmp
+::operator() (const signature_vec *lhs, const signature_vec *rhs)
+{
+  const signature_vec& l = *lhs;
+  const signature_vec& r = *rhs;
+
+  if (l.size () < r.size ())
+    return true;
+  else if (l.size () > r.size ())
+    return false;
+
+  for (size_t i = 0; i < l.size (); ++i)
+    {
+      if (l[i]->type_id () < r[i]->type_id ())
+        return true;
+      else if (l[i]->type_id () > r[i]->type_id ())
+        return false;
+    }
+
+  return false;
+}
+
+// -------------------- jit_index_operation --------------------
+jit_function *
+jit_index_operation::generate (const signature_vec& types) const
+{
+  if (types.size () > 2 && types[0] == jit_typeinfo::get_matrix ())
+    {
+      // indexing a matrix with scalars
+      jit_type *scalar = jit_typeinfo::get_scalar ();
+      for (size_t i = 1; i < types.size (); ++i)
+        if (types[i] != scalar)
+          return 0;
+
+      return generate_matrix (types);
+    }
+
+  return 0;
+}
+
+llvm::Value *
+jit_index_operation::create_arg_array (llvm::IRBuilderD& builder,
+                                       const jit_function &fn, size_t start_idx,
+                                       size_t end_idx) const
+{
+  size_t n = end_idx - start_idx;
+  llvm::Type *scalar_t = jit_typeinfo::get_scalar_llvm ();
+  llvm::ArrayType *array_t = llvm::ArrayType::get (scalar_t, n);
+  llvm::Value *array = llvm::UndefValue::get (array_t);
+  for (size_t i = start_idx; i < end_idx; ++i)
+    {
+      llvm::Value *idx = fn.argument (builder, i);
+      array = builder.CreateInsertValue (array, idx, i - start_idx);
+    }
+
+  llvm::Value *array_mem = builder.CreateAlloca (array_t);
+  builder.CreateStore (array, array_mem);
+  return builder.CreateBitCast (array_mem, scalar_t->getPointerTo ());
+}
+
+// -------------------- jit_paren_subsref --------------------
+jit_function *
+jit_paren_subsref::generate_matrix (const signature_vec& types) const
+{
+  std::stringstream ss;
+  ss << "jit_paren_subsref_matrix_scalar" << (types.size () - 1);
+
+  jit_type *scalar = jit_typeinfo::get_scalar ();
+  jit_function *fn = new jit_function (module, jit_convention::internal,
+                                       ss.str (), scalar, types);
+  fn->mark_can_error ();
+  llvm::BasicBlock *body = fn->new_block ();
+  llvm::IRBuilder<> builder (body);
+
+  llvm::Value *array = create_arg_array (builder, *fn, 1, types.size ());
+  jit_type *index = jit_typeinfo::get_index ();
+  llvm::Value *nelem = llvm::ConstantInt::get (index->to_llvm (),
+                                               types.size () - 1);
+  llvm::Value *mat = fn->argument (builder, 0);
+  llvm::Value *ret = paren_scalar.call (builder, mat, array, nelem);
+  fn->do_return (builder, ret);
+  return fn;
+}
+
+void
+jit_paren_subsref::do_initialize (void)
+{
+  std::vector<jit_type *> types (3);
+  types[0] = jit_typeinfo::get_matrix ();
+  types[1] = jit_typeinfo::get_scalar_ptr ();
+  types[2] = jit_typeinfo::get_index ();
+
+  jit_type *scalar = jit_typeinfo::get_scalar ();
+  paren_scalar = jit_function (module, jit_convention::external,
+                               "octave_jit_paren_scalar", scalar, types);
+  paren_scalar.add_mapping (engine, &octave_jit_paren_scalar);
+  paren_scalar.mark_can_error ();
+}
+
+// -------------------- jit_paren_subsasgn --------------------
+jit_function *
+jit_paren_subsasgn::generate_matrix (const signature_vec& types) const
+{
+  std::stringstream ss;
+  ss << "jit_paren_subsasgn_matrix_scalar" << (types.size () - 2);
+
+  jit_type *matrix = jit_typeinfo::get_matrix ();
+  jit_function *fn = new jit_function (module, jit_convention::internal,
+                                       ss.str (), matrix, types);
+  fn->mark_can_error ();
+  llvm::BasicBlock *body = fn->new_block ();
+  llvm::IRBuilder<> builder (body);
+
+  llvm::Value *array = create_arg_array (builder, *fn, 1, types.size () - 1);
+  jit_type *index = jit_typeinfo::get_index ();
+  llvm::Value *nelem = llvm::ConstantInt::get (index->to_llvm (),
+                                               types.size () - 2);
+
+  llvm::Value *mat = fn->argument (builder, 0);
+  llvm::Value *value = fn->argument (builder, types.size () - 1);
+  llvm::Value *ret = paren_scalar.call (builder, mat, array, nelem, value);
+  fn->do_return (builder, ret);
+  return fn;
+}
+
+void
+jit_paren_subsasgn::do_initialize (void)
+{
+  if (paren_scalar.valid ())
+    return;
+
+  jit_type *matrix = jit_typeinfo::get_matrix ();
+  std::vector<jit_type *> types (4);
+  types[0] = matrix;
+  types[1] = jit_typeinfo::get_scalar_ptr ();
+  types[2] = jit_typeinfo::get_index ();
+  types[3] = jit_typeinfo::get_scalar ();
+
+  paren_scalar = jit_function (module, jit_convention::external,
+                               "octave_jit_paren_scalar", matrix, types);
+  paren_scalar.add_mapping (engine, &octave_jit_paren_scalar_subsasgn);
+  paren_scalar.mark_can_error ();
+}
+
+// -------------------- jit_typeinfo --------------------
+void
+jit_typeinfo::initialize (llvm::Module *m, llvm::ExecutionEngine *e)
+{
+  new jit_typeinfo (m, e);
+}
+
+jit_typeinfo::jit_typeinfo (llvm::Module *m, llvm::ExecutionEngine *e)
+  : module (m), engine (e), next_id (0),
+    builder (*new llvm::IRBuilderD (context))
+{
+  instance = this;
+
+  // FIXME: We should be registering types like in octave_value_typeinfo
+  llvm::Type *any_t = llvm::StructType::create (context, "octave_base_value");
+  any_t = any_t->getPointerTo ();
+
+  llvm::Type *scalar_t = llvm::Type::getDoubleTy (context);
+  llvm::Type *bool_t = llvm::Type::getInt1Ty (context);
+  llvm::Type *string_t = llvm::Type::getInt8Ty (context);
+  string_t = string_t->getPointerTo ();
+  llvm::Type *index_t = llvm::Type::getIntNTy (context,
+                                               sizeof(octave_idx_type) * 8);
+
+  llvm::StructType *range_t = llvm::StructType::create (context, "range");
+  std::vector<llvm::Type *> range_contents (4, scalar_t);
+  range_contents[3] = index_t;
+  range_t->setBody (range_contents);
+
+  llvm::Type *refcount_t = llvm::Type::getIntNTy (context, sizeof(int) * 8);
+
+  llvm::StructType *matrix_t = llvm::StructType::create (context, "matrix");
+  llvm::Type *matrix_contents[5];
+  matrix_contents[0] = refcount_t->getPointerTo ();
+  matrix_contents[1] = scalar_t->getPointerTo ();
+  matrix_contents[2] = index_t;
+  matrix_contents[3] = index_t->getPointerTo ();
+  matrix_contents[4] = string_t;
+  matrix_t->setBody (llvm::makeArrayRef (matrix_contents, 5));
+
+  llvm::Type *complex_t = llvm::VectorType::get (scalar_t, 2);
+
+  // complex_ret is what is passed to C functions in order to get calling
+  // convention right
+  complex_ret = llvm::StructType::create (context, "complex_ret");
+  llvm::Type *complex_ret_contents[] = {scalar_t, scalar_t};
+  complex_ret->setBody (complex_ret_contents);
+
+  // create types
+  any = new_type ("any", 0, any_t);
+  matrix = new_type ("matrix", any, matrix_t);
+  complex = new_type ("complex", any, complex_t);
+  scalar = new_type ("scalar", complex, scalar_t);
+  scalar_ptr = new_type ("scalar_ptr", 0, scalar_t->getPointerTo ());
+  range = new_type ("range", any, range_t);
+  string = new_type ("string", any, string_t);
+  boolean = new_type ("bool", any, bool_t);
+  index = new_type ("index", any, index_t);
+
+  create_int (8);
+  create_int (16);
+  create_int (32);
+  create_int (64);
+
+  casts.resize (next_id + 1);
+  identities.resize (next_id + 1);
+
+  // specify calling conventions
+  // FIXME: We should detect architecture and do something sane based on that
+  // here we assume x86 or x86_64
+  matrix->mark_sret ();
+  matrix->mark_pointer_arg ();
+
+  range->mark_sret ();
+  range->mark_pointer_arg ();
+
+  complex->set_pack (jit_convention::external, &jit_typeinfo::pack_complex);
+  complex->set_unpack (jit_convention::external, &jit_typeinfo::unpack_complex);
+  complex->set_packed_type (jit_convention::external, complex_ret);
+
+  if (sizeof (void *) == 4)
+    complex->mark_sret ();
+
+  paren_subsref_fn.initialize (module, engine);
+  paren_subsasgn_fn.initialize (module, engine);
+
+  // bind global variables
+  lerror_state = new llvm::GlobalVariable (*module, bool_t, false,
+                                           llvm::GlobalValue::ExternalLinkage,
+                                           0, "error_state");
+  engine->addGlobalMapping (lerror_state,
+                            reinterpret_cast<void *> (&error_state));
+
+  // any with anything is an any op
+  jit_function fn;
+  jit_type *binary_op_type = intN (sizeof (octave_value::binary_op) * 8);
+  llvm::Type *llvm_bo_type = binary_op_type->to_llvm ();
+  jit_function any_binary = create_function (jit_convention::external,
+                                             "octave_jit_binary_any_any",
+                                             any, binary_op_type, any, any);
+  any_binary.add_mapping (engine, &octave_jit_binary_any_any);
+  any_binary.mark_can_error ();
+  binary_ops.resize (octave_value::num_binary_ops);
+  for (size_t i = 0; i < octave_value::num_binary_ops; ++i)
+    {
+      octave_value::binary_op op = static_cast<octave_value::binary_op> (i);
+      std::string op_name = octave_value::binary_op_as_string (op);
+      binary_ops[i].stash_name ("binary" + op_name);
+    }
+
+  for (int op = 0; op < octave_value::num_binary_ops; ++op)
+    {
+      llvm::Twine fn_name ("octave_jit_binary_any_any_");
+      fn_name = fn_name + llvm::Twine (op);
+
+      fn = create_function (jit_convention::internal, fn_name, any, any, any);
+      fn.mark_can_error ();
+      llvm::BasicBlock *block = fn.new_block ();
+      builder.SetInsertPoint (block);
+      llvm::APInt op_int(sizeof (octave_value::binary_op) * 8, op,
+                         std::numeric_limits<octave_value::binary_op>::is_signed);
+      llvm::Value *op_as_llvm = llvm::ConstantInt::get (llvm_bo_type, op_int);
+      llvm::Value *ret = any_binary.call (builder, op_as_llvm,
+                                          fn.argument (builder, 0),
+                                          fn.argument (builder, 1));
+      fn.do_return (builder, ret);
+      binary_ops[op].add_overload (fn);
+    }
+
+  // grab any
+  fn = create_function (jit_convention::external, "octave_jit_grab_any", any,
+                        any);
+  fn.add_mapping (engine, &octave_jit_grab_any);
+  grab_fn.add_overload (fn);
+  grab_fn.stash_name ("grab");
+
+  // grab matrix
+  fn = create_function (jit_convention::external, "octave_jit_grab_matrix",
+                        matrix, matrix);
+  fn.add_mapping (engine, &octave_jit_grab_matrix);
+  grab_fn.add_overload (fn);
+
+  // release any
+  fn = create_function (jit_convention::external, "octave_jit_release_any", 0,
+                        any);
+  fn.add_mapping (engine, &octave_jit_release_any);
+  release_fn.add_overload (fn);
+  release_fn.stash_name ("release");
+
+  // release matrix
+  fn = create_function (jit_convention::external, "octave_jit_release_matrix",
+                        0, matrix);
+  fn.add_mapping (engine, &octave_jit_release_matrix);
+  release_fn.add_overload (fn);
+
+  // release scalar
+  fn = create_identity (scalar);
+  release_fn.add_overload (fn);
+
+  // release complex
+  fn = create_identity (complex);
+  release_fn.add_overload (fn);
+
+  // release index
+  fn = create_identity (index);
+  release_fn.add_overload (fn);
+
+  // now for binary scalar operations
+  // FIXME: Finish all operations
+  add_binary_op (scalar, octave_value::op_add, llvm::Instruction::FAdd);
+  add_binary_op (scalar, octave_value::op_sub, llvm::Instruction::FSub);
+  add_binary_op (scalar, octave_value::op_mul, llvm::Instruction::FMul);
+  add_binary_op (scalar, octave_value::op_el_mul, llvm::Instruction::FMul);
+
+  add_binary_fcmp (scalar, octave_value::op_lt, llvm::CmpInst::FCMP_ULT);
+  add_binary_fcmp (scalar, octave_value::op_le, llvm::CmpInst::FCMP_ULE);
+  add_binary_fcmp (scalar, octave_value::op_eq, llvm::CmpInst::FCMP_UEQ);
+  add_binary_fcmp (scalar, octave_value::op_ge, llvm::CmpInst::FCMP_UGE);
+  add_binary_fcmp (scalar, octave_value::op_gt, llvm::CmpInst::FCMP_UGT);
+  add_binary_fcmp (scalar, octave_value::op_ne, llvm::CmpInst::FCMP_UNE);
+
+  jit_function gripe_div0 = create_function (jit_convention::external,
+                                             "gripe_divide_by_zero", 0);
+  gripe_div0.add_mapping (engine, &gripe_divide_by_zero);
+  gripe_div0.mark_can_error ();
+
+  // divide is annoying because it might error
+  fn = create_function (jit_convention::internal,
+                        "octave_jit_div_scalar_scalar", scalar, scalar, scalar);
+  fn.mark_can_error ();
+
+  llvm::BasicBlock *body = fn.new_block ();
+  builder.SetInsertPoint (body);
+  {
+    llvm::BasicBlock *warn_block = fn.new_block ("warn");
+    llvm::BasicBlock *normal_block = fn.new_block ("normal");
+
+    llvm::Value *zero = llvm::ConstantFP::get (scalar_t, 0);
+    llvm::Value *check = builder.CreateFCmpUEQ (zero, fn.argument (builder, 1));
+    builder.CreateCondBr (check, warn_block, normal_block);
+
+    builder.SetInsertPoint (warn_block);
+    gripe_div0.call (builder);
+    builder.CreateBr (normal_block);
+
+    builder.SetInsertPoint (normal_block);
+    llvm::Value *ret = builder.CreateFDiv (fn.argument (builder, 0),
+                                           fn.argument (builder, 1));
+    fn.do_return (builder, ret);
+  }
+  binary_ops[octave_value::op_div].add_overload (fn);
+  binary_ops[octave_value::op_el_div].add_overload (fn);
+
+  // ldiv is the same as div with the operators reversed
+  fn = mirror_binary (fn);
+  binary_ops[octave_value::op_ldiv].add_overload (fn);
+  binary_ops[octave_value::op_el_ldiv].add_overload (fn);
+
+  // In general, the result of scalar ^ scalar is a complex number. We might be
+  // able to improve on this if we keep track of the range of values varaibles
+  // can take on.
+  fn = create_function (jit_convention::external,
+                        "octave_jit_pow_scalar_scalar", complex, scalar,
+                        scalar);
+  fn.add_mapping (engine, &octave_jit_pow_scalar_scalar);
+  binary_ops[octave_value::op_pow].add_overload (fn);
+  binary_ops[octave_value::op_el_pow].add_overload (fn);
+
+  // now for binary complex operations
+  add_binary_op (complex, octave_value::op_add, llvm::Instruction::FAdd);
+  add_binary_op (complex, octave_value::op_sub, llvm::Instruction::FSub);
+
+  fn = create_function (jit_convention::internal,
+                        "octave_jit_*_complex_complex", complex, complex,
+                        complex);
+  body = fn.new_block ();
+  builder.SetInsertPoint (body);
+  {
+    // (x0*x1 - y0*y1, x0*y1 + y0*x1) = (x0,y0) * (x1,y1)
+    // We compute this in one vectorized multiplication, a subtraction, and an
+    // addition.
+    llvm::Value *lhs = fn.argument (builder, 0);
+    llvm::Value *rhs = fn.argument (builder, 1);
+
+    // FIXME: We need a better way of doing this, working with llvm's IR
+    // directly is sort of a pain.
+    llvm::Value *zero = builder.getInt32 (0);
+    llvm::Value *one = builder.getInt32 (1);
+    llvm::Value *two = builder.getInt32 (2);
+    llvm::Value *three = builder.getInt32 (3);
+
+    llvm::Type *vec4 = llvm::VectorType::get (scalar_t, 4);
+    llvm::Value *mlhs = llvm::UndefValue::get (vec4);
+    llvm::Value *mrhs = mlhs;
+
+    llvm::Value *temp = complex_real (lhs);
+    mlhs = builder.CreateInsertElement (mlhs, temp, zero);
+    mlhs = builder.CreateInsertElement (mlhs, temp, two);
+    temp = complex_imag (lhs);
+    mlhs = builder.CreateInsertElement (mlhs, temp, one);
+    mlhs = builder.CreateInsertElement (mlhs, temp, three);
+
+    temp = complex_real (rhs);
+    mrhs = builder.CreateInsertElement (mrhs, temp, zero);
+    mrhs = builder.CreateInsertElement (mrhs, temp, three);
+    temp = complex_imag (rhs);
+    mrhs = builder.CreateInsertElement (mrhs, temp, one);
+    mrhs = builder.CreateInsertElement (mrhs, temp, two);
+
+    llvm::Value *mres = builder.CreateFMul (mlhs, mrhs);
+    llvm::Value *tlhs = builder.CreateExtractElement (mres, zero);
+    llvm::Value *trhs = builder.CreateExtractElement (mres, one);
+    llvm::Value *ret_real = builder.CreateFSub (tlhs, trhs);
+
+    tlhs = builder.CreateExtractElement (mres, two);
+    trhs = builder.CreateExtractElement (mres, three);
+    llvm::Value *ret_imag = builder.CreateFAdd (tlhs, trhs);
+    fn.do_return (builder, complex_new (ret_real, ret_imag));
+  }
+
+  binary_ops[octave_value::op_mul].add_overload (fn);
+  binary_ops[octave_value::op_el_mul].add_overload (fn);
+
+  jit_function complex_div = create_function (jit_convention::external,
+                                              "octave_jit_complex_div",
+                                              complex, complex, complex);
+  complex_div.add_mapping (engine, &octave_jit_complex_div);
+  complex_div.mark_can_error ();
+  binary_ops[octave_value::op_div].add_overload (fn);
+  binary_ops[octave_value::op_ldiv].add_overload (fn);
+
+  fn = mirror_binary (complex_div);
+  binary_ops[octave_value::op_ldiv].add_overload (fn);
+  binary_ops[octave_value::op_el_ldiv].add_overload (fn);
+
+  fn = create_function (jit_convention::external,
+                        "octave_jit_pow_complex_complex", complex, complex,
+                        complex);
+  fn.add_mapping (engine, &octave_jit_pow_complex_complex);
+  binary_ops[octave_value::op_pow].add_overload (fn);
+  binary_ops[octave_value::op_el_pow].add_overload (fn);
+
+  fn = create_function (jit_convention::internal,
+                        "octave_jit_*_scalar_complex", complex, scalar,
+                        complex);
+  jit_function mul_scalar_complex = fn;
+  body = fn.new_block ();
+  builder.SetInsertPoint (body);
+  {
+    llvm::Value *lhs = fn.argument (builder, 0);
+    llvm::Value *tlhs = complex_new (lhs, lhs);
+    llvm::Value *rhs = fn.argument (builder, 1);
+    fn.do_return (builder, builder.CreateFMul (tlhs, rhs));
+  }
+  binary_ops[octave_value::op_mul].add_overload (fn);
+  binary_ops[octave_value::op_el_mul].add_overload (fn);
+
+
+  fn = mirror_binary (mul_scalar_complex);
+  binary_ops[octave_value::op_mul].add_overload (fn);
+  binary_ops[octave_value::op_el_mul].add_overload (fn);
+
+  fn = create_function (jit_convention::internal, "octave_jit_+_scalar_complex",
+                        complex, scalar, complex);
+  body = fn.new_block ();
+  builder.SetInsertPoint (body);
+  {
+    llvm::Value *lhs = fn.argument (builder, 0);
+    llvm::Value *rhs = fn.argument (builder, 1);
+    llvm::Value *real = builder.CreateFAdd (lhs, complex_real (rhs));
+    fn.do_return (builder, complex_real (rhs, real));
+  }
+  binary_ops[octave_value::op_add].add_overload (fn);
+
+  fn = mirror_binary (fn);
+  binary_ops[octave_value::op_add].add_overload (fn);
+
+  fn = create_function (jit_convention::internal, "octave_jit_-_complex_scalar",
+                        complex, complex, scalar);
+  body = fn.new_block ();
+  builder.SetInsertPoint (body);
+  {
+    llvm::Value *lhs = fn.argument (builder, 0);
+    llvm::Value *rhs = fn.argument (builder, 1);
+    llvm::Value *real = builder.CreateFSub (complex_real (lhs), rhs);
+    fn.do_return (builder, complex_real (lhs, real));
+  }
+  binary_ops[octave_value::op_sub].add_overload (fn);
+
+  fn = create_function (jit_convention::internal, "octave_jit_-_scalar_complex",
+                        complex, scalar, complex);
+  body = fn.new_block ();
+  builder.SetInsertPoint (body);
+  {
+    llvm::Value *lhs = fn.argument (builder, 0);
+    llvm::Value *rhs = fn.argument (builder, 1);
+    llvm::Value *real = builder.CreateFSub (lhs, complex_real (rhs));
+    fn.do_return (builder, complex_real (rhs, real));
+  }
+  binary_ops[octave_value::op_sub].add_overload (fn);
+
+  fn = create_function (jit_convention::external,
+                        "octave_jit_pow_scalar_complex", complex, scalar,
+                        complex);
+  fn.add_mapping (engine, &octave_jit_pow_scalar_complex);
+  binary_ops[octave_value::op_pow].add_overload (fn);
+  binary_ops[octave_value::op_el_pow].add_overload (fn);
+
+  fn = create_function (jit_convention::external,
+                        "octave_jit_pow_complex_scalar", complex, complex,
+                        scalar);
+  fn.add_mapping (engine, &octave_jit_pow_complex_scalar);
+  binary_ops[octave_value::op_pow].add_overload (fn);
+  binary_ops[octave_value::op_el_pow].add_overload (fn);
+
+  // now for binary index operators
+  add_binary_op (index, octave_value::op_add, llvm::Instruction::Add);
+
+  // and binary bool operators
+  add_binary_op (boolean, octave_value::op_el_or, llvm::Instruction::Or);
+  add_binary_op (boolean, octave_value::op_el_and, llvm::Instruction::And);
+
+  // now for printing functions
+  print_fn.stash_name ("print");
+  add_print (any, reinterpret_cast<void *> (&octave_jit_print_any));
+  add_print (scalar, reinterpret_cast<void *> (&octave_jit_print_scalar));
+
+  // initialize for loop
+  for_init_fn.stash_name ("for_init");
+
+  fn = create_function (jit_convention::internal, "octave_jit_for_range_init",
+                        index, range);
+  body = fn.new_block ();
+  builder.SetInsertPoint (body);
+  {
+    llvm::Value *zero = llvm::ConstantInt::get (index_t, 0);
+    fn.do_return (builder, zero);
+  }
+  for_init_fn.add_overload (fn);
+
+  // bounds check for for loop
+  for_check_fn.stash_name ("for_check");
+
+  fn = create_function (jit_convention::internal, "octave_jit_for_range_check",
+                        boolean, range, index);
+  body = fn.new_block ();
+  builder.SetInsertPoint (body);
+  {
+    llvm::Value *nelem
+      = builder.CreateExtractValue (fn.argument (builder, 0), 3);
+    llvm::Value *idx = fn.argument (builder, 1);
+    llvm::Value *ret = builder.CreateICmpULT (idx, nelem);
+    fn.do_return (builder, ret);
+  }
+  for_check_fn.add_overload (fn);
+
+  // index variabe for for loop
+  for_index_fn.stash_name ("for_index");
+
+  fn = create_function (jit_convention::internal, "octave_jit_for_range_idx",
+                        scalar, range, index);
+  body = fn.new_block ();
+  builder.SetInsertPoint (body);
+  {
+    llvm::Value *idx = fn.argument (builder, 1);
+    llvm::Value *didx = builder.CreateSIToFP (idx, scalar_t);
+    llvm::Value *rng = fn.argument (builder, 0);
+    llvm::Value *base = builder.CreateExtractValue (rng, 0);
+    llvm::Value *inc = builder.CreateExtractValue (rng, 2);
+
+    llvm::Value *ret = builder.CreateFMul (didx, inc);
+    ret = builder.CreateFAdd (base, ret);
+    fn.do_return (builder, ret);
+  }
+  for_index_fn.add_overload (fn);
+
+  // logically true
+  logically_true_fn.stash_name ("logically_true");
+
+  jit_function gripe_nantl
+    = create_function (jit_convention::external,
+                       "octave_jit_gripe_nan_to_logical_conversion", 0);
+  gripe_nantl.add_mapping (engine, &octave_jit_gripe_nan_to_logical_conversion);
+  gripe_nantl.mark_can_error ();
+
+  fn = create_function (jit_convention::internal,
+                        "octave_jit_logically_true_scalar", boolean, scalar);
+  fn.mark_can_error ();
+
+  body = fn.new_block ();
+  builder.SetInsertPoint (body);
+  {
+    llvm::BasicBlock *error_block = fn.new_block ("error");
+    llvm::BasicBlock *normal_block = fn.new_block ("normal");
+
+    llvm::Value *check = builder.CreateFCmpUNE (fn.argument (builder, 0),
+                                                fn.argument (builder, 0));
+    builder.CreateCondBr (check, error_block, normal_block);
+
+    builder.SetInsertPoint (error_block);
+    gripe_nantl.call (builder);
+    builder.CreateBr (normal_block);
+    builder.SetInsertPoint (normal_block);
+
+    llvm::Value *zero = llvm::ConstantFP::get (scalar_t, 0);
+    llvm::Value *ret = builder.CreateFCmpONE (fn.argument (builder, 0), zero);
+    fn.do_return (builder, ret);
+  }
+  logically_true_fn.add_overload (fn);
+
+  // logically_true boolean
+  fn = create_identity (boolean);
+  logically_true_fn.add_overload (fn);
+
+  // make_range
+  // FIXME: May be benificial to implement all in LLVM
+  make_range_fn.stash_name ("make_range");
+  jit_function compute_nelem
+    = create_function (jit_convention::external, "octave_jit_compute_nelem",
+                       index, scalar, scalar, scalar);
+  compute_nelem.add_mapping (engine, &octave_jit_compute_nelem);
+
+  fn = create_function (jit_convention::internal, "octave_jit_make_range",
+                        range, scalar, scalar, scalar);
+  body = fn.new_block ();
+  builder.SetInsertPoint (body);
+  {
+    llvm::Value *base = fn.argument (builder, 0);
+    llvm::Value *limit = fn.argument (builder, 1);
+    llvm::Value *inc = fn.argument (builder, 2);
+    llvm::Value *nelem = compute_nelem.call (builder, base, limit, inc);
+
+    llvm::Value *dzero = llvm::ConstantFP::get (scalar_t, 0);
+    llvm::Value *izero = llvm::ConstantInt::get (index_t, 0);
+    llvm::Value *rng = llvm::ConstantStruct::get (range_t, dzero, dzero, dzero,
+                                                  izero, NULL);
+    rng = builder.CreateInsertValue (rng, base, 0);
+    rng = builder.CreateInsertValue (rng, limit, 1);
+    rng = builder.CreateInsertValue (rng, inc, 2);
+    rng = builder.CreateInsertValue (rng, nelem, 3);
+    fn.do_return (builder, rng);
+  }
+  make_range_fn.add_overload (fn);
+
+  // paren_subsref
+  jit_type *jit_int = intN (sizeof (int) * 8);
+  llvm::Type *int_t = jit_int->to_llvm ();
+  jit_function ginvalid_index
+    = create_function (jit_convention::external, "octave_jit_ginvalid_index",
+                       0);
+  ginvalid_index.add_mapping (engine, &octave_jit_ginvalid_index);
+  jit_function gindex_range = create_function (jit_convention::external,
+                                               "octave_jit_gindex_range",
+                                               0, jit_int, jit_int, index,
+                                               index);
+  gindex_range.add_mapping (engine, &octave_jit_gindex_range);
+
+  fn = create_function (jit_convention::internal, "()subsref", scalar, matrix,
+                        scalar);
+  fn.mark_can_error ();
+
+  body = fn.new_block ();
+  builder.SetInsertPoint (body);
+  {
+    llvm::Value *one = llvm::ConstantInt::get (index_t, 1);
+    llvm::Value *ione;
+    if (index_t == int_t)
+      ione = one;
+    else
+      ione = llvm::ConstantInt::get (int_t, 1);
+
+    llvm::Value *undef = llvm::UndefValue::get (scalar_t);
+    llvm::Value *mat = fn.argument (builder, 0);
+    llvm::Value *idx = fn.argument (builder, 1);
+
+    // convert index to scalar to integer, and check index >= 1
+    llvm::Value *int_idx = builder.CreateFPToSI (idx, index_t);
+    llvm::Value *check_idx = builder.CreateSIToFP (int_idx, scalar_t);
+    llvm::Value *cond0 = builder.CreateFCmpUNE (idx, check_idx);
+    llvm::Value *cond1 = builder.CreateICmpSLT (int_idx, one);
+    llvm::Value *cond = builder.CreateOr (cond0, cond1);
+
+    llvm::BasicBlock *done = fn.new_block ("done");
+    llvm::BasicBlock *conv_error = fn.new_block ("conv_error", done);
+    llvm::BasicBlock *normal = fn.new_block ("normal", done);
+    builder.CreateCondBr (cond, conv_error, normal);
+
+    builder.SetInsertPoint (conv_error);
+    ginvalid_index.call (builder);
+    builder.CreateBr (done);
+
+    builder.SetInsertPoint (normal);
+    llvm::Value *len = builder.CreateExtractValue (mat,
+                                                   llvm::ArrayRef<unsigned> (2));
+    cond = builder.CreateICmpSGT (int_idx, len);
+
+
+    llvm::BasicBlock *bounds_error = fn.new_block ("bounds_error", done);
+    llvm::BasicBlock *success = fn.new_block ("success", done);
+    builder.CreateCondBr (cond, bounds_error, success);
+
+    builder.SetInsertPoint (bounds_error);
+    gindex_range.call (builder, ione, ione, int_idx, len);
+    builder.CreateBr (done);
+
+    builder.SetInsertPoint (success);
+    llvm::Value *data = builder.CreateExtractValue (mat,
+                                                    llvm::ArrayRef<unsigned> (1));
+    llvm::Value *gep = builder.CreateInBoundsGEP (data, int_idx);
+    llvm::Value *ret = builder.CreateLoad (gep);
+    builder.CreateBr (done);
+
+    builder.SetInsertPoint (done);
+
+    llvm::PHINode *merge = llvm::PHINode::Create (scalar_t, 3);
+    builder.Insert (merge);
+    merge->addIncoming (undef, conv_error);
+    merge->addIncoming (undef, bounds_error);
+    merge->addIncoming (ret, success);
+    fn.do_return (builder, merge);
+  }
+  paren_subsref_fn.add_overload (fn);
+
+  // paren subsasgn
+  paren_subsasgn_fn.stash_name ("()subsasgn");
+
+  jit_function resize_paren_subsasgn
+    = create_function (jit_convention::external,
+                       "octave_jit_paren_subsasgn_impl", matrix, matrix, index,
+                       scalar);
+  resize_paren_subsasgn.add_mapping (engine, &octave_jit_paren_subsasgn_impl);
+  fn = create_function (jit_convention::internal, "octave_jit_paren_subsasgn",
+                        matrix, matrix, scalar, scalar);
+  fn.mark_can_error ();
+  body = fn.new_block ();
+  builder.SetInsertPoint (body);
+  {
+    llvm::Value *one = llvm::ConstantInt::get (index_t, 1);
+
+    llvm::Value *mat = fn.argument (builder, 0);
+    llvm::Value *idx = fn.argument (builder, 1);
+    llvm::Value *value = fn.argument (builder, 2);
+
+    llvm::Value *int_idx = builder.CreateFPToSI (idx, index_t);
+    llvm::Value *check_idx = builder.CreateSIToFP (int_idx, scalar_t);
+    llvm::Value *cond0 = builder.CreateFCmpUNE (idx, check_idx);
+    llvm::Value *cond1 = builder.CreateICmpSLT (int_idx, one);
+    llvm::Value *cond = builder.CreateOr (cond0, cond1);
+
+    llvm::BasicBlock *done = fn.new_block ("done");
+
+    llvm::BasicBlock *conv_error = fn.new_block ("conv_error", done);
+    llvm::BasicBlock *normal = fn.new_block ("normal", done);
+    builder.CreateCondBr (cond, conv_error, normal);
+    builder.SetInsertPoint (conv_error);
+    ginvalid_index.call (builder);
+    builder.CreateBr (done);
+
+    builder.SetInsertPoint (normal);
+    llvm::Value *len = builder.CreateExtractValue (mat, 2);
+    cond0 = builder.CreateICmpSGT (int_idx, len);
+
+    llvm::Value *rcount = builder.CreateExtractValue (mat, 0);
+    rcount = builder.CreateLoad (rcount);
+    cond1 = builder.CreateICmpSGT (rcount, one);
+    cond = builder.CreateOr (cond0, cond1);
+
+    llvm::BasicBlock *bounds_error = fn.new_block ("bounds_error", done);
+    llvm::BasicBlock *success = fn.new_block ("success", done);
+    builder.CreateCondBr (cond, bounds_error, success);
+
+    // resize on out of bounds access
+    builder.SetInsertPoint (bounds_error);
+    llvm::Value *resize_result = resize_paren_subsasgn.call (builder, mat,
+                                                             int_idx, value);
+    builder.CreateBr (done);
+
+    builder.SetInsertPoint (success);
+    llvm::Value *data = builder.CreateExtractValue (mat,
+                                                    llvm::ArrayRef<unsigned> (1));
+    llvm::Value *gep = builder.CreateInBoundsGEP (data, int_idx);
+    builder.CreateStore (value, gep);
+    builder.CreateBr (done);
+
+    builder.SetInsertPoint (done);
+
+    llvm::PHINode *merge = llvm::PHINode::Create (matrix_t, 3);
+    builder.Insert (merge);
+    merge->addIncoming (mat, conv_error);
+    merge->addIncoming (resize_result, bounds_error);
+    merge->addIncoming (mat, success);
+    fn.do_return (builder, merge);
+  }
+  paren_subsasgn_fn.add_overload (fn);
+
+  fn = create_function (jit_convention::external,
+                        "octave_jit_paren_subsasgn_matrix_range", matrix,
+                        matrix, range, scalar);
+  fn.add_mapping (engine, &octave_jit_paren_subsasgn_matrix_range);
+  fn.mark_can_error ();
+  paren_subsasgn_fn.add_overload (fn);
+
+  end_fn.stash_name ("end");
+  fn = create_function (jit_convention::internal, "octave_jit_end_matrix",
+                        scalar, matrix);
+  body = fn.new_block ();
+  builder.SetInsertPoint (body);
+  {
+    llvm::Value *mat = fn.argument (builder, 0);
+    llvm::Value *ret = builder.CreateExtractValue (mat, 2);
+    fn.do_return (builder, builder.CreateSIToFP (ret, scalar_t));
+  }
+  end_fn.add_overload (fn);
+
+  casts[any->type_id ()].stash_name ("(any)");
+  casts[scalar->type_id ()].stash_name ("(scalar)");
+  casts[complex->type_id ()].stash_name ("(complex)");
+  casts[matrix->type_id ()].stash_name ("(matrix)");
+  casts[any->type_id ()].stash_name ("(range)");
+
+  // cast any <- matrix
+  fn = create_function (jit_convention::external, "octave_jit_cast_any_matrix",
+                        any, matrix);
+  fn.add_mapping (engine, &octave_jit_cast_any_matrix);
+  casts[any->type_id ()].add_overload (fn);
+
+  // cast matrix <- any
+  fn = create_function (jit_convention::external, "octave_jit_cast_matrix_any",
+                        matrix, any);
+  fn.add_mapping (engine, &octave_jit_cast_matrix_any);
+  casts[matrix->type_id ()].add_overload (fn);
+
+  // cast any <- range
+  fn = create_function (jit_convention::external, "octave_jit_cast_any_range",
+                        any, range);
+  fn.add_mapping (engine, &octave_jit_cast_any_range);
+  casts[any->type_id ()].add_overload (fn);
+
+  // cast range <- any
+  fn = create_function (jit_convention::external, "octave_jit_cast_range_any",
+                        range, any);
+  fn.add_mapping (engine, &octave_jit_cast_range_any);
+  casts[range->type_id ()].add_overload (fn);
+
+  // cast any <- scalar
+  fn = create_function (jit_convention::external, "octave_jit_cast_any_scalar",
+                        any, scalar);
+  fn.add_mapping (engine, &octave_jit_cast_any_scalar);
+  casts[any->type_id ()].add_overload (fn);
+
+  // cast scalar <- any
+  fn = create_function (jit_convention::external, "octave_jit_cast_scalar_any",
+                        scalar, any);
+  fn.add_mapping (engine, &octave_jit_cast_scalar_any);
+  casts[scalar->type_id ()].add_overload (fn);
+
+  // cast any <- complex
+  fn = create_function (jit_convention::external, "octave_jit_cast_any_complex",
+                        any, complex);
+  fn.add_mapping (engine, &octave_jit_cast_any_complex);
+  casts[any->type_id ()].add_overload (fn);
+
+  // cast complex <- any
+  fn = create_function (jit_convention::external, "octave_jit_cast_complex_any",
+                        complex, any);
+  fn.add_mapping (engine, &octave_jit_cast_complex_any);
+  casts[complex->type_id ()].add_overload (fn);
+
+  // cast complex <- scalar
+  fn = create_function (jit_convention::internal,
+                        "octave_jit_cast_complex_scalar", complex, scalar);
+  body = fn.new_block ();
+  builder.SetInsertPoint (body);
+  {
+    llvm::Value *zero = llvm::ConstantFP::get (scalar_t, 0);
+    fn.do_return (builder, complex_new (fn.argument (builder, 0), zero));
+  }
+  casts[complex->type_id ()].add_overload (fn);
+
+  // cast scalar <- complex
+  fn = create_function (jit_convention::internal,
+                        "octave_jit_cast_scalar_complex", scalar, complex);
+  body = fn.new_block ();
+  builder.SetInsertPoint (body);
+  fn.do_return (builder, complex_real (fn.argument (builder, 0)));
+  casts[scalar->type_id ()].add_overload (fn);
+
+  // cast any <- any
+  fn = create_identity (any);
+  casts[any->type_id ()].add_overload (fn);
+
+  // cast scalar <- scalar
+  fn = create_identity (scalar);
+  casts[scalar->type_id ()].add_overload (fn);
+
+  // cast complex <- complex
+  fn = create_identity (complex);
+  casts[complex->type_id ()].add_overload (fn);
+
+  // -------------------- builtin functions --------------------
+  add_builtin ("#unknown_function");
+  unknown_function = builtins["#unknown_function"];
+
+  add_builtin ("sin");
+  register_intrinsic ("sin", llvm::Intrinsic::sin, scalar, scalar);
+  register_generic ("sin", matrix, matrix);
+
+  add_builtin ("cos");
+  register_intrinsic ("cos", llvm::Intrinsic::cos, scalar, scalar);
+  register_generic ("cos", matrix, matrix);
+
+  add_builtin ("exp");
+  register_intrinsic ("exp", llvm::Intrinsic::cos, scalar, scalar);
+  register_generic ("exp", matrix, matrix);
+
+  casts.resize (next_id + 1);
+  jit_function any_id = create_identity (any);
+  jit_function release_any = get_release (any);
+  std::vector<jit_type *> args;
+  args.resize (1);
+
+  for (std::map<std::string, jit_type *>::iterator iter = builtins.begin ();
+       iter != builtins.end (); ++iter)
+    {
+      jit_type *btype = iter->second;
+      args[0] = btype;
+
+      release_fn.add_overload (jit_function (release_any, 0, args));
+      casts[any->type_id ()].add_overload (jit_function (any_id, any, args));
+
+      args[0] = any;
+      casts[btype->type_id ()].add_overload (jit_function (any_id, btype,
+                                                           args));
+    }
+}
+
+void
+jit_typeinfo::add_print (jit_type *ty, void *fptr)
+{
+  std::stringstream name;
+  name << "octave_jit_print_" << ty->name ();
+  jit_function fn = create_function (jit_convention::external, name.str (), 0,
+                                     intN (8), ty);
+  fn.add_mapping (engine, fptr);
+  print_fn.add_overload (fn);
+}
+
+// FIXME: cp between add_binary_op, add_binary_icmp, and add_binary_fcmp
+void
+jit_typeinfo::add_binary_op (jit_type *ty, int op, int llvm_op)
+{
+  std::stringstream fname;
+  octave_value::binary_op ov_op = static_cast<octave_value::binary_op>(op);
+  fname << "octave_jit_" << octave_value::binary_op_as_string (ov_op)
+        << "_" << ty->name ();
+
+  jit_function fn = create_function (jit_convention::internal, fname.str (),
+                                        ty, ty, ty);
+  llvm::BasicBlock *block = fn.new_block ();
+  builder.SetInsertPoint (block);
+  llvm::Instruction::BinaryOps temp
+    = static_cast<llvm::Instruction::BinaryOps>(llvm_op);
+
+  llvm::Value *ret = builder.CreateBinOp (temp, fn.argument (builder, 0),
+                                          fn.argument (builder, 1));
+  fn.do_return (builder, ret);
+  binary_ops[op].add_overload (fn);
+}
+
+void
+jit_typeinfo::add_binary_icmp (jit_type *ty, int op, int llvm_op)
+{
+  std::stringstream fname;
+  octave_value::binary_op ov_op = static_cast<octave_value::binary_op>(op);
+  fname << "octave_jit" << octave_value::binary_op_as_string (ov_op)
+        << "_" << ty->name ();
+
+  jit_function fn = create_function (jit_convention::internal, fname.str (),
+                                     boolean, ty, ty);
+  llvm::BasicBlock *block = fn.new_block ();
+  builder.SetInsertPoint (block);
+  llvm::CmpInst::Predicate temp
+    = static_cast<llvm::CmpInst::Predicate>(llvm_op);
+  llvm::Value *ret = builder.CreateICmp (temp, fn.argument (builder, 0),
+                                         fn.argument (builder, 1));
+  fn.do_return (builder, ret);
+  binary_ops[op].add_overload (fn);
+}
+
+void
+jit_typeinfo::add_binary_fcmp (jit_type *ty, int op, int llvm_op)
+{
+  std::stringstream fname;
+  octave_value::binary_op ov_op = static_cast<octave_value::binary_op>(op);
+  fname << "octave_jit" << octave_value::binary_op_as_string (ov_op)
+        << "_" << ty->name ();
+
+  jit_function fn = create_function (jit_convention::internal, fname.str (),
+                                     boolean, ty, ty);
+  llvm::BasicBlock *block = fn.new_block ();
+  builder.SetInsertPoint (block);
+  llvm::CmpInst::Predicate temp
+    = static_cast<llvm::CmpInst::Predicate>(llvm_op);
+  llvm::Value *ret = builder.CreateFCmp (temp, fn.argument (builder, 0),
+                                         fn.argument (builder, 1));
+  fn.do_return (builder, ret);
+  binary_ops[op].add_overload (fn);
+}
+
+jit_function
+jit_typeinfo::create_function (jit_convention::type cc, const llvm::Twine& name,
+                               jit_type *ret,
+                               const std::vector<jit_type *>& args)
+{
+  jit_function result (module, cc, name, ret, args);
+  return result;
+}
+
+jit_function
+jit_typeinfo::create_identity (jit_type *type)
+{
+  size_t id = type->type_id ();
+  if (id >= identities.size ())
+    identities.resize (id + 1);
+
+  if (! identities[id].valid ())
+    {
+      jit_function fn = create_function (jit_convention::internal, "id", type,
+                                         type);
+      llvm::BasicBlock *body = fn.new_block ();
+      builder.SetInsertPoint (body);
+      fn.do_return (builder, fn.argument (builder, 0));
+      return identities[id] = fn;
+    }
+
+  return identities[id];
+}
+
+llvm::Value *
+jit_typeinfo::do_insert_error_check (llvm::IRBuilderD& abuilder)
+{
+  return abuilder.CreateLoad (lerror_state);
+}
+
+void
+jit_typeinfo::add_builtin (const std::string& name)
+{
+  jit_type *btype = new_type (name, any, any->to_llvm ());
+  builtins[name] = btype;
+
+  octave_builtin *ov_builtin = find_builtin (name);
+  if (ov_builtin)
+    ov_builtin->stash_jit (*btype);
+}
+
+void
+jit_typeinfo::register_intrinsic (const std::string& name, size_t iid,
+                                  jit_type *result,
+                                  const std::vector<jit_type *>& args)
+{
+  jit_type *builtin_type = builtins[name];
+  size_t nargs = args.size ();
+  llvm::SmallVector<llvm::Type *, 5> llvm_args (nargs);
+  for (size_t i = 0; i < nargs; ++i)
+    llvm_args[i] = args[i]->to_llvm ();
+
+  llvm::Intrinsic::ID id = static_cast<llvm::Intrinsic::ID> (iid);
+  llvm::Function *ifun = llvm::Intrinsic::getDeclaration (module, id,
+                                                          llvm_args);
+  std::stringstream fn_name;
+  fn_name << "octave_jit_" << name;
+
+  std::vector<jit_type *> args1 (nargs + 1);
+  args1[0] = builtin_type;
+  std::copy (args.begin (), args.end (), args1.begin () + 1);
+
+  // The first argument will be the Octave function, but we already know that
+  // the function call is the equivalent of the intrinsic, so we ignore it and
+  // call the intrinsic with the remaining arguments.
+  jit_function fn = create_function (jit_convention::internal, fn_name.str (),
+                                     result, args1);
+  llvm::BasicBlock *body = fn.new_block ();
+  builder.SetInsertPoint (body);
+
+  llvm::SmallVector<llvm::Value *, 5> fargs (nargs);
+  for (size_t i = 0; i < nargs; ++i)
+    fargs[i] = fn.argument (builder, i + 1);
+
+  llvm::Value *ret = builder.CreateCall (ifun, fargs);
+  fn.do_return (builder, ret);
+  paren_subsref_fn.add_overload (fn);
+}
+
+octave_builtin *
+jit_typeinfo::find_builtin (const std::string& name)
+{
+  // FIXME: Finalize what we want to store in octave_builtin, then add functions
+  // to access these values in octave_value
+  octave_value ov_builtin = symbol_table::find (name);
+  return dynamic_cast<octave_builtin *> (ov_builtin.internal_rep ());
+}
+
+void
+jit_typeinfo::register_generic (const std::string&, jit_type *,
+                                const std::vector<jit_type *>&)
+{
+  // FIXME: Implement
+}
+
+jit_function
+jit_typeinfo::mirror_binary (const jit_function& fn)
+{
+  jit_function ret = create_function (jit_convention::internal,
+                                      fn.name () + "_reverse",
+                                      fn.result (), fn.argument_type (1),
+                                      fn.argument_type (0));
+  if (fn.can_error ())
+    ret.mark_can_error ();
+
+  llvm::BasicBlock *body = ret.new_block ();
+  builder.SetInsertPoint (body);
+  llvm::Value *result = fn.call (builder, ret.argument (builder, 1),
+                                 ret.argument (builder, 0));
+  if (ret.result ())
+    ret.do_return (builder, result);
+  else
+    ret.do_return (builder);
+
+  return ret;
+}
+
+llvm::Value *
+jit_typeinfo::pack_complex (llvm::IRBuilderD& bld, llvm::Value *cplx)
+{
+  llvm::Type *complex_ret = instance->complex_ret;
+  llvm::Value *real = bld.CreateExtractElement (cplx, bld.getInt32 (0));
+  llvm::Value *imag = bld.CreateExtractElement (cplx, bld.getInt32 (1));
+  llvm::Value *ret = llvm::UndefValue::get (complex_ret);
+  ret = bld.CreateInsertValue (ret, real, 0);
+  return bld.CreateInsertValue (ret, imag, 1);
+}
+
+llvm::Value *
+jit_typeinfo::unpack_complex (llvm::IRBuilderD& bld, llvm::Value *result)
+{
+  llvm::Type *complex_t = get_complex ()->to_llvm ();
+  llvm::Value *real = bld.CreateExtractValue (result, 0);
+  llvm::Value *imag = bld.CreateExtractValue (result, 1);
+  llvm::Value *ret = llvm::UndefValue::get (complex_t);
+  ret = bld.CreateInsertElement (ret, real, bld.getInt32 (0));
+  return bld.CreateInsertElement (ret, imag, bld.getInt32 (1));
+}
+
+llvm::Value *
+jit_typeinfo::complex_real (llvm::Value *cx)
+{
+  return builder.CreateExtractElement (cx, builder.getInt32 (0));
+}
+
+llvm::Value *
+jit_typeinfo::complex_real (llvm::Value *cx, llvm::Value *real)
+{
+  return builder.CreateInsertElement (cx, real, builder.getInt32 (0));
+}
+
+llvm::Value *
+jit_typeinfo::complex_imag (llvm::Value *cx)
+{
+  return builder.CreateExtractElement (cx, builder.getInt32 (1));
+}
+
+llvm::Value *
+jit_typeinfo::complex_imag (llvm::Value *cx, llvm::Value *imag)
+{
+  return builder.CreateInsertElement (cx, imag, builder.getInt32 (1));
+}
+
+llvm::Value *
+jit_typeinfo::complex_new (llvm::Value *real, llvm::Value *imag)
+{
+  llvm::Value *ret = llvm::UndefValue::get (complex->to_llvm ());
+  ret = complex_real (ret, real);
+  return complex_imag (ret, imag);
+}
+
+void
+jit_typeinfo::create_int (size_t nbits)
+{
+  std::stringstream tname;
+  tname << "int" << nbits;
+  ints[nbits] = new_type (tname.str (), any, llvm::Type::getIntNTy (context,
+                                                                    nbits));
+}
+
+jit_type *
+jit_typeinfo::intN (size_t nbits) const
+{
+  std::map<size_t, jit_type *>::const_iterator iter = ints.find (nbits);
+  if (iter != ints.end ())
+    return iter->second;
+
+  throw jit_fail_exception ("No such integer type");
+}
+
+jit_type *
+jit_typeinfo::do_type_of (const octave_value &ov) const
+{
+  if (ov.is_function ())
+    {
+      // FIXME: This is ugly, we need to finalize how we want to to this, then
+      // have octave_value fully support the needed functionality
+      octave_builtin *builtin
+        = dynamic_cast<octave_builtin *> (ov.internal_rep ());
+      return builtin && builtin->to_jit () ? builtin->to_jit ()
+        : unknown_function;
+    }
+
+  if (ov.is_range ())
+    return get_range ();
+
+  if (ov.is_double_type ())
+    {
+      if (ov.is_real_scalar ())
+        return get_scalar ();
+
+      if (ov.is_matrix_type ())
+        return get_matrix ();
+    }
+
+  if (ov.is_complex_scalar ())
+    return get_complex ();
+
+  return get_any ();
+}
+
+jit_type*
+jit_typeinfo::new_type (const std::string& name, jit_type *parent,
+                        llvm::Type *llvm_type)
+{
+  jit_type *ret = new jit_type (name, parent, llvm_type, next_id++);
+  id_to_type.push_back (ret);
+  return ret;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/jit-typeinfo.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,753 @@
+/*
+
+Copyright (C) 2012 Max Brister <max@2bass.com>
+
+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/>.
+
+*/
+
+#if !defined (octave_jit_typeinfo_h)
+#define octave_jit_typeinfo_h 1
+
+#ifdef HAVE_LLVM
+
+#include <map>
+#include <vector>
+
+#include "Range.h"
+#include "jit-util.h"
+
+// Defines the type system used by jit and a singleton class, jit_typeinfo, to
+// manage the types.
+//
+// FIXME:
+// Operations are defined and implemented in jit_typeinfo. Eventually they
+// should be moved elsewhere. (just like with octave_typeinfo)
+
+// jit_range is compatable with the llvm range structure
+struct
+jit_range
+{
+  jit_range (const Range& from) : base (from.base ()), limit (from.limit ()),
+                                  inc (from.inc ()), nelem (from.nelem ())
+  {}
+
+  operator Range () const
+  {
+    return Range (base, limit, inc);
+  }
+
+  bool all_elements_are_ints () const;
+
+  double base;
+  double limit;
+  double inc;
+  octave_idx_type nelem;
+};
+
+std::ostream& operator<< (std::ostream& os, const jit_range& rng);
+
+// jit_array is compatable with the llvm array/matrix structures
+template <typename T, typename U>
+struct
+jit_array
+{
+  jit_array (T& from) : array (new T (from))
+  {
+    update ();
+  }
+
+  void update (void)
+  {
+    ref_count = array->jit_ref_count ();
+    slice_data = array->jit_slice_data () - 1;
+    slice_len = array->capacity ();
+    dimensions = array->jit_dimensions ();
+  }
+
+  void update (T *aarray)
+  {
+    array = aarray;
+    update ();
+  }
+
+  operator T () const
+  {
+    return *array;
+  }
+
+  int *ref_count;
+
+  U *slice_data;
+  octave_idx_type slice_len;
+  octave_idx_type *dimensions;
+
+  T *array;
+};
+
+typedef jit_array<NDArray, double> jit_matrix;
+
+std::ostream& operator<< (std::ostream& os, const jit_matrix& mat);
+
+// calling convention
+namespace
+jit_convention
+{
+  enum
+  type
+  {
+    // internal to jit
+    internal,
+
+    // an external C call
+    external,
+
+    length
+  };
+}
+
+// Used to keep track of estimated (infered) types during JIT. This is a
+// hierarchical type system which includes both concrete and abstract types.
+//
+// The types form a lattice. Currently we only allow for one parent type, but
+// eventually we may allow for multiple predecessors.
+class
+jit_type
+{
+public:
+  typedef llvm::Value *(*convert_fn) (llvm::IRBuilderD&, llvm::Value *);
+
+  jit_type (const std::string& aname, jit_type *aparent, llvm::Type *allvm_type,
+            int aid);
+
+  // a user readable type name
+  const std::string& name (void) const { return mname; }
+
+  // a unique id for the type
+  int type_id (void) const { return mid; }
+
+  // An abstract base type, may be null
+  jit_type *parent (void) const { return mparent; }
+
+  // convert to an llvm type
+  llvm::Type *to_llvm (void) const { return llvm_type; }
+
+  // how this type gets passed as a function argument
+  llvm::Type *to_llvm_arg (void) const;
+
+  size_t depth (void) const { return mdepth; }
+
+  // -------------------- Calling Convention information --------------------
+
+  // A function declared like: mytype foo (int arg0, int arg1);
+  // Will be converted to: void foo (mytype *retval, int arg0, int arg1)
+  // if mytype is sret. The caller is responsible for allocating space for
+  // retval. (on the stack)
+  bool sret (jit_convention::type cc) const { return msret[cc]; }
+
+  void mark_sret (jit_convention::type cc = jit_convention::external)
+  { msret[cc] = true; }
+
+  // A function like: void foo (mytype arg0)
+  // Will be converted to: void foo (mytype *arg0)
+  // Basically just pass by reference.
+  bool pointer_arg (jit_convention::type cc) const { return mpointer_arg[cc]; }
+
+  void mark_pointer_arg (jit_convention::type cc = jit_convention::external)
+  { mpointer_arg[cc] = true; }
+
+  // Convert into an equivalent form before calling. For example, complex is
+  // represented as two values llvm vector, but we need to pass it as a two
+  // valued llvm structure to C functions.
+  convert_fn pack (jit_convention::type cc) { return mpack[cc]; }
+
+  void set_pack (jit_convention::type cc, convert_fn fn) { mpack[cc] = fn; }
+
+  // The inverse operation of pack.
+  convert_fn unpack (jit_convention::type cc) { return munpack[cc]; }
+
+  void set_unpack (jit_convention::type cc, convert_fn fn)
+  { munpack[cc] = fn; }
+
+  // The resulting type after pack is called.
+  llvm::Type *packed_type (jit_convention::type cc)
+  { return mpacked_type[cc]; }
+
+  void set_packed_type (jit_convention::type cc, llvm::Type *ty)
+  { mpacked_type[cc] = ty; }
+private:
+  std::string mname;
+  jit_type *mparent;
+  llvm::Type *llvm_type;
+  int mid;
+  size_t mdepth;
+
+  bool msret[jit_convention::length];
+  bool mpointer_arg[jit_convention::length];
+
+  convert_fn mpack[jit_convention::length];
+  convert_fn munpack[jit_convention::length];
+
+  llvm::Type *mpacked_type[jit_convention::length];
+};
+
+// seperate print function to allow easy printing if type is null
+std::ostream& jit_print (std::ostream& os, jit_type *atype);
+
+class jit_value;
+
+// An abstraction for calling llvm functions with jit_values. Deals with calling
+// convention details.
+class
+jit_function
+{
+  friend std::ostream& operator<< (std::ostream& os, const jit_function& fn);
+public:
+  // create a function in an invalid state
+  jit_function ();
+
+  jit_function (llvm::Module *amodule, jit_convention::type acall_conv,
+                const llvm::Twine& aname, jit_type *aresult,
+                const std::vector<jit_type *>& aargs);
+
+  // Use an existing function, but change the argument types. The new argument
+  // types must behave the same for the current calling convention.
+  jit_function (const jit_function& fn, jit_type *aresult,
+                const std::vector<jit_type *>& aargs);
+
+  jit_function (const jit_function& fn);
+
+  template <typename T>
+  void add_mapping (llvm::ExecutionEngine *engine, T fn)
+  {
+    do_add_mapping (engine, reinterpret_cast<void *> (fn));
+  }
+
+  bool valid (void) const { return llvm_function; }
+
+  std::string name (void) const;
+
+  llvm::BasicBlock *new_block (const std::string& aname = "body",
+                               llvm::BasicBlock *insert_before = 0);
+
+  llvm::Value *call (llvm::IRBuilderD& builder,
+                     const std::vector<jit_value *>& in_args) const;
+
+  llvm::Value *call (llvm::IRBuilderD& builder,
+                     const std::vector<llvm::Value *>& in_args
+                     = std::vector<llvm::Value *> ()) const;
+
+#define JIT_PARAM_ARGS llvm::IRBuilderD& builder,
+#define JIT_PARAMS builder,
+#define JIT_CALL(N) JIT_EXPAND (llvm::Value *, call, llvm::Value *, const, N)
+
+  JIT_CALL (1)
+  JIT_CALL (2)
+  JIT_CALL (3)
+  JIT_CALL (4)
+  JIT_CALL (5)
+
+#undef JIT_CALL
+
+#define JIT_CALL(N) JIT_EXPAND (llvm::Value *, call, jit_value *, const, N)
+
+  JIT_CALL (1);
+  JIT_CALL (2);
+
+#undef JIT_CALL
+#undef JIT_PARAMS
+#undef JIT_PARAM_ARGS
+
+  llvm::Value *argument (llvm::IRBuilderD& builder, size_t idx) const;
+
+  void do_return (llvm::IRBuilderD& builder, llvm::Value *rval = 0);
+
+  llvm::Function *to_llvm (void) const { return llvm_function; }
+
+  // If true, then the return value is passed as a pointer in the first argument
+  bool sret (void) const { return mresult && mresult->sret (call_conv); }
+
+  bool can_error (void) const { return mcan_error; }
+
+  void mark_can_error (void) { mcan_error = true; }
+
+  jit_type *result (void) const { return mresult; }
+
+  jit_type *argument_type (size_t idx) const
+  {
+    assert (idx < args.size ());
+    return args[idx];
+  }
+
+  const std::vector<jit_type *>& arguments (void) const { return args; }
+private:
+  void do_add_mapping (llvm::ExecutionEngine *engine, void *fn);
+
+  llvm::Module *module;
+  llvm::Function *llvm_function;
+  jit_type *mresult;
+  std::vector<jit_type *> args;
+  jit_convention::type call_conv;
+  bool mcan_error;
+};
+
+std::ostream& operator<< (std::ostream& os, const jit_function& fn);
+
+
+// Keeps track of information about how to implement operations (+, -, *, ect)
+// and their resulting types.
+class
+jit_operation
+{
+public:
+  // type signature vector
+  typedef std::vector<jit_type *> signature_vec;
+
+  virtual ~jit_operation (void);
+
+  void add_overload (const jit_function& func)
+  {
+    add_overload (func, func.arguments ());
+  }
+
+  void add_overload (const jit_function& func,
+                     const signature_vec& args);
+
+  const jit_function& overload (const signature_vec& types) const;
+
+  jit_type *result (const signature_vec& types) const
+  {
+    const jit_function& temp = overload (types);
+    return temp.result ();
+  }
+
+#define JIT_PARAMS
+#define JIT_PARAM_ARGS
+#define JIT_OVERLOAD(N)                                              \
+  JIT_EXPAND (const jit_function&, overload, jit_type *, const, N)   \
+  JIT_EXPAND (jit_type *, result, jit_type *, const, N)
+
+  JIT_OVERLOAD (1);
+  JIT_OVERLOAD (2);
+  JIT_OVERLOAD (3);
+
+#undef JIT_PARAMS
+#undef JIT_PARAM_ARGS
+
+  const std::string& name (void) const { return mname; }
+
+  void stash_name (const std::string& aname) { mname = aname; }
+protected:
+  virtual jit_function *generate (const signature_vec& types) const;
+private:
+  Array<octave_idx_type> to_idx (const signature_vec& types) const;
+
+  const jit_function& do_generate (const signature_vec& types) const;
+
+  struct signature_cmp
+  {
+    bool operator() (const signature_vec *lhs, const signature_vec *rhs);
+  };
+
+  typedef std::map<const signature_vec *, jit_function *, signature_cmp>
+  generated_map;
+
+  mutable generated_map generated;
+
+  std::vector<Array<jit_function> > overloads;
+
+  std::string mname;
+};
+
+class
+jit_index_operation : public jit_operation
+{
+public:
+  jit_index_operation (void) : module (0), engine (0) {}
+
+  void initialize (llvm::Module *amodule, llvm::ExecutionEngine *aengine)
+  {
+    module = amodule;
+    engine = aengine;
+    do_initialize ();
+  }
+protected:
+  virtual jit_function *generate (const signature_vec& types) const;
+
+  virtual jit_function *generate_matrix (const signature_vec& types) const = 0;
+
+  virtual void do_initialize (void) = 0;
+
+  // helper functions
+  // [start_idx, end_idx).
+  llvm::Value *create_arg_array (llvm::IRBuilderD& builder,
+                                 const jit_function &fn, size_t start_idx,
+                                 size_t end_idx) const;
+
+  llvm::Module *module;
+  llvm::ExecutionEngine *engine;
+};
+
+class
+jit_paren_subsref : public jit_index_operation
+{
+protected:
+  virtual jit_function *generate_matrix (const signature_vec& types) const;
+
+  virtual void do_initialize (void);
+private:
+  jit_function paren_scalar;
+};
+
+class
+jit_paren_subsasgn : public jit_index_operation
+{
+protected:
+  jit_function *generate_matrix (const signature_vec& types) const;
+
+  virtual void do_initialize (void);
+private:
+  jit_function paren_scalar;
+};
+
+// A singleton class which handles the construction of jit_types and
+// jit_operations.
+class
+jit_typeinfo
+{
+public:
+  static void initialize (llvm::Module *m, llvm::ExecutionEngine *e);
+
+  static jit_type *join (jit_type *lhs, jit_type *rhs)
+  {
+    return instance->do_join (lhs, rhs);
+  }
+
+  static jit_type *get_any (void) { return instance->any; }
+
+  static jit_type *get_matrix (void) { return instance->matrix; }
+
+  static jit_type *get_scalar (void) { return instance->scalar; }
+
+  static llvm::Type *get_scalar_llvm (void)
+  { return instance->scalar->to_llvm (); }
+
+  static jit_type *get_scalar_ptr (void) { return instance->scalar_ptr; }
+
+  static jit_type *get_range (void) { return instance->range; }
+
+  static jit_type *get_string (void) { return instance->string; }
+
+  static jit_type *get_bool (void) { return instance->boolean; }
+
+  static jit_type *get_index (void) { return instance->index; }
+
+  static llvm::Type *get_index_llvm (void)
+  { return instance->index->to_llvm (); }
+
+  static jit_type *get_complex (void) { return instance->complex; }
+
+  // Get the jit_type of an octave_value
+  static jit_type *type_of (const octave_value& ov)
+  {
+    return instance->do_type_of (ov);
+  }
+
+  static const jit_operation& binary_op (int op)
+  {
+    return instance->do_binary_op (op);
+  }
+
+  static const jit_operation& grab (void) { return instance->grab_fn; }
+
+  static const jit_function& get_grab (jit_type *type)
+  {
+    return instance->grab_fn.overload (type);
+  }
+
+  static const jit_operation& release (void)
+  {
+    return instance->release_fn;
+  }
+
+  static const jit_function& get_release (jit_type *type)
+  {
+    return instance->release_fn.overload (type);
+  }
+
+  static const jit_operation& print_value (void)
+  {
+    return instance->print_fn;
+  }
+
+  static const jit_operation& for_init (void)
+  {
+    return instance->for_init_fn;
+  }
+
+  static const jit_operation& for_check (void)
+  {
+    return instance->for_check_fn;
+  }
+
+  static const jit_operation& for_index (void)
+  {
+    return instance->for_index_fn;
+  }
+
+  static const jit_operation& make_range (void)
+  {
+    return instance->make_range_fn;
+  }
+
+  static const jit_operation& paren_subsref (void)
+  {
+    return instance->paren_subsref_fn;
+  }
+
+  static const jit_operation& paren_subsasgn (void)
+  {
+    return instance->paren_subsasgn_fn;
+  }
+
+  static const jit_operation& logically_true (void)
+  {
+    return instance->logically_true_fn;
+  }
+
+  static const jit_operation& cast (jit_type *result)
+  {
+    return instance->do_cast (result);
+  }
+
+  static const jit_function& cast (jit_type *to, jit_type *from)
+  {
+    return instance->do_cast (to, from);
+  }
+
+  static llvm::Value *insert_error_check (llvm::IRBuilderD& bld)
+  {
+    return instance->do_insert_error_check (bld);
+  }
+
+  static const jit_operation& end (void)
+  {
+    return instance->end_fn;
+  }
+
+  static const jit_function& end (jit_type *ty)
+  {
+    return instance->end_fn.overload (ty);
+  }
+private:
+  jit_typeinfo (llvm::Module *m, llvm::ExecutionEngine *e);
+
+  // FIXME: Do these methods really need to be in jit_typeinfo?
+  jit_type *do_join (jit_type *lhs, jit_type *rhs)
+  {
+    // empty case
+    if (! lhs)
+      return rhs;
+
+    if (! rhs)
+      return lhs;
+
+    // check for a shared parent
+    while (lhs != rhs)
+      {
+        if (lhs->depth () > rhs->depth ())
+          lhs = lhs->parent ();
+        else if (lhs->depth () < rhs->depth ())
+          rhs = rhs->parent ();
+        else
+          {
+            // we MUST have depth > 0 as any is the base type of everything
+            do
+              {
+                lhs = lhs->parent ();
+                rhs = rhs->parent ();
+              }
+            while (lhs != rhs);
+          }
+      }
+
+    return lhs;
+  }
+
+  jit_type *do_difference (jit_type *lhs, jit_type *)
+  {
+    // FIXME: Maybe we can do something smarter?
+    return lhs;
+  }
+
+  jit_type *do_type_of (const octave_value &ov) const;
+
+  const jit_operation& do_binary_op (int op) const
+  {
+    assert (static_cast<size_t>(op) < binary_ops.size ());
+    return binary_ops[op];
+  }
+
+  const jit_operation& do_cast (jit_type *to)
+  {
+    static jit_operation null_function;
+    if (! to)
+      return null_function;
+
+    size_t id = to->type_id ();
+    if (id >= casts.size ())
+      return null_function;
+    return casts[id];
+  }
+
+  const jit_function& do_cast (jit_type *to, jit_type *from)
+  {
+    return do_cast (to).overload (from);
+  }
+
+  jit_type *new_type (const std::string& name, jit_type *parent,
+                      llvm::Type *llvm_type);
+
+
+  void add_print (jit_type *ty, void *fptr);
+
+  void add_binary_op (jit_type *ty, int op, int llvm_op);
+
+  void add_binary_icmp (jit_type *ty, int op, int llvm_op);
+
+  void add_binary_fcmp (jit_type *ty, int op, int llvm_op);
+
+  jit_function create_function (jit_convention::type cc,
+                                const llvm::Twine& name, jit_type *ret,
+                                const std::vector<jit_type *>& args
+                                = std::vector<jit_type *> ());
+
+#define JIT_PARAM_ARGS jit_convention::type cc, const llvm::Twine& name, \
+    jit_type *ret,
+#define JIT_PARAMS cc, name, ret,
+#define CREATE_FUNCTION(N) JIT_EXPAND(jit_function, create_function,    \
+                                      jit_type *, /* empty */, N)
+
+  CREATE_FUNCTION(1);
+  CREATE_FUNCTION(2);
+  CREATE_FUNCTION(3);
+  CREATE_FUNCTION(4);
+
+#undef JIT_PARAM_ARGS
+#undef JIT_PARAMS
+#undef CREATE_FUNCTION
+
+  jit_function create_identity (jit_type *type);
+
+  llvm::Value *do_insert_error_check (llvm::IRBuilderD& bld);
+
+  void add_builtin (const std::string& name);
+
+  void register_intrinsic (const std::string& name, size_t id,
+                           jit_type *result, jit_type *arg0)
+  {
+    std::vector<jit_type *> args (1, arg0);
+    register_intrinsic (name, id, result, args);
+  }
+
+  void register_intrinsic (const std::string& name, size_t id, jit_type *result,
+                           const std::vector<jit_type *>& args);
+
+  void register_generic (const std::string& name, jit_type *result,
+                         jit_type *arg0)
+  {
+    std::vector<jit_type *> args (1, arg0);
+    register_generic (name, result, args);
+  }
+
+  void register_generic (const std::string& name, jit_type *result,
+                         const std::vector<jit_type *>& args);
+
+  octave_builtin *find_builtin (const std::string& name);
+
+  jit_function mirror_binary (const jit_function& fn);
+
+  llvm::Function *wrap_complex (llvm::Function *wrap);
+
+  static llvm::Value *pack_complex (llvm::IRBuilderD& bld,
+                                    llvm::Value *cplx);
+
+  static llvm::Value *unpack_complex (llvm::IRBuilderD& bld,
+                                      llvm::Value *result);
+
+  llvm::Value *complex_real (llvm::Value *cx);
+
+  llvm::Value *complex_real (llvm::Value *cx, llvm::Value *real);
+
+  llvm::Value *complex_imag (llvm::Value *cx);
+
+  llvm::Value *complex_imag (llvm::Value *cx, llvm::Value *imag);
+
+  llvm::Value *complex_new (llvm::Value *real, llvm::Value *imag);
+
+  void create_int (size_t nbits);
+
+  jit_type *intN (size_t nbits) const;
+
+  static jit_typeinfo *instance;
+
+  llvm::Module *module;
+  llvm::ExecutionEngine *engine;
+  int next_id;
+
+  llvm::GlobalVariable *lerror_state;
+
+  std::vector<jit_type*> id_to_type;
+  jit_type *any;
+  jit_type *matrix;
+  jit_type *scalar;
+  jit_type *scalar_ptr; // a fake type for interfacing with C++
+  jit_type *range;
+  jit_type *string;
+  jit_type *boolean;
+  jit_type *index;
+  jit_type *complex;
+  jit_type *unknown_function;
+  std::map<size_t, jit_type *> ints;
+  std::map<std::string, jit_type *> builtins;
+
+  llvm::StructType *complex_ret;
+
+  std::vector<jit_operation> binary_ops;
+  jit_operation grab_fn;
+  jit_operation release_fn;
+  jit_operation print_fn;
+  jit_operation for_init_fn;
+  jit_operation for_check_fn;
+  jit_operation for_index_fn;
+  jit_operation logically_true_fn;
+  jit_operation make_range_fn;
+  jit_paren_subsref paren_subsref_fn;
+  jit_paren_subsasgn paren_subsasgn_fn;
+  jit_operation end_fn;
+
+  // type id -> cast function TO that type
+  std::vector<jit_operation> casts;
+
+  // type id -> identity function
+  std::vector<jit_function> identities;
+
+  llvm::IRBuilderD& builder;
+};
+
+#endif
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/jit-util.cc	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,44 @@
+/*
+
+Copyright (C) 2012 Max Brister <max@2bass.com>
+
+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/>.
+
+*/
+
+// defines required by llvm
+#define __STDC_LIMIT_MACROS
+#define __STDC_CONSTANT_MACROS
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_LLVM
+
+#include <llvm/Value.h>
+#include <llvm/Support/raw_os_ostream.h>
+
+std::ostream&
+operator<< (std::ostream& os, const llvm::Value& v)
+{
+  llvm::raw_os_ostream llvm_out (os);
+  v.print (llvm_out);
+  return os;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/jit-util.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,203 @@
+/*
+
+Copyright (C) 2012 Max Brister <max@2bass.com>
+
+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/>.
+
+*/
+
+// Some utility classes and functions used throughout jit
+
+#if !defined (octave_jit_util_h)
+#define octave_jit_util_h 1
+
+#ifdef HAVE_LLVM
+
+#include <stdexcept>
+
+// we don't want to include llvm headers here, as they require
+// __STDC_LIMIT_MACROS and __STDC_CONSTANT_MACROS be defined in the entire
+// compilation unit
+namespace llvm
+{
+  class Value;
+  class Module;
+  class FunctionPassManager;
+  class PassManager;
+  class ExecutionEngine;
+  class Function;
+  class BasicBlock;
+  class LLVMContext;
+  class Type;
+  class StructType;
+  class Twine;
+  class GlobalVariable;
+  class TerminatorInst;
+  class PHINode;
+
+  class ConstantFolder;
+
+  template <bool preserveNames>
+  class IRBuilderDefaultInserter;
+
+  template <bool preserveNames, typename T, typename Inserter>
+  class IRBuilder;
+
+typedef IRBuilder<true, ConstantFolder, IRBuilderDefaultInserter<true> >
+IRBuilderD;
+}
+
+class octave_base_value;
+class octave_builtin;
+class octave_value;
+class tree;
+class tree_expression;
+
+// thrown when we should give up on JIT and interpret
+class jit_fail_exception : public std::runtime_error
+{
+public:
+  jit_fail_exception (void) : std::runtime_error ("unknown"), mknown (false) {}
+  jit_fail_exception (const std::string& reason) : std::runtime_error (reason),
+                                                   mknown (true)
+  {}
+
+  bool known (void) const { return mknown; }
+private:
+  bool mknown;
+};
+
+// llvm doesn't provide this, and it's really useful for debugging
+std::ostream& operator<< (std::ostream& os, const llvm::Value& v);
+
+template <typename HOLDER_T, typename SUB_T>
+class jit_internal_node;
+
+// jit_internal_list and jit_internal_node implement generic embedded doubly
+// linked lists. List items extend from jit_internal_list, and can be placed
+// in nodes of type jit_internal_node. We use CRTP twice.
+template <typename LIST_T, typename NODE_T>
+class
+jit_internal_list
+{
+  friend class jit_internal_node<LIST_T, NODE_T>;
+public:
+  jit_internal_list (void) : use_head (0), use_tail (0), muse_count (0) {}
+
+  virtual ~jit_internal_list (void)
+  {
+    while (use_head)
+      use_head->stash_value (0);
+  }
+
+  NODE_T *first_use (void) const { return use_head; }
+
+  size_t use_count (void) const { return muse_count; }
+private:
+  NODE_T *use_head;
+  NODE_T *use_tail;
+  size_t muse_count;
+};
+
+// a node for internal linked lists
+template <typename LIST_T, typename NODE_T>
+class
+jit_internal_node
+{
+public:
+  typedef jit_internal_list<LIST_T, NODE_T> jit_ilist;
+
+  jit_internal_node (void) : mvalue (0), mnext (0), mprev (0) {}
+
+  ~jit_internal_node (void) { remove (); }
+
+  LIST_T *value (void) const { return mvalue; }
+
+  void stash_value (LIST_T *avalue)
+  {
+    remove ();
+
+    mvalue = avalue;
+
+    if (mvalue)
+      {
+        jit_ilist *ilist = mvalue;
+        NODE_T *sthis = static_cast<NODE_T *> (this);
+        if (ilist->use_head)
+          {
+            ilist->use_tail->mnext = sthis;
+            mprev = ilist->use_tail;
+          }
+        else
+          ilist->use_head = sthis;
+
+        ilist->use_tail = sthis;
+        ++ilist->muse_count;
+      }
+  }
+
+  NODE_T *next (void) const { return mnext; }
+
+  NODE_T *prev (void) const { return mprev; }
+private:
+  void remove ()
+  {
+    if (mvalue)
+      {
+        jit_ilist *ilist = mvalue;
+        if (mprev)
+          mprev->mnext = mnext;
+        else
+          // we are the use_head
+          ilist->use_head = mnext;
+
+        if (mnext)
+          mnext->mprev = mprev;
+        else
+          // we are the use tail
+          ilist->use_tail = mprev;
+
+        mnext = mprev = 0;
+        --ilist->muse_count;
+        mvalue = 0;
+      }
+  }
+
+  LIST_T *mvalue;
+  NODE_T *mnext;
+  NODE_T *mprev;
+};
+
+// Use like: isa<jit_phi> (value)
+// basically just a short cut type typing dyanmic_cast.
+template <typename T, typename U>
+bool isa (U *value)
+{
+  return dynamic_cast<T *> (value);
+}
+
+#define JIT_ASSIGN_ARG(i) the_args[i] = arg ## i;
+#define JIT_EXPAND(ret, fname, type, isconst, N)                        \
+  ret fname (JIT_PARAM_ARGS OCT_MAKE_DECL_LIST (type, arg, N)) isconst  \
+  {                                                                     \
+    std::vector<type> the_args (N);                                     \
+    OCT_ITERATE_MACRO (JIT_ASSIGN_ARG, N);                              \
+    return fname (JIT_PARAMS the_args);                                 \
+  }
+
+#endif
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/ls-ascii-helper.cc	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,175 @@
+/*
+
+Copyright (C) 2009-2012 Benjamin Lindner
+
+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/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "ls-ascii-helper.h"
+
+#include <iostream>
+#include <sstream>
+
+// Helper functions when reading from ascii files.
+
+// These function take care of CR/LF issues when files are opened in
+// text-mode for reading.
+
+// Skip characters from stream IS until a newline is reached.
+// Depending on KEEP_NEWLINE, either eat newline from stream or
+// keep it unread.
+
+void
+skip_until_newline (std::istream& is, bool keep_newline)
+{
+  if (! is)
+    return;
+
+  while (is)
+    {
+      char c = is.peek ();
+
+      if (c == '\n' || c == '\r')
+        {
+          // Reached newline.
+          if (! keep_newline)
+            {
+              // Eat the CR or LF character.
+              char d;
+              is.get (d);
+
+              // Make sure that for binary-mode opened ascii files
+              // containing CRLF line endings we skip the LF after CR.
+              if (c == '\r' && is.peek () == '\n')
+                {
+                  // Yes, LF following CR, eat it.
+                  is.get (d);
+                }
+            }
+
+          // Newline was found, and read from stream if
+          // keep_newline == true, so exit loop.
+          break;
+        }
+      else
+        {
+          // No newline charater peeked, so read it and proceed to next
+          // character.
+          char d;
+          is.get (d);
+        }
+    }
+}
+
+
+// If stream IS currently points to a newline (a leftover from a
+// previous read) then eat newline(s) until a non-newline character is
+// found.
+
+void
+skip_preceeding_newline (std::istream& is)
+{
+  if (! is)
+    return;
+
+  // Check whether IS currently points to newline character.
+  char c = is.peek ();
+
+  if (c == '\n' || c == '\r')
+    {
+      // Yes, at newline.
+      do
+        {
+          // Eat the CR or LF character.
+          char d;
+          is.get (d);
+
+          // Make sure that for binary-mode opened ascii files
+          // containing CRLF line endings we skip the LF after CR.
+          if (c == '\r' && is.peek () == '\n')
+            {
+              // Yes, LF following CR, eat it.
+              is.get (d);
+          }
+
+          // Peek into next character.
+          c = is.peek ();
+
+          // Loop while still a newline ahead.
+        }
+      while (c == '\n' || c == '\r');
+    }
+}
+
+// Read charaters from stream IS until a newline is reached.
+// Depending on KEEP_NEWLINE, either eat newline from stream or keep
+// it unread.  Characters read are stored and returned as
+// std::string.
+
+std::string
+read_until_newline (std::istream& is, bool keep_newline)
+{
+  if (! is)
+    return std::string ();
+
+  std::ostringstream buf;
+
+  while (is)
+    {
+      char c = is.peek ();
+
+      if (c == '\n' || c == '\r')
+        {
+          // Reached newline.
+          if (! keep_newline)
+            {
+              // Eat the CR or LF character.
+              char d;
+              is.get (d);
+
+              // Make sure that for binary-mode opened ascii files
+              // containing CRLF line endings we skip the LF after
+              // CR.
+
+              if (c == '\r' && is.peek () == '\n')
+                {
+                  // Yes, LF following CR, eat it.
+                  is.get (d);
+                }
+            }
+
+          // Newline was found, and read from stream if
+          // keep_newline == true, so exit loop.
+          break;
+        }
+      else
+        {
+          // No newline charater peeked, so read it, store it, and
+          // proceed to next.
+          char d;
+          is.get (d);
+          buf << d;
+        }
+    }
+
+  return buf.str ();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/ls-ascii-helper.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,38 @@
+/*
+
+Copyright (C) 2009-2012 Benjamin Lindner
+
+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/>.
+
+*/
+
+#if !defined (octave_ls_ascii_helper_h)
+#define octave_ls_ascii_helper_h 1
+
+#include <iosfwd>
+#include <string>
+
+extern OCTINTERP_API void
+skip_until_newline (std::istream& is, bool keep_newline = false);
+
+extern OCTINTERP_API void
+skip_preceeding_newline (std::istream& is);
+
+extern OCTINTERP_API std::string
+read_until_newline (std::istream& is, bool keep_newline = false);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/ls-hdf5.cc	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,921 @@
+/*
+
+Copyright (C) 1996-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+// Author: Steven G. Johnson <stevenj@alum.mit.edu>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#if defined (HAVE_HDF5)
+
+#include <cfloat>
+#include <cstring>
+#include <cctype>
+
+#include <fstream>
+#include <iomanip>
+#include <iostream>
+#include <string>
+#include <vector>
+
+#include "byte-swap.h"
+#include "data-conv.h"
+#include "file-ops.h"
+#include "glob-match.h"
+#include "lo-mappers.h"
+#include "mach-info.h"
+#include "oct-env.h"
+#include "oct-time.h"
+#include "quit.h"
+#include "str-vec.h"
+#include "oct-locbuf.h"
+
+#include "Cell.h"
+#include "defun.h"
+#include "error.h"
+#include "gripes.h"
+#include "load-save.h"
+#include "oct-obj.h"
+#include "oct-map.h"
+#include "ov-cell.h"
+#include "pager.h"
+#include "pt-exp.h"
+#include "sysdep.h"
+#include "unwind-prot.h"
+#include "utils.h"
+#include "variables.h"
+#include "version.h"
+#include "dMatrix.h"
+#include "ov-lazy-idx.h"
+
+#include "ls-utils.h"
+#include "ls-hdf5.h"
+
+static std::string
+make_valid_identifier (const std::string& nm)
+{
+  std::string retval;
+
+  size_t nm_len = nm.length ();
+
+  if (nm_len > 0)
+    {
+      if (! isalpha (nm[0]))
+        retval += '_';
+
+      for (size_t i = 0; i < nm_len; i++)
+        {
+          char c = nm[i];
+          retval += (isalnum (c) || c == '_') ? c : '_';
+        }
+    }
+
+  return retval;
+}
+
+// Define this to 1 if/when HDF5 supports automatic conversion between
+// integer and floating-point binary data:
+#define HAVE_HDF5_INT2FLOAT_CONVERSIONS 0
+
+// Given two compound types t1 and t2, determine whether they
+// are compatible for reading/writing.  This function only
+// works for non-nested types composed of simple elements (ints, floats...),
+// which is all we need it for
+
+bool
+hdf5_types_compatible (hid_t t1, hid_t t2)
+{
+  int n;
+  if ((n = H5Tget_nmembers (t1)) != H5Tget_nmembers (t2))
+    return false;
+
+  for (int i = 0; i < n; ++i)
+    {
+      hid_t mt1 = H5Tget_member_type (t1, i);
+      hid_t mt2 = H5Tget_member_type (t2, i);
+
+      if (H5Tget_class (mt1) != H5Tget_class (mt2))
+        return false;
+
+      H5Tclose (mt2);
+      H5Tclose (mt1);
+    }
+
+  return true;
+}
+
+// Return true if loc_id has the attribute named attr_name, and false
+// otherwise.
+
+bool
+hdf5_check_attr (hid_t loc_id, const char *attr_name)
+{
+  bool retval = false;
+
+  // we have to pull some shenanigans here to make sure
+  // HDF5 doesn't print out all sorts of error messages if we
+  // call H5Aopen for a non-existing attribute
+
+  H5E_auto_t err_func;
+  void *err_func_data;
+
+  // turn off error reporting temporarily, but save the error
+  // reporting function:
+
+#if HAVE_HDF5_18
+  H5Eget_auto (H5E_DEFAULT, &err_func, &err_func_data);
+  H5Eset_auto (H5E_DEFAULT, 0, 0);
+#else
+  H5Eget_auto (&err_func, &err_func_data);
+  H5Eset_auto (0, 0);
+#endif
+
+  hid_t attr_id = H5Aopen_name (loc_id, attr_name);
+
+  if (attr_id >= 0)
+    {
+      // successful
+      retval = true;
+      H5Aclose (attr_id);
+    }
+
+  // restore error reporting:
+#if HAVE_HDF5_18
+  H5Eset_auto (H5E_DEFAULT, err_func, err_func_data);
+#else
+  H5Eset_auto (err_func, err_func_data);
+#endif
+  return retval;
+}
+
+bool
+hdf5_get_scalar_attr (hid_t loc_id, hid_t type_id,
+                      const char *attr_name, void *buf)
+{
+  bool retval = false;
+
+  // we have to pull some shenanigans here to make sure
+  // HDF5 doesn't print out all sorts of error messages if we
+  // call H5Aopen for a non-existing attribute
+
+  H5E_auto_t err_func;
+  void *err_func_data;
+
+  // turn off error reporting temporarily, but save the error
+  // reporting function:
+
+#if HAVE_HDF5_18
+  H5Eget_auto (H5E_DEFAULT, &err_func, &err_func_data);
+  H5Eset_auto (H5E_DEFAULT, 0, 0);
+#else
+  H5Eget_auto (&err_func, &err_func_data);
+  H5Eset_auto (0, 0);
+#endif
+
+  hid_t attr_id = H5Aopen_name (loc_id, attr_name);
+
+  if (attr_id >= 0)
+    {
+      hid_t space_id = H5Aget_space (attr_id);
+
+      hsize_t rank = H5Sget_simple_extent_ndims (space_id);
+
+      if (rank == 0)
+        retval = H5Aread (attr_id, type_id, buf) >= 0;
+      H5Aclose (attr_id);
+    }
+
+  // restore error reporting:
+#if HAVE_HDF5_18
+  H5Eset_auto (H5E_DEFAULT, err_func, err_func_data);
+#else
+  H5Eset_auto (err_func, err_func_data);
+#endif
+  return retval;
+}
+
+
+
+
+// The following subroutines creates an HDF5 representations of the way
+// we will store Octave complex types (pairs of floating-point numbers).
+// NUM_TYPE is the HDF5 numeric type to use for storage (e.g.
+// H5T_NATIVE_DOUBLE to save as 'double'). Note that any necessary
+// conversions are handled automatically by HDF5.
+
+hid_t
+hdf5_make_complex_type (hid_t num_type)
+{
+  hid_t type_id = H5Tcreate (H5T_COMPOUND, sizeof (double) * 2);
+
+  H5Tinsert (type_id, "real", 0 * sizeof (double), num_type);
+  H5Tinsert (type_id, "imag", 1 * sizeof (double), num_type);
+
+  return type_id;
+}
+
+// This function is designed to be passed to H5Giterate, which calls it
+// on each data item in an HDF5 file.  For the item whose name is NAME in
+// the group GROUP_ID, this function sets dv->tc to an Octave representation
+// of that item.  (dv must be a pointer to hdf5_callback_data.)  (It also
+// sets the other fields of dv).
+//
+// It returns 1 on success (in which case H5Giterate stops and returns),
+// -1 on error, and 0 to tell H5Giterate to continue on to the next item
+// (e.g. if NAME was a data type we don't recognize).
+
+herr_t
+hdf5_read_next_data (hid_t group_id, const char *name, void *dv)
+{
+  hdf5_callback_data *d = static_cast <hdf5_callback_data *> (dv);
+  hid_t type_id = -1, type_class_id = -1, data_id = -1, subgroup_id = -1,
+    space_id = -1;
+
+  H5G_stat_t info;
+  herr_t retval = 0;
+  bool ident_valid = valid_identifier (name);
+
+  std::string vname = name;
+
+  // Allow identifiers as all digits so we can load lists saved by
+  // earlier versions of Octave.
+
+  if (! ident_valid )
+    {
+      // fix the identifier, replacing invalid chars with underscores
+      vname = make_valid_identifier (vname);
+
+      // check again (in case vname was null, empty, or some such thing):
+      ident_valid = valid_identifier (vname);
+    }
+
+  H5Gget_objinfo (group_id, name, 1, &info);
+
+  if (info.type == H5G_GROUP && ident_valid)
+    {
+#if HAVE_HDF5_18
+      subgroup_id = H5Gopen (group_id, name, H5P_DEFAULT);
+#else
+      subgroup_id = H5Gopen (group_id, name);
+#endif
+
+      if (subgroup_id < 0)
+        {
+          retval = subgroup_id;
+          goto done;
+        }
+
+      if (hdf5_check_attr (subgroup_id, "OCTAVE_NEW_FORMAT"))
+        {
+#if HAVE_HDF5_18
+          data_id = H5Dopen (subgroup_id, "type", H5P_DEFAULT);
+#else
+          data_id = H5Dopen (subgroup_id, "type");
+#endif
+
+          if (data_id < 0)
+            {
+              retval = data_id;
+              goto done;
+            }
+
+          type_id = H5Dget_type (data_id);
+
+          type_class_id = H5Tget_class (type_id);
+
+          if (type_class_id != H5T_STRING)
+            goto done;
+
+          space_id = H5Dget_space (data_id);
+          hsize_t rank = H5Sget_simple_extent_ndims (space_id);
+
+          if (rank != 0)
+            goto done;
+
+          int slen = H5Tget_size (type_id);
+          if (slen < 0)
+            goto done;
+
+          OCTAVE_LOCAL_BUFFER (char, typ, slen);
+
+          // create datatype for (null-terminated) string to read into:
+          hid_t st_id = H5Tcopy (H5T_C_S1);
+          H5Tset_size (st_id, slen);
+
+          if (H5Dread (data_id, st_id, H5S_ALL, H5S_ALL, H5P_DEFAULT,
+                       typ) < 0)
+            goto done;
+
+          H5Tclose (st_id);
+          H5Dclose (data_id);
+
+          d->tc = octave_value_typeinfo::lookup_type (typ);
+
+          retval = (d->tc.load_hdf5 (subgroup_id, "value") ? 1 : -1);
+
+          // check for OCTAVE_GLOBAL attribute:
+          d->global = hdf5_check_attr (subgroup_id, "OCTAVE_GLOBAL");
+
+          H5Gclose (subgroup_id);
+        }
+      else
+        {
+          // an HDF5 group is treated as an octave structure by
+          // default (since that preserves name information), and an
+          // octave list otherwise.
+
+          if (hdf5_check_attr (subgroup_id, "OCTAVE_LIST"))
+            d->tc = octave_value_typeinfo::lookup_type ("list");
+          else
+            d->tc = octave_value_typeinfo::lookup_type ("struct");
+
+          // check for OCTAVE_GLOBAL attribute:
+          d->global = hdf5_check_attr (subgroup_id, "OCTAVE_GLOBAL");
+
+          H5Gclose (subgroup_id);
+
+          retval = (d->tc.load_hdf5 (group_id, name) ? 1 : -1);
+        }
+
+    }
+  else if (info.type == H5G_DATASET && ident_valid)
+    {
+      // For backwards compatiability.
+#if HAVE_HDF5_18
+      data_id = H5Dopen (group_id, name, H5P_DEFAULT);
+#else
+      data_id = H5Dopen (group_id, name);
+#endif
+
+      if (data_id < 0)
+        {
+          retval = data_id;
+          goto done;
+        }
+
+      type_id = H5Dget_type (data_id);
+
+      type_class_id = H5Tget_class (type_id);
+
+      if (type_class_id == H5T_FLOAT)
+        {
+          space_id = H5Dget_space (data_id);
+
+          hsize_t rank = H5Sget_simple_extent_ndims (space_id);
+
+          if (rank == 0)
+            d->tc = octave_value_typeinfo::lookup_type ("scalar");
+          else
+            d->tc = octave_value_typeinfo::lookup_type ("matrix");
+
+          H5Sclose (space_id);
+        }
+      else if (type_class_id == H5T_INTEGER)
+        {
+          // What integer type do we really have..
+          std::string int_typ;
+#ifdef HAVE_H5T_GET_NATIVE_TYPE
+          // FIXME test this code and activated with an autoconf
+          // test!! It is also incorrect for 64-bit indexing!!
+
+          switch (H5Tget_native_type (type_id, H5T_DIR_ASCEND))
+            {
+            case H5T_NATIVE_CHAR:
+              int_typ = "int8 ";
+              break;
+
+            case H5T_NATIVE_SHORT:
+              int_typ = "int16 ";
+              break;
+
+            case H5T_NATIVE_INT:
+            case H5T_NATIVE_LONG:
+              int_typ = "int32 ";
+              break;
+
+            case H5T_NATIVE_LLONG:
+              int_typ = "int64 ";
+              break;
+
+            case H5T_NATIVE_UCHAR:
+              int_typ = "uint8 ";
+              break;
+
+            case H5T_NATIVE_USHORT:
+              int_typ = "uint16 ";
+              break;
+
+            case H5T_NATIVE_UINT:
+            case H5T_NATIVE_ULONG:
+              int_typ = "uint32 ";
+              break;
+
+            case H5T_NATIVE_ULLONG:
+              int_typ = "uint64 ";
+              break;
+            }
+#else
+          hid_t int_sign = H5Tget_sign (type_id);
+
+          if (int_sign == H5T_SGN_ERROR)
+            warning ("load: can't read `%s' (unknown datatype)", name);
+          else
+            {
+              if (int_sign == H5T_SGN_NONE)
+                int_typ.append ("u");
+              int_typ.append ("int");
+
+              int slen = H5Tget_size (type_id);
+              if (slen < 0)
+                warning ("load: can't read `%s' (unknown datatype)", name);
+              else
+                {
+                  switch (slen)
+                    {
+                    case 1:
+                      int_typ.append ("8 ");
+                      break;
+
+                    case 2:
+                      int_typ.append ("16 ");
+                      break;
+
+                    case 4:
+                      int_typ.append ("32 ");
+                      break;
+
+                    case 8:
+                      int_typ.append ("64 ");
+                      break;
+
+                    default:
+                      warning ("load: can't read `%s' (unknown datatype)",
+                               name);
+                      int_typ = "";
+                      break;
+                    }
+                }
+            }
+#endif
+          if (int_typ == "")
+            warning ("load: can't read `%s' (unknown datatype)", name);
+          else
+            {
+              // Matrix or scalar?
+              space_id = H5Dget_space (data_id);
+
+              hsize_t rank = H5Sget_simple_extent_ndims (space_id);
+
+              if (rank == 0)
+                int_typ.append ("scalar");
+              else
+                int_typ.append ("matrix");
+
+              d->tc = octave_value_typeinfo::lookup_type (int_typ);
+              H5Sclose (space_id);
+            }
+        }
+      else if (type_class_id == H5T_STRING)
+        d->tc = octave_value_typeinfo::lookup_type ("string");
+      else if (type_class_id == H5T_COMPOUND)
+        {
+          hid_t complex_type = hdf5_make_complex_type (H5T_NATIVE_DOUBLE);
+
+          if (hdf5_types_compatible (type_id, complex_type))
+            {
+              // read complex matrix or scalar variable
+              space_id = H5Dget_space (data_id);
+              hsize_t rank = H5Sget_simple_extent_ndims (space_id);
+
+              if (rank == 0)
+                d->tc = octave_value_typeinfo::lookup_type ("complex scalar");
+              else
+                d->tc = octave_value_typeinfo::lookup_type ("complex matrix");
+
+              H5Sclose (space_id);
+            }
+          else
+            // Assume that if its not complex its a range. If its not
+            // it'll be rejected later in the range code
+            d->tc = octave_value_typeinfo::lookup_type ("range");
+
+          H5Tclose (complex_type);
+        }
+      else
+        {
+          warning ("load: can't read `%s' (unknown datatype)", name);
+          retval = 0; // unknown datatype; skip
+        }
+
+      // check for OCTAVE_GLOBAL attribute:
+      d->global = hdf5_check_attr (data_id, "OCTAVE_GLOBAL");
+
+      H5Tclose (type_id);
+      H5Dclose (data_id);
+
+      retval = (d->tc.load_hdf5 (group_id, name) ? 1 : -1);
+    }
+
+  if (!ident_valid)
+    {
+      // should we attempt to handle invalid identifiers by converting
+      // bad characters to '_', say?
+      warning ("load: skipping invalid identifier `%s' in hdf5 file",
+               name);
+    }
+
+ done:
+  if (retval < 0)
+    error ("load: error while reading hdf5 item %s", name);
+
+  if (retval > 0)
+    {
+      // get documentation string, if any:
+      int comment_length = H5Gget_comment (group_id, name, 0, 0);
+
+      if (comment_length > 1)
+        {
+          OCTAVE_LOCAL_BUFFER (char, tdoc, comment_length);
+          H5Gget_comment (group_id, name, comment_length, tdoc);
+          d->doc = tdoc;
+        }
+      else if (vname != name)
+        {
+          // the name was changed; store the original name
+          // as the documentation string:
+          d->doc = name;
+        }
+
+      // copy name (actually, vname):
+      d->name = vname;
+    }
+
+  return retval;
+}
+
+// Read the next Octave variable from the stream IS, which must really be
+// an hdf5_ifstream.  Return the variable value in tc, its doc string
+// in doc, and whether it is global in global.  The return value is
+// the name of the variable, or NULL if none were found or there was
+// and error.
+std::string
+read_hdf5_data (std::istream& is, const std::string& /* filename */,
+                bool& global, octave_value& tc, std::string& doc)
+{
+  std::string retval;
+
+  doc.resize (0);
+
+  hdf5_ifstream& hs = dynamic_cast<hdf5_ifstream&> (is);
+  hdf5_callback_data d;
+
+  herr_t H5Giterate_retval = -1;
+
+  hsize_t num_obj = 0;
+#if HAVE_HDF5_18
+  hid_t group_id = H5Gopen (hs.file_id, "/", H5P_DEFAULT);
+#else
+  hid_t group_id = H5Gopen (hs.file_id, "/");
+#endif
+  H5Gget_num_objs (group_id, &num_obj);
+  H5Gclose (group_id);
+  if (hs.current_item < static_cast<int> (num_obj))
+    H5Giterate_retval = H5Giterate (hs.file_id, "/", &hs.current_item,
+                                    hdf5_read_next_data, &d);
+
+  if (H5Giterate_retval > 0)
+    {
+      global = d.global;
+      tc = d.tc;
+      doc = d.doc;
+    }
+  else
+    {
+      // an error occurred (H5Giterate_retval < 0) or there are no
+      // more datasets print an error message if retval < 0?
+      // hdf5_read_next_data already printed one, probably.
+    }
+
+  if (! d.name.empty ())
+    retval = d.name;
+
+  return retval;
+}
+
+// Add an attribute named attr_name to loc_id (a simple scalar
+// attribute with value 1).  Return value is >= 0 on success.
+herr_t
+hdf5_add_attr (hid_t loc_id, const char *attr_name)
+{
+  herr_t retval = 0;
+
+  hid_t as_id = H5Screate (H5S_SCALAR);
+
+  if (as_id >= 0)
+    {
+#if HAVE_HDF5_18
+      hid_t a_id = H5Acreate (loc_id, attr_name, H5T_NATIVE_UCHAR,
+                              as_id, H5P_DEFAULT, H5P_DEFAULT);
+#else
+      hid_t a_id = H5Acreate (loc_id, attr_name,
+                              H5T_NATIVE_UCHAR, as_id, H5P_DEFAULT);
+#endif
+      if (a_id >= 0)
+        {
+          unsigned char attr_val = 1;
+
+          retval = H5Awrite (a_id, H5T_NATIVE_UCHAR, &attr_val);
+
+          H5Aclose (a_id);
+        }
+      else
+        retval = a_id;
+
+      H5Sclose (as_id);
+    }
+  else
+    retval = as_id;
+
+  return retval;
+}
+
+herr_t
+hdf5_add_scalar_attr (hid_t loc_id, hid_t type_id,
+                      const char *attr_name, void *buf)
+{
+  herr_t retval = 0;
+
+  hid_t as_id = H5Screate (H5S_SCALAR);
+
+  if (as_id >= 0)
+    {
+#if HAVE_HDF5_18
+      hid_t a_id = H5Acreate (loc_id, attr_name, type_id,
+                              as_id, H5P_DEFAULT, H5P_DEFAULT);
+#else
+      hid_t a_id = H5Acreate (loc_id, attr_name,
+                              type_id, as_id, H5P_DEFAULT);
+#endif
+      if (a_id >= 0)
+        {
+          retval = H5Awrite (a_id, type_id, buf);
+
+          H5Aclose (a_id);
+        }
+      else
+        retval = a_id;
+
+      H5Sclose (as_id);
+    }
+  else
+    retval = as_id;
+
+  return retval;
+}
+
+// Save an empty matrix, if needed. Returns
+//    > 0  Saved empty matrix
+//    = 0  Not an empty matrix; did nothing
+//    < 0  Error condition
+int
+save_hdf5_empty (hid_t loc_id, const char *name, const dim_vector d)
+{
+  hsize_t sz = d.length ();
+  OCTAVE_LOCAL_BUFFER (octave_idx_type, dims, sz);
+  bool empty = false;
+  hid_t space_hid = -1, data_hid = -1;
+  int retval;
+  for (hsize_t i = 0; i < sz; i++)
+    {
+      dims[i] = d(i);
+      if (dims[i] < 1)
+        empty = true;
+    }
+
+  if (!empty)
+    return 0;
+
+  space_hid = H5Screate_simple (1, &sz, 0);
+  if (space_hid < 0) return space_hid;
+#if HAVE_HDF5_18
+  data_hid = H5Dcreate (loc_id, name, H5T_NATIVE_IDX, space_hid,
+                        H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+#else
+  data_hid = H5Dcreate (loc_id, name, H5T_NATIVE_IDX, space_hid,
+                        H5P_DEFAULT);
+#endif
+  if (data_hid < 0)
+    {
+      H5Sclose (space_hid);
+      return data_hid;
+    }
+
+  retval = H5Dwrite (data_hid, H5T_NATIVE_IDX, H5S_ALL, H5S_ALL,
+                     H5P_DEFAULT, dims) >= 0;
+
+  H5Dclose (data_hid);
+  H5Sclose (space_hid);
+
+  if (retval >= 0)
+    retval = hdf5_add_attr (loc_id, "OCTAVE_EMPTY_MATRIX");
+
+  return (retval == 0 ? 1 : retval);
+}
+
+// Load an empty matrix, if needed. Returns
+//    > 0  loaded empty matrix, dimensions returned
+//    = 0  Not an empty matrix; did nothing
+//    < 0  Error condition
+int
+load_hdf5_empty (hid_t loc_id, const char *name, dim_vector &d)
+{
+  if (! hdf5_check_attr (loc_id, "OCTAVE_EMPTY_MATRIX"))
+    return 0;
+
+  hsize_t hdims, maxdims;
+#if HAVE_HDF5_18
+  hid_t data_hid = H5Dopen (loc_id, name, H5P_DEFAULT);
+#else
+  hid_t data_hid = H5Dopen (loc_id, name);
+#endif
+  hid_t space_id = H5Dget_space (data_hid);
+  H5Sget_simple_extent_dims (space_id, &hdims, &maxdims);
+  int retval;
+
+  OCTAVE_LOCAL_BUFFER (octave_idx_type, dims, hdims);
+
+  retval = H5Dread (data_hid, H5T_NATIVE_IDX, H5S_ALL, H5S_ALL,
+                    H5P_DEFAULT, dims);
+  if (retval >= 0)
+    {
+      d.resize (hdims);
+      for (hsize_t i = 0; i < hdims; i++)
+        d(i) = dims[i];
+    }
+
+  H5Sclose (space_id);
+  H5Dclose (data_hid);
+
+  return (retval == 0 ? hdims : retval);
+}
+
+// save_type_to_hdf5 is not currently used, since hdf5 doesn't yet support
+// automatic float<->integer conversions:
+
+#if HAVE_HDF5_INT2FLOAT_CONVERSIONS
+
+// return the HDF5 type id corresponding to the Octave save_type
+
+hid_t
+save_type_to_hdf5 (save_type st)
+{
+  switch (st)
+    {
+    case LS_U_CHAR:
+      return H5T_NATIVE_UCHAR;
+
+    case LS_U_SHORT:
+      return H5T_NATIVE_USHORT;
+
+    case LS_U_INT:
+      return H5T_NATIVE_UINT;
+
+    case LS_CHAR:
+      return H5T_NATIVE_CHAR;
+
+    case LS_SHORT:
+      return H5T_NATIVE_SHORT;
+
+    case LS_INT:
+      return H5T_NATIVE_INT;
+
+    case LS_FLOAT:
+      return H5T_NATIVE_FLOAT;
+
+    case LS_DOUBLE:
+    default:
+      return H5T_NATIVE_DOUBLE;
+    }
+}
+#endif /* HAVE_HDF5_INT2FLOAT_CONVERSIONS */
+
+// Add the data from TC to the HDF5 location loc_id, which could
+// be either a file or a group within a file.  Return true if
+// successful.  This function calls itself recursively for lists
+// (stored as HDF5 groups).
+
+bool
+add_hdf5_data (hid_t loc_id, const octave_value& tc,
+               const std::string& name, const std::string& doc,
+               bool mark_as_global, bool save_as_floats)
+{
+  hsize_t dims[3];
+  hid_t type_id = -1, space_id = -1, data_id = -1, data_type_id = -1;
+  bool retval = false;
+  octave_value val = tc;
+  // FIXME: diagonal & permutation matrices currently don't know how to save
+  // themselves, so we convert them first to normal matrices using A = A(:,:).
+  // This is a temporary hack.
+  if (val.is_diag_matrix () || val.is_perm_matrix ()
+      || val.type_id () == octave_lazy_index::static_type_id ())
+    val = val.full_value ();
+
+  std::string t = val.type_name ();
+#if HAVE_HDF5_18
+  data_id = H5Gcreate (loc_id, name.c_str (), H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+#else
+  data_id = H5Gcreate (loc_id, name.c_str (), 0);
+#endif
+  if (data_id < 0)
+    goto error_cleanup;
+
+  // attach the type of the variable
+  type_id = H5Tcopy (H5T_C_S1); H5Tset_size (type_id, t.length () + 1);
+  if (type_id < 0)
+    goto error_cleanup;
+
+  dims[0] = 0;
+  space_id = H5Screate_simple (0 , dims, 0);
+  if (space_id < 0)
+    goto error_cleanup;
+#if HAVE_HDF5_18
+  data_type_id = H5Dcreate (data_id, "type",  type_id, space_id,
+                            H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+#else
+  data_type_id = H5Dcreate (data_id, "type",  type_id, space_id, H5P_DEFAULT);
+#endif
+  if (data_type_id < 0 || H5Dwrite (data_type_id, type_id, H5S_ALL, H5S_ALL,
+                                    H5P_DEFAULT, t.c_str ()) < 0)
+    goto error_cleanup;
+
+  // Now call the real function to save the variable
+  retval = val.save_hdf5 (data_id, "value", save_as_floats);
+
+  // attach doc string as comment:
+  if (retval && doc.length () > 0
+      && H5Gset_comment (loc_id, name.c_str (), doc.c_str ()) < 0)
+    retval = false;
+
+  // if it's global, add an attribute "OCTAVE_GLOBAL" with value 1
+  if (retval && mark_as_global)
+    retval = hdf5_add_attr (data_id, "OCTAVE_GLOBAL") >= 0;
+
+  // We are saving in the new variable format, so mark it
+  if (retval)
+    retval = hdf5_add_attr (data_id, "OCTAVE_NEW_FORMAT") >= 0;
+
+ error_cleanup:
+
+  if (data_type_id >= 0)
+    H5Dclose (data_type_id);
+
+  if (type_id >= 0)
+    H5Tclose (type_id);
+
+  if (space_id >= 0)
+    H5Sclose (space_id);
+
+  if (data_id >= 0)
+    H5Gclose (data_id);
+
+  if (! retval)
+    error ("save: error while writing `%s' to hdf5 file", name.c_str ());
+
+  return retval;
+}
+
+// Write data from TC in HDF5 (binary) format to the stream OS,
+// which must be an hdf5_ofstream, returning true on success.
+
+bool
+save_hdf5_data (std::ostream& os, const octave_value& tc,
+                const std::string& name, const std::string& doc,
+                bool mark_as_global, bool save_as_floats)
+{
+  hdf5_ofstream& hs = dynamic_cast<hdf5_ofstream&> (os);
+
+  return add_hdf5_data (hs.file_id, tc, name, doc,
+                        mark_as_global, save_as_floats);
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/ls-hdf5.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,213 @@
+/*
+
+Copyright (C) 2003-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if !defined (octave_ls_hdf5_h)
+#define octave_ls_hdf5_h 1
+
+#if defined (HAVE_HDF5)
+
+#include "oct-hdf5.h"
+
+// first, we need to define our own dummy stream subclass, since
+// HDF5 needs to do its own file i/o
+
+// hdf5_fstreambase is used for both input and output streams, modeled
+// on the fstreambase class in <fstream.h>
+
+class hdf5_fstreambase : virtual public std::ios
+{
+public:
+
+  // HDF5 uses an "id" to refer to an open file
+  hid_t file_id;
+
+  // keep track of current item index in the file
+  int current_item;
+
+  hdf5_fstreambase () : file_id (-1), current_item () { }
+
+  ~hdf5_fstreambase () { close (); }
+
+  hdf5_fstreambase (const char *name, int mode, int /* prot */ = 0)
+    : file_id (-1), current_item (-1)
+    {
+      if (mode & std::ios::in)
+        file_id = H5Fopen (name, H5F_ACC_RDONLY, H5P_DEFAULT);
+      else if (mode & std::ios::out)
+        {
+          if (mode & std::ios::app && H5Fis_hdf5 (name) > 0)
+            file_id = H5Fopen (name, H5F_ACC_RDWR, H5P_DEFAULT);
+          else
+            file_id = H5Fcreate (name, H5F_ACC_TRUNC, H5P_DEFAULT,
+                                 H5P_DEFAULT);
+        }
+      if (file_id < 0)
+        std::ios::setstate (std::ios::badbit);
+
+      current_item = 0;
+    }
+
+  void close ()
+    {
+      if (file_id >= 0)
+        {
+          if (H5Fclose (file_id) < 0)
+            std::ios::setstate (std::ios::badbit);
+          file_id = -1;
+        }
+    }
+
+  void open (const char *name, int mode, int)
+    {
+      clear ();
+
+      if (mode & std::ios::in)
+        file_id = H5Fopen (name, H5F_ACC_RDONLY, H5P_DEFAULT);
+      else if (mode & std::ios::out)
+        {
+          if (mode & std::ios::app && H5Fis_hdf5 (name) > 0)
+            file_id = H5Fopen (name, H5F_ACC_RDWR, H5P_DEFAULT);
+          else
+            file_id = H5Fcreate (name, H5F_ACC_TRUNC, H5P_DEFAULT,
+                                 H5P_DEFAULT);
+        }
+      if (file_id < 0)
+        std::ios::setstate (std::ios::badbit);
+
+      current_item = 0;
+    }
+};
+
+// input and output streams, subclassing istream and ostream
+// so that we can pass them for stream parameters in the functions below.
+
+class hdf5_ifstream : public hdf5_fstreambase, public std::istream
+{
+public:
+
+  hdf5_ifstream () : hdf5_fstreambase (), std::istream (0) { }
+
+  hdf5_ifstream (const char *name, int mode = std::ios::in|std::ios::binary,
+                 int prot = 0)
+    : hdf5_fstreambase (name, mode, prot), std::istream (0) { }
+
+  void open (const char *name, int mode = std::ios::in|std::ios::binary,
+             int prot = 0)
+    { hdf5_fstreambase::open (name, mode, prot); }
+};
+
+class hdf5_ofstream : public hdf5_fstreambase, public std::ostream
+{
+public:
+
+  hdf5_ofstream () : hdf5_fstreambase (), std::ostream (0) { }
+
+  hdf5_ofstream (const char *name, int mode = std::ios::out|std::ios::binary,
+                 int prot = 0)
+    : hdf5_fstreambase (name, mode, prot), std::ostream (0) { }
+
+  void open (const char *name, int mode = std::ios::out|std::ios::binary,
+             int prot = 0)
+    { hdf5_fstreambase::open (name, mode, prot); }
+};
+
+// Callback data structure for passing data to hdf5_read_next_data, below.
+
+struct
+hdf5_callback_data
+{
+  hdf5_callback_data (void)
+    : name (), global (false), tc (), doc () { }
+
+  // the following fields are set by hdf5_read_data on successful return:
+
+  // the name of the variable
+  std::string name;
+
+  // whether it is global
+  bool global;
+
+  // the value of the variable, in Octave form
+  octave_value tc;
+
+  // a documentation string (NULL if none)
+  std::string doc;
+};
+
+#if HAVE_HDF5_INT2FLOAT_CONVERSIONS
+extern OCTINTERP_API hid_t
+save_type_to_hdf5 (save_type st)
+#endif
+
+extern OCTINTERP_API hid_t
+hdf5_make_complex_type (hid_t num_type);
+
+extern OCTINTERP_API bool
+hdf5_types_compatible (hid_t t1, hid_t t2);
+
+extern OCTINTERP_API herr_t
+hdf5_read_next_data (hid_t group_id, const char *name, void *dv);
+
+extern OCTINTERP_API bool
+add_hdf5_data (hid_t loc_id, const octave_value& tc,
+               const std::string& name, const std::string& doc,
+               bool mark_as_global, bool save_as_floats);
+
+extern OCTINTERP_API int
+save_hdf5_empty (hid_t loc_id, const char *name, const dim_vector d);
+
+extern OCTINTERP_API int
+load_hdf5_empty (hid_t loc_id, const char *name, dim_vector &d);
+
+extern OCTINTERP_API std::string
+read_hdf5_data (std::istream& is,  const std::string& filename, bool& global,
+                octave_value& tc, std::string& doc);
+
+extern OCTINTERP_API bool
+save_hdf5_data (std::ostream& os, const octave_value& tc,
+                const std::string& name, const std::string& doc,
+                bool mark_as_global, bool save_as_floats);
+
+extern OCTINTERP_API bool
+hdf5_check_attr (hid_t loc_id, const char *attr_name);
+
+extern OCTINTERP_API bool
+hdf5_get_scalar_attr (hid_t loc_id, hid_t type_id, const char *attr_name,
+                      void *buf);
+
+extern OCTINTERP_API herr_t
+hdf5_add_attr (hid_t loc_id, const char *attr_name);
+
+
+extern OCTINTERP_API herr_t
+hdf5_add_scalar_attr (hid_t loc_id, hid_t type_id,
+                      const char *attr_name, void *buf);
+
+#ifdef IDX_TYPE_LONG
+#define H5T_NATIVE_IDX H5T_NATIVE_LONG
+#else
+#define H5T_NATIVE_IDX H5T_NATIVE_INT
+#endif
+
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/ls-mat-ascii.cc	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,378 @@
+/*
+
+Copyright (C) 1996-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <cfloat>
+#include <cstring>
+#include <cctype>
+
+#include <fstream>
+#include <iomanip>
+#include <iostream>
+#include <sstream>
+#include <string>
+
+#include "byte-swap.h"
+#include "data-conv.h"
+#include "file-ops.h"
+#include "glob-match.h"
+#include "lo-mappers.h"
+#include "mach-info.h"
+#include "oct-env.h"
+#include "oct-time.h"
+#include "quit.h"
+#include "str-vec.h"
+
+#include "Cell.h"
+#include "defun.h"
+#include "error.h"
+#include "gripes.h"
+#include "lex.h"
+#include "load-save.h"
+#include "ls-ascii-helper.h"
+#include "ls-mat-ascii.h"
+#include "oct-obj.h"
+#include "oct-map.h"
+#include "ov-cell.h"
+#include "pager.h"
+#include "pt-exp.h"
+#include "sysdep.h"
+#include "unwind-prot.h"
+#include "utils.h"
+#include "variables.h"
+#include "version.h"
+#include "dMatrix.h"
+
+static std::string
+get_mat_data_input_line (std::istream& is)
+{
+  std::string retval;
+
+  bool have_data = false;
+
+  do
+    {
+      retval = "";
+
+      char c;
+      while (is.get (c))
+        {
+          if (c == '\n' || c == '\r')
+            {
+              is.putback (c);
+              skip_preceeding_newline (is);
+              break;
+            }
+
+          if (c == '%' || c == '#')
+            {
+              skip_until_newline (is, false);
+              break;
+            }
+
+          if (! is.eof ())
+            {
+              if (! have_data && c != ' ' && c != '\t')
+                have_data = true;
+
+              retval += c;
+            }
+        }
+    }
+  while (! (have_data || is.eof ()));
+
+  return retval;
+}
+
+static void
+get_lines_and_columns (std::istream& is, const std::string& filename, octave_idx_type& nr, octave_idx_type& nc)
+{
+  std::streampos pos = is.tellg ();
+
+  int file_line_number = 0;
+
+  nr = 0;
+  nc = 0;
+
+  while (is && ! error_state)
+    {
+      octave_quit ();
+
+      std::string buf = get_mat_data_input_line (is);
+
+      file_line_number++;
+
+      size_t beg = buf.find_first_not_of (", \t");
+
+      // If we see a CR as the last character in the buffer, we had a
+      // CRLF pair as the line separator.  Any other CR in the text
+      // will not be considered as whitespace.
+
+      if (beg != std::string::npos && buf[beg] == '\r' && beg == buf.length () - 1)
+        {
+          // We had a blank line ending with a CRLF.  Handle it the
+          // same as an empty line.
+          beg = std::string::npos;
+        }
+
+      octave_idx_type tmp_nc = 0;
+
+      while (beg != std::string::npos)
+        {
+          tmp_nc++;
+
+          size_t end = buf.find_first_of (", \t", beg);
+
+          if (end != std::string::npos)
+            {
+              beg = buf.find_first_not_of (", \t", end);
+
+              if (beg == std::string::npos || (buf[beg] == '\r' &&
+                                  beg == buf.length () - 1))
+                {
+                  // We had a line with trailing spaces and
+                  // ending with a CRLF, so this should look like EOL,
+                  // not a new colum.
+                  break;
+                }
+            }
+          else
+            break;
+        }
+
+      if (tmp_nc > 0)
+        {
+          if (nc == 0)
+            {
+              nc = tmp_nc;
+              nr++;
+            }
+          else if (nc == tmp_nc)
+            nr++;
+          else
+            error ("load: %s: inconsistent number of columns near line %d",
+                   filename.c_str (), file_line_number);
+        }
+    }
+
+  if (nr == 0 || nc == 0)
+    error ("load: file `%s' seems to be empty!", filename.c_str ());
+
+  is.clear ();
+  is.seekg (pos);
+}
+
+// Extract a matrix from a file of numbers only.
+//
+// Comments are not allowed.  The file should only have numeric values.
+//
+// Reads the file twice.  Once to find the number of rows and columns,
+// and once to extract the matrix.
+//
+// FILENAME is used for error messages.
+//
+// This format provides no way to tag the data as global.
+
+std::string
+read_mat_ascii_data (std::istream& is, const std::string& filename,
+                     octave_value& tc)
+{
+  std::string retval;
+
+  std::string varname;
+
+  size_t pos = filename.rfind ('/');
+
+  if (pos != std::string::npos)
+    varname = filename.substr (pos+1);
+  else
+    varname = filename;
+
+  pos = varname.rfind ('.');
+
+  if (pos != std::string::npos)
+    varname = varname.substr (0, pos);
+
+  size_t len = varname.length ();
+  for (size_t i = 0; i < len; i++)
+    {
+      char c = varname[i];
+      if (! (isalnum (c) || c == '_'))
+        varname[i] = '_';
+    }
+
+  if (is_keyword (varname) || ! isalpha (varname[0]))
+    varname.insert (0, "X");
+
+  if (valid_identifier (varname))
+    {
+      octave_idx_type nr = 0;
+      octave_idx_type nc = 0;
+
+      int total_count = 0;
+
+      get_lines_and_columns (is, filename, nr, nc);
+
+      octave_quit ();
+
+      if (! error_state && nr > 0 && nc > 0)
+        {
+          Matrix tmp (nr, nc);
+
+          if (nr < 1 || nc < 1)
+            is.clear (std::ios::badbit);
+          else
+            {
+              double d;
+              for (octave_idx_type i = 0; i < nr; i++)
+                {
+                  std::string buf = get_mat_data_input_line (is);
+
+                  std::istringstream tmp_stream (buf);
+
+                  for (octave_idx_type j = 0; j < nc; j++)
+                    {
+                      octave_quit ();
+
+                      d = octave_read_value<double> (tmp_stream);
+
+                      if (tmp_stream || tmp_stream.eof ())
+                        {
+                          tmp.elem (i, j) = d;
+                          total_count++;
+
+                          // Skip whitespace and commas.
+                          char c;
+                          while (1)
+                            {
+                              tmp_stream >> c;
+
+                              if (! tmp_stream)
+                                break;
+
+                              if (! (c == ' ' || c == '\t' || c == ','))
+                                {
+                                  tmp_stream.putback (c);
+                                  break;
+                                }
+                            }
+
+                          if (tmp_stream.eof ())
+                            break;
+                        }
+                      else
+                        {
+                          error ("load: failed to read matrix from file `%s'",
+                                 filename.c_str ());
+
+                          return retval;
+                        }
+
+                    }
+                }
+            }
+
+          if (is || is.eof ())
+            {
+              // FIXME -- not sure this is best, but it works.
+
+              if (is.eof ())
+                is.clear ();
+
+              octave_idx_type expected = nr * nc;
+
+              if (expected == total_count)
+                {
+                  tc = tmp;
+                  retval = varname;
+                }
+              else
+                error ("load: expected %d elements, found %d",
+                       expected, total_count);
+            }
+          else
+            error ("load: failed to read matrix from file `%s'",
+                   filename.c_str ());
+        }
+      else
+        error ("load: unable to extract matrix size from file `%s'",
+               filename.c_str ());
+    }
+  else
+    error ("load: unable to convert filename `%s' to valid identifier",
+           filename.c_str ());
+
+  return retval;
+}
+
+bool
+save_mat_ascii_data (std::ostream& os, const octave_value& val,
+                     int precision, bool tabs)
+{
+  bool success = true;
+
+  if (val.is_complex_type ())
+    warning ("save: omitting imaginary part for ASCII file");
+
+  Matrix m = val.matrix_value (true);
+
+  if (error_state)
+    {
+      success = false;
+
+      error_state = 0;
+    }
+  else
+    {
+      long old_precision = os.precision ();
+
+      os.precision (precision);
+
+      std::ios::fmtflags oflags
+        = os.flags (static_cast<std::ios::fmtflags> (std::ios::scientific));
+
+      if (tabs)
+        {
+          for (octave_idx_type i = 0; i < m.rows (); i++)
+            {
+              for (octave_idx_type j = 0; j < m.cols (); j++)
+                {
+                  // Omit leading tabs.
+                  if (j != 0) os << '\t';
+                  octave_write_double (os, m (i, j));
+                }
+              os << "\n";
+            }
+        }
+      else
+        os << m;
+
+      os.flags (oflags);
+
+      os.precision (old_precision);
+    }
+
+  return (os && success);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/ls-mat-ascii.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,34 @@
+/*
+
+Copyright (C) 2003-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if !defined (octave_ls_mat_ascii_h)
+#define octave_ls_mat_ascii_h 1
+
+extern std::string
+read_mat_ascii_data (std::istream& is, const std::string& filename,
+                     octave_value& tc);
+
+extern bool
+save_mat_ascii_data (std::ostream& os, const octave_value& val_arg,
+                     int precision, bool tabs = false);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/ls-mat4.cc	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,609 @@
+/*
+
+Copyright (C) 1996-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <cfloat>
+#include <cstring>
+#include <cctype>
+
+#include <fstream>
+#include <iomanip>
+#include <iostream>
+#include <string>
+#include <vector>
+
+#include "byte-swap.h"
+#include "data-conv.h"
+#include "file-ops.h"
+#include "glob-match.h"
+#include "lo-mappers.h"
+#include "mach-info.h"
+#include "oct-env.h"
+#include "oct-time.h"
+#include "quit.h"
+#include "str-vec.h"
+#include "oct-locbuf.h"
+
+#include "Cell.h"
+#include "defun.h"
+#include "error.h"
+#include "gripes.h"
+#include "load-save.h"
+#include "oct-obj.h"
+#include "oct-map.h"
+#include "ov-cell.h"
+#include "pager.h"
+#include "pt-exp.h"
+#include "sysdep.h"
+#include "unwind-prot.h"
+#include "utils.h"
+#include "variables.h"
+#include "version.h"
+#include "dMatrix.h"
+#include "dSparse.h"
+
+#include "ls-mat4.h"
+
+// Read LEN elements of data from IS in the format specified by
+// PRECISION, placing the result in DATA.  If SWAP is TRUE, swap
+// the bytes of each element before copying to DATA.  FLT_FMT
+// specifies the format of the data if we are reading floating point
+// numbers.
+
+static void
+read_mat_binary_data (std::istream& is, double *data, int precision,
+                      int len, bool swap,
+                      oct_mach_info::float_format flt_fmt)
+{
+  switch (precision)
+    {
+    case 0:
+      read_doubles (is, data, LS_DOUBLE, len, swap, flt_fmt);
+      break;
+
+    case 1:
+      read_doubles (is, data, LS_FLOAT, len, swap, flt_fmt);
+      break;
+
+    case 2:
+      read_doubles (is, data, LS_INT, len, swap, flt_fmt);
+      break;
+
+    case 3:
+      read_doubles (is, data, LS_SHORT, len, swap, flt_fmt);
+      break;
+
+    case 4:
+      read_doubles (is, data, LS_U_SHORT, len, swap, flt_fmt);
+      break;
+
+    case 5:
+      read_doubles (is, data, LS_U_CHAR, len, swap, flt_fmt);
+      break;
+
+    default:
+      break;
+    }
+}
+
+int
+read_mat_file_header (std::istream& is, bool& swap, int32_t& mopt,
+                      int32_t& nr, int32_t& nc,
+                      int32_t& imag, int32_t& len,
+                      int quiet)
+{
+  swap = false;
+
+  // We expect to fail here, at the beginning of a record, so not
+  // being able to read another mopt value should not result in an
+  // error.
+
+  is.read (reinterpret_cast<char *> (&mopt), 4);
+  if (! is)
+    return 1;
+
+  if (! is.read (reinterpret_cast<char *> (&nr), 4))
+    goto data_read_error;
+
+  if (! is.read (reinterpret_cast<char *> (&nc), 4))
+    goto data_read_error;
+
+  if (! is.read (reinterpret_cast<char *> (&imag), 4))
+    goto data_read_error;
+
+  if (! is.read (reinterpret_cast<char *> (&len), 4))
+    goto data_read_error;
+
+// If mopt is nonzero and the byte order is swapped, mopt will be
+// bigger than we expect, so we swap bytes.
+//
+// If mopt is zero, it means the file was written on a little endian
+// machine, and we only need to swap if we are running on a big endian
+// machine.
+//
+// Gag me.
+
+  if (oct_mach_info::words_big_endian () && mopt == 0)
+    swap = true;
+
+  // mopt is signed, therefore byte swap may result in negative value.
+
+  if (mopt > 9999 || mopt < 0)
+    swap = true;
+
+  if (swap)
+    {
+      swap_bytes<4> (&mopt);
+      swap_bytes<4> (&nr);
+      swap_bytes<4> (&nc);
+      swap_bytes<4> (&imag);
+      swap_bytes<4> (&len);
+    }
+
+  if (mopt > 9999 || mopt < 0 || imag > 1 || imag < 0)
+    {
+      if (! quiet)
+        error ("load: can't read binary file");
+      return -1;
+    }
+
+  return 0;
+
+ data_read_error:
+  return -1;
+}
+
+// We don't just use a cast here, because we need to be able to detect
+// possible errors.
+
+oct_mach_info::float_format
+mopt_digit_to_float_format (int mach)
+{
+  oct_mach_info::float_format flt_fmt = oct_mach_info::flt_fmt_unknown;
+
+  switch (mach)
+    {
+    case 0:
+      flt_fmt = oct_mach_info::flt_fmt_ieee_little_endian;
+      break;
+
+    case 1:
+      flt_fmt = oct_mach_info::flt_fmt_ieee_big_endian;
+      break;
+
+    case 2:
+      flt_fmt = oct_mach_info::flt_fmt_vax_d;
+      break;
+
+    case 3:
+      flt_fmt = oct_mach_info::flt_fmt_vax_g;
+      break;
+
+    case 4:
+      flt_fmt = oct_mach_info::flt_fmt_cray;
+      break;
+
+    default:
+      flt_fmt = oct_mach_info::flt_fmt_unknown;
+      break;
+    }
+
+  return flt_fmt;
+}
+
+int
+float_format_to_mopt_digit (oct_mach_info::float_format flt_fmt)
+{
+  int retval = -1;
+
+  switch (flt_fmt)
+    {
+    case oct_mach_info::flt_fmt_ieee_little_endian:
+      retval = 0;
+      break;
+
+    case oct_mach_info::flt_fmt_ieee_big_endian:
+      retval = 1;
+      break;
+
+    case oct_mach_info::flt_fmt_vax_d:
+      retval = 2;
+      break;
+
+    case oct_mach_info::flt_fmt_vax_g:
+      retval = 3;
+      break;
+
+    case oct_mach_info::flt_fmt_cray:
+      retval = 4;
+      break;
+
+    default:
+      break;
+    }
+
+  return retval;
+}
+
+// Extract one value (scalar, matrix, string, etc.) from stream IS and
+// place it in TC, returning the name of the variable.
+//
+// The data is expected to be in Matlab version 4 .mat format, though
+// not all the features of that format are supported.
+//
+// FILENAME is used for error messages.
+//
+// This format provides no way to tag the data as global.
+
+std::string
+read_mat_binary_data (std::istream& is, const std::string& filename,
+                      octave_value& tc)
+{
+  std::string retval;
+
+  // These are initialized here instead of closer to where they are
+  // first used to avoid errors from gcc about goto crossing
+  // initialization of variable.
+
+  Matrix re;
+  oct_mach_info::float_format flt_fmt = oct_mach_info::flt_fmt_unknown;
+  bool swap = false;
+  int type = 0;
+  int prec = 0;
+  int order = 0;
+  int mach = 0;
+  int dlen = 0;
+
+  int32_t mopt, nr, nc, imag, len;
+
+  int err = read_mat_file_header (is, swap, mopt, nr, nc, imag, len);
+  if (err)
+    {
+      if (err < 0)
+        goto data_read_error;
+      else
+        return retval;
+    }
+
+  type = mopt % 10;  // Full, sparse, etc.
+  mopt /= 10;        // Eliminate first digit.
+  prec = mopt % 10;  // double, float, int, etc.
+  mopt /= 10;        // Eliminate second digit.
+  order = mopt % 10; // Row or column major ordering.
+  mopt /= 10;        // Eliminate third digit.
+  mach = mopt % 10;  // IEEE, VAX, etc.
+
+  flt_fmt = mopt_digit_to_float_format (mach);
+
+  if (flt_fmt == oct_mach_info::flt_fmt_unknown)
+    {
+      error ("load: unrecognized binary format!");
+      return retval;
+    }
+
+  if (imag && type == 1)
+    {
+      error ("load: encountered complex matrix with string flag set!");
+      return retval;
+    }
+
+  // LEN includes the terminating character, and the file is also
+  // supposed to include it, but apparently not all files do.  Either
+  // way, I think this should work.
+
+  {
+    OCTAVE_LOCAL_BUFFER (char, name, len+1);
+    name[len] = '\0';
+    if (! is.read (name, len))
+      goto data_read_error;
+    retval = name;
+
+    dlen = nr * nc;
+    if (dlen < 0)
+      goto data_read_error;
+
+    if (order)
+      {
+        octave_idx_type tmp = nr;
+        nr = nc;
+        nc = tmp;
+      }
+
+    if (type == 2)
+      {
+        if (nc == 4)
+          {
+            octave_idx_type nr_new, nc_new;
+            Array<Complex> data (dim_vector (1, nr - 1));
+            Array<octave_idx_type> c (dim_vector (1, nr - 1));
+            Array<octave_idx_type> r (dim_vector (1, nr - 1));
+            OCTAVE_LOCAL_BUFFER (double, dtmp, nr);
+            OCTAVE_LOCAL_BUFFER (double, ctmp, nr);
+
+            read_mat_binary_data (is, dtmp, prec, nr, swap, flt_fmt);
+            for (octave_idx_type i = 0; i < nr - 1; i++)
+              r.xelem (i) = dtmp[i] - 1;
+            nr_new = dtmp[nr - 1];
+            read_mat_binary_data (is, dtmp, prec, nr, swap, flt_fmt);
+            for (octave_idx_type i = 0; i < nr - 1; i++)
+              c.xelem (i) = dtmp[i] - 1;
+            nc_new = dtmp[nr - 1];
+            read_mat_binary_data (is, dtmp, prec, nr - 1, swap, flt_fmt);
+            read_mat_binary_data (is, ctmp, prec, 1, swap, flt_fmt);
+            read_mat_binary_data (is, ctmp, prec, nr - 1, swap, flt_fmt);
+
+            for (octave_idx_type i = 0; i < nr - 1; i++)
+              data.xelem (i) = Complex (dtmp[i], ctmp[i]);
+            read_mat_binary_data (is, ctmp, prec, 1, swap, flt_fmt);
+
+            SparseComplexMatrix smc = SparseComplexMatrix (data, r, c,
+                                                           nr_new, nc_new);
+
+            tc = order ? smc.transpose () : smc;
+          }
+        else
+          {
+            octave_idx_type nr_new, nc_new;
+            Array<double> data (dim_vector (1, nr - 1));
+            Array<octave_idx_type> c (dim_vector (1, nr - 1));
+            Array<octave_idx_type> r (dim_vector (1, nr - 1));
+            OCTAVE_LOCAL_BUFFER (double, dtmp, nr);
+
+            read_mat_binary_data (is, dtmp, prec, nr, swap, flt_fmt);
+            for (octave_idx_type i = 0; i < nr - 1; i++)
+              r.xelem (i) = dtmp[i] - 1;
+            nr_new = dtmp[nr - 1];
+            read_mat_binary_data (is, dtmp, prec, nr, swap, flt_fmt);
+            for (octave_idx_type i = 0; i < nr - 1; i++)
+              c.xelem (i) = dtmp[i] - 1;
+            nc_new = dtmp[nr - 1];
+            read_mat_binary_data (is, data.fortran_vec (), prec, nr - 1, swap, flt_fmt);
+            read_mat_binary_data (is, dtmp, prec, 1, swap, flt_fmt);
+
+            SparseMatrix sm = SparseMatrix (data, r, c, nr_new, nc_new);
+
+            tc = order ? sm.transpose () : sm;
+          }
+      }
+    else
+      {
+        re.resize (nr, nc);
+
+        read_mat_binary_data (is, re.fortran_vec (), prec, dlen, swap, flt_fmt);
+
+        if (! is || error_state)
+          {
+            error ("load: reading matrix data for `%s'", name);
+            goto data_read_error;
+          }
+
+        if (imag)
+          {
+            Matrix im (nr, nc);
+
+            read_mat_binary_data (is, im.fortran_vec (), prec, dlen, swap,
+                                  flt_fmt);
+
+            if (! is || error_state)
+              {
+                error ("load: reading imaginary matrix data for `%s'", name);
+                goto data_read_error;
+              }
+
+            ComplexMatrix ctmp (nr, nc);
+
+            for (octave_idx_type j = 0; j < nc; j++)
+              for (octave_idx_type i = 0; i < nr; i++)
+                ctmp (i, j) = Complex (re (i, j), im (i, j));
+
+            tc = order ? ctmp.transpose () : ctmp;
+          }
+        else
+          tc = order ? re.transpose () : re;
+
+        if (type == 1)
+          tc = tc.convert_to_str (false, true, '\'');
+      }
+
+      return retval;
+    }
+
+ data_read_error:
+  error ("load: trouble reading binary file `%s'", filename.c_str ());
+  return retval;
+}
+
+// Save the data from TC along with the corresponding NAME on stream OS
+// in the MatLab version 4 binary format.
+
+bool
+save_mat_binary_data (std::ostream& os, const octave_value& tc,
+                      const std::string& name)
+{
+  int32_t mopt = 0;
+
+  mopt += tc.is_sparse_type () ? 2 : tc.is_string () ? 1 : 0;
+
+  oct_mach_info::float_format flt_fmt =
+    oct_mach_info::native_float_format ();;
+
+  mopt += 1000 * float_format_to_mopt_digit (flt_fmt);
+
+  os.write (reinterpret_cast<char *> (&mopt), 4);
+
+  octave_idx_type len;
+  int32_t nr = tc.rows ();
+
+  int32_t nc = tc.columns ();
+
+  if (tc.is_sparse_type ())
+    {
+      len = tc.nnz ();
+      uint32_t nnz = len + 1;
+      os.write (reinterpret_cast<char *> (&nnz), 4);
+
+      uint32_t iscmplx = tc.is_complex_type () ? 4 : 3;
+      os.write (reinterpret_cast<char *> (&iscmplx), 4);
+
+      uint32_t tmp = 0;
+      os.write (reinterpret_cast<char *> (&tmp), 4);
+    }
+  else
+    {
+      os.write (reinterpret_cast<char *> (&nr), 4);
+      os.write (reinterpret_cast<char *> (&nc), 4);
+
+      int32_t imag = tc.is_complex_type () ? 1 : 0;
+      os.write (reinterpret_cast<char *> (&imag), 4);
+
+      len = nr * nc;
+    }
+
+
+  // LEN includes the terminating character, and the file is also
+  // supposed to include it.
+
+  int32_t name_len = name.length () + 1;
+
+  os.write (reinterpret_cast<char *> (&name_len), 4);
+  os << name << '\0';
+
+  if (tc.is_string ())
+    {
+      unwind_protect frame;
+
+      charMatrix chm = tc.char_matrix_value ();
+
+      octave_idx_type nrow = chm.rows ();
+      octave_idx_type ncol = chm.cols ();
+
+      OCTAVE_LOCAL_BUFFER (double, buf, ncol*nrow);
+
+      for (octave_idx_type i = 0; i < nrow; i++)
+        {
+          std::string tstr = chm.row_as_string (i);
+          const char *s = tstr.data ();
+
+          for (octave_idx_type j = 0; j < ncol; j++)
+            buf[j*nrow+i] = static_cast<double> (*s++ & 0x00FF);
+        }
+      os.write (reinterpret_cast<char *> (buf), nrow*ncol*sizeof (double));
+    }
+  else if (tc.is_range ())
+    {
+      Range r = tc.range_value ();
+      double base = r.base ();
+      double inc = r.inc ();
+      octave_idx_type nel = r.nelem ();
+      for (octave_idx_type i = 0; i < nel; i++)
+        {
+          double x = base + i * inc;
+          os.write (reinterpret_cast<char *> (&x), 8);
+        }
+    }
+  else if (tc.is_real_scalar ())
+    {
+      double tmp = tc.double_value ();
+      os.write (reinterpret_cast<char *> (&tmp), 8);
+    }
+  else if (tc.is_sparse_type ())
+    {
+      double ds;
+      OCTAVE_LOCAL_BUFFER (double, dtmp, len);
+      if (tc.is_complex_matrix ())
+        {
+          SparseComplexMatrix m = tc.sparse_complex_matrix_value ();
+
+          for (octave_idx_type i = 0; i < len; i++)
+            dtmp[i] = m.ridx (i) + 1;
+          os.write (reinterpret_cast<const char *> (dtmp), 8 * len);
+          ds = nr;
+          os.write (reinterpret_cast<const char *> (&ds), 8);
+
+          octave_idx_type ii = 0;
+          for (octave_idx_type j = 0; j < nc; j++)
+            for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++)
+              dtmp[ii++] = j + 1;
+          os.write (reinterpret_cast<const char *> (dtmp), 8 * len);
+          ds = nc;
+          os.write (reinterpret_cast<const char *> (&ds), 8);
+
+          for (octave_idx_type i = 0; i < len; i++)
+            dtmp[i] = std::real (m.data (i));
+          os.write (reinterpret_cast<const char *> (dtmp), 8 * len);
+          ds = 0.;
+          os.write (reinterpret_cast<const char *> (&ds), 8);
+
+          for (octave_idx_type i = 0; i < len; i++)
+            dtmp[i] = std::imag (m.data (i));
+          os.write (reinterpret_cast<const char *> (dtmp), 8 * len);
+          os.write (reinterpret_cast<const char *> (&ds), 8);
+        }
+      else
+        {
+          SparseMatrix m = tc.sparse_matrix_value ();
+
+          for (octave_idx_type i = 0; i < len; i++)
+            dtmp[i] = m.ridx (i) + 1;
+          os.write (reinterpret_cast<const char *> (dtmp), 8 * len);
+          ds = nr;
+          os.write (reinterpret_cast<const char *> (&ds), 8);
+
+          octave_idx_type ii = 0;
+          for (octave_idx_type j = 0; j < nc; j++)
+            for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++)
+              dtmp[ii++] = j + 1;
+          os.write (reinterpret_cast<const char *> (dtmp), 8 * len);
+          ds = nc;
+          os.write (reinterpret_cast<const char *> (&ds), 8);
+
+          os.write (reinterpret_cast<const char *> (m.data ()), 8 * len);
+          ds = 0.;
+          os.write (reinterpret_cast<const char *> (&ds), 8);
+        }
+    }
+  else if (tc.is_real_matrix ())
+    {
+      Matrix m = tc.matrix_value ();
+      os.write (reinterpret_cast<const char *> (m.data ()), 8 * len);
+    }
+  else if (tc.is_complex_scalar ())
+    {
+      Complex tmp = tc.complex_value ();
+      os.write (reinterpret_cast<char *> (&tmp), 16);
+    }
+  else if (tc.is_complex_matrix ())
+    {
+      ComplexMatrix m_cmplx = tc.complex_matrix_value ();
+      Matrix m = ::real (m_cmplx);
+      os.write (reinterpret_cast<const char *> (m.data ()), 8 * len);
+      m = ::imag (m_cmplx);
+      os.write (reinterpret_cast<const char *> (m.data ()), 8 * len);
+    }
+  else
+    gripe_wrong_type_arg ("save", tc, false);
+
+  return os;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/ls-mat4.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,45 @@
+/*
+
+Copyright (C) 2003-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if !defined (octave_ls_mat4_h)
+#define octave_ls_mat4_h 1
+
+extern oct_mach_info::float_format
+mopt_digit_to_float_format (int mach);
+
+extern int
+float_format_to_mopt_digit (oct_mach_info::float_format flt_fmt);
+
+extern int
+read_mat_file_header (std::istream& is, bool& swap, int32_t& mopt,
+                      int32_t& nr, int32_t& nc, int32_t& imag,
+                      int32_t& len, int quiet = 0);
+
+extern std::string
+read_mat_binary_data (std::istream& is, const std::string& filename,
+                      octave_value& tc);
+
+extern bool
+save_mat_binary_data (std::ostream& os, const octave_value& tc,
+                      const std::string& name) ;
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/ls-mat5.cc	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,2719 @@
+/*
+
+Copyright (C) 1996-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+// Author: James R. Van Zandt <jrv@vanzandt.mv.com>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <cfloat>
+#include <cstring>
+#include <cctype>
+
+#include <fstream>
+#include <iomanip>
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "byte-swap.h"
+#include "data-conv.h"
+#include "file-ops.h"
+#include "glob-match.h"
+#include "lo-mappers.h"
+#include "mach-info.h"
+#include "oct-env.h"
+#include "oct-time.h"
+#include "quit.h"
+#include "str-vec.h"
+#include "file-stat.h"
+#include "oct-locbuf.h"
+
+#include "Cell.h"
+#include "defun.h"
+#include "error.h"
+#include "gripes.h"
+#include "load-save.h"
+#include "load-path.h"
+#include "oct-obj.h"
+#include "oct-map.h"
+#include "ov-cell.h"
+#include "ov-class.h"
+#include "ov-fcn-inline.h"
+#include "pager.h"
+#include "pt-exp.h"
+#include "sysdep.h"
+#include "toplev.h"
+#include "unwind-prot.h"
+#include "utils.h"
+#include "variables.h"
+#include "version.h"
+#include "dMatrix.h"
+
+#include "ls-utils.h"
+#include "ls-mat5.h"
+
+#include "parse.h"
+#include "defaults.h"
+
+#ifdef HAVE_ZLIB
+#include <zlib.h>
+#endif
+
+#define PAD(l) (((l) > 0 && (l) <= 4) ? 4 : (((l)+7)/8)*8)
+
+
+// The subsystem data block
+static octave_value subsys_ov;
+
+// FIXME -- the following enum values should be the same as the
+// mxClassID values in mexproto.h, but it seems they have also changed
+// over time.  What is the correct way to handle this and maintain
+// backward compatibility with old MAT files?  For now, use
+// "MAT_FILE_" instead of "mx" as the prefix for these names to avoid
+// conflict with the mxClassID enum in mexproto.h.
+
+enum arrayclasstype
+  {
+    MAT_FILE_CELL_CLASS=1,              // cell array
+    MAT_FILE_STRUCT_CLASS,              // structure
+    MAT_FILE_OBJECT_CLASS,              // object
+    MAT_FILE_CHAR_CLASS,                // character array
+    MAT_FILE_SPARSE_CLASS,              // sparse array
+    MAT_FILE_DOUBLE_CLASS,              // double precision array
+    MAT_FILE_SINGLE_CLASS,              // single precision floating point
+    MAT_FILE_INT8_CLASS,                // 8 bit signed integer
+    MAT_FILE_UINT8_CLASS,               // 8 bit unsigned integer
+    MAT_FILE_INT16_CLASS,               // 16 bit signed integer
+    MAT_FILE_UINT16_CLASS,              // 16 bit unsigned integer
+    MAT_FILE_INT32_CLASS,               // 32 bit signed integer
+    MAT_FILE_UINT32_CLASS,              // 32 bit unsigned integer
+    MAT_FILE_INT64_CLASS,               // 64 bit signed integer
+    MAT_FILE_UINT64_CLASS,              // 64 bit unsigned integer
+    MAT_FILE_FUNCTION_CLASS,            // Function handle
+    MAT_FILE_WORKSPACE_CLASS            // Workspace (undocumented)
+  };
+
+// Read COUNT elements of data from IS in the format specified by TYPE,
+// placing the result in DATA.  If SWAP is TRUE, swap the bytes of
+// each element before copying to DATA.  FLT_FMT specifies the format
+// of the data if we are reading floating point numbers.
+
+static void
+read_mat5_binary_data (std::istream& is, double *data,
+                       octave_idx_type  count, bool swap, mat5_data_type type,
+                       oct_mach_info::float_format flt_fmt)
+{
+
+  switch (type)
+    {
+    case miINT8:
+      read_doubles (is, data, LS_CHAR, count, swap, flt_fmt);
+      break;
+
+    case miUTF8:
+    case miUINT8:
+      read_doubles (is, data, LS_U_CHAR, count, swap, flt_fmt);
+      break;
+
+    case miINT16:
+      read_doubles (is, data, LS_SHORT, count, swap, flt_fmt);
+      break;
+
+    case miUTF16:
+    case miUINT16:
+      read_doubles (is, data, LS_U_SHORT, count, swap, flt_fmt);
+      break;
+
+    case miINT32:
+      read_doubles (is, data, LS_INT, count, swap, flt_fmt);
+      break;
+
+    case miUTF32:
+    case miUINT32:
+      read_doubles (is, data, LS_U_INT, count, swap, flt_fmt);
+      break;
+
+    case miSINGLE:
+      read_doubles (is, data, LS_FLOAT, count, swap, flt_fmt);
+      break;
+
+    case miRESERVE1:
+      break;
+
+    case miDOUBLE:
+      read_doubles (is, data, LS_DOUBLE, count, swap, flt_fmt);
+      break;
+
+    case miRESERVE2:
+    case miRESERVE3:
+      break;
+
+    // FIXME -- how are the 64-bit cases supposed to work here?
+    case miINT64:
+      read_doubles (is, data, LS_LONG, count, swap, flt_fmt);
+      break;
+
+    case miUINT64:
+      read_doubles (is, data, LS_U_LONG, count, swap, flt_fmt);
+      break;
+
+    case miMATRIX:
+    default:
+      break;
+    }
+}
+
+static void
+read_mat5_binary_data (std::istream& is, float *data,
+                       octave_idx_type  count, bool swap, mat5_data_type type,
+                       oct_mach_info::float_format flt_fmt)
+{
+
+  switch (type)
+    {
+    case miINT8:
+      read_floats (is, data, LS_CHAR, count, swap, flt_fmt);
+      break;
+
+    case miUTF8:
+    case miUINT8:
+      read_floats (is, data, LS_U_CHAR, count, swap, flt_fmt);
+      break;
+
+    case miINT16:
+      read_floats (is, data, LS_SHORT, count, swap, flt_fmt);
+      break;
+
+    case miUTF16:
+    case miUINT16:
+      read_floats (is, data, LS_U_SHORT, count, swap, flt_fmt);
+      break;
+
+    case miINT32:
+      read_floats (is, data, LS_INT, count, swap, flt_fmt);
+      break;
+
+    case miUTF32:
+    case miUINT32:
+      read_floats (is, data, LS_U_INT, count, swap, flt_fmt);
+      break;
+
+    case miSINGLE:
+      read_floats (is, data, LS_FLOAT, count, swap, flt_fmt);
+      break;
+
+    case miRESERVE1:
+      break;
+
+    case miDOUBLE:
+      read_floats (is, data, LS_DOUBLE, count, swap, flt_fmt);
+      break;
+
+    case miRESERVE2:
+    case miRESERVE3:
+      break;
+
+    // FIXME -- how are the 64-bit cases supposed to work here?
+    case miINT64:
+      read_floats (is, data, LS_LONG, count, swap, flt_fmt);
+      break;
+
+    case miUINT64:
+      read_floats (is, data, LS_U_LONG, count, swap, flt_fmt);
+      break;
+
+    case miMATRIX:
+    default:
+      break;
+    }
+}
+
+template <class T>
+void
+read_mat5_integer_data (std::istream& is, T *m, octave_idx_type count,
+                        bool swap, mat5_data_type type)
+{
+
+#define READ_INTEGER_DATA(TYPE, swap, data, size, len, stream)  \
+  do \
+    { \
+      if (len > 0) \
+        { \
+          OCTAVE_LOCAL_BUFFER (TYPE, ptr, len); \
+          stream.read (reinterpret_cast<char *> (ptr), size * len); \
+          if (swap) \
+            swap_bytes< size > (ptr, len); \
+          for (octave_idx_type i = 0; i < len; i++) \
+            data[i] = ptr[i]; \
+        } \
+    } \
+  while (0)
+
+  switch (type)
+    {
+    case miINT8:
+      READ_INTEGER_DATA (int8_t, swap, m, 1, count, is);
+      break;
+
+    case miUINT8:
+      READ_INTEGER_DATA (uint8_t, swap, m, 1, count, is);
+      break;
+
+    case miINT16:
+      READ_INTEGER_DATA (int16_t, swap, m, 2, count, is);
+      break;
+
+    case miUINT16:
+      READ_INTEGER_DATA (uint16_t, swap, m, 2, count, is);
+      break;
+
+    case miINT32:
+      READ_INTEGER_DATA (int32_t, swap, m, 4, count, is);
+      break;
+
+    case miUINT32:
+      READ_INTEGER_DATA (uint32_t, swap, m, 4, count, is);
+      break;
+
+    case miSINGLE:
+    case miRESERVE1:
+    case miDOUBLE:
+    case miRESERVE2:
+    case miRESERVE3:
+      break;
+
+    case miINT64:
+      READ_INTEGER_DATA (int64_t, swap, m, 8, count, is);
+      break;
+
+    case miUINT64:
+      READ_INTEGER_DATA (uint64_t, swap, m, 8, count, is);
+      break;
+
+    case miMATRIX:
+    default:
+      break;
+    }
+
+#undef READ_INTEGER_DATA
+
+}
+
+template void
+read_mat5_integer_data (std::istream& is, octave_int8 *m,
+                        octave_idx_type count, bool swap,
+                        mat5_data_type type);
+
+template void
+read_mat5_integer_data (std::istream& is, octave_int16 *m,
+                        octave_idx_type count, bool swap,
+                        mat5_data_type type);
+
+template void
+read_mat5_integer_data (std::istream& is, octave_int32 *m,
+                        octave_idx_type count, bool swap,
+                        mat5_data_type type);
+
+template void
+read_mat5_integer_data (std::istream& is, octave_int64 *m,
+                        octave_idx_type count, bool swap,
+                        mat5_data_type type);
+
+template void
+read_mat5_integer_data (std::istream& is, octave_uint8 *m,
+                        octave_idx_type count, bool swap,
+                        mat5_data_type type);
+
+template void
+read_mat5_integer_data (std::istream& is, octave_uint16 *m,
+                        octave_idx_type count, bool swap,
+                        mat5_data_type type);
+
+template void
+read_mat5_integer_data (std::istream& is, octave_uint32 *m,
+                        octave_idx_type count, bool swap,
+                        mat5_data_type type);
+
+template void
+read_mat5_integer_data (std::istream& is, octave_uint64 *m,
+                        octave_idx_type count, bool swap,
+                        mat5_data_type type);
+
+template void
+read_mat5_integer_data (std::istream& is, int *m,
+                        octave_idx_type count, bool swap,
+                        mat5_data_type type);
+
+#define OCTAVE_MAT5_INTEGER_READ(TYP) \
+  { \
+        TYP re (dims); \
+  \
+        std::streampos tmp_pos; \
+  \
+        if (read_mat5_tag (is, swap, type, len)) \
+          { \
+            error ("load: reading matrix data for `%s'", retval.c_str ()); \
+            goto data_read_error; \
+          } \
+  \
+        octave_idx_type n = re.numel (); \
+        tmp_pos = is.tellg (); \
+        read_mat5_integer_data (is, re.fortran_vec (), n, swap, \
+                                static_cast<enum mat5_data_type> (type)); \
+  \
+        if (! is || error_state) \
+          { \
+            error ("load: reading matrix data for `%s'", retval.c_str ()); \
+            goto data_read_error; \
+          } \
+  \
+        is.seekg (tmp_pos + static_cast<std::streamoff> (PAD (len))); \
+  \
+        if (imag) \
+          { \
+            /* We don't handle imag integer types, convert to an array */ \
+            NDArray im (dims); \
+  \
+            if (read_mat5_tag (is, swap, type, len)) \
+              { \
+                error ("load: reading matrix data for `%s'", \
+                       retval.c_str ()); \
+                goto data_read_error; \
+              } \
+  \
+            n = im.numel (); \
+            read_mat5_binary_data (is, im.fortran_vec (), n, swap, \
+                                   static_cast<enum mat5_data_type> (type), flt_fmt); \
+  \
+            if (! is || error_state) \
+              { \
+                error ("load: reading imaginary matrix data for `%s'", \
+                       retval.c_str ()); \
+                goto data_read_error; \
+              } \
+  \
+            ComplexNDArray ctmp (dims); \
+  \
+            for (octave_idx_type i = 0; i < n; i++) \
+              ctmp(i) = Complex (re(i).double_value (), im(i)); \
+  \
+            tc = ctmp;  \
+          } \
+        else \
+          tc = re; \
+  }
+
+// Read one element tag from stream IS,
+// place the type code in TYPE and the byte count in BYTES
+// return nonzero on error
+static int
+read_mat5_tag (std::istream& is, bool swap, int32_t& type, int32_t& bytes)
+{
+  unsigned int upper;
+  int32_t temp;
+
+  if (! is.read (reinterpret_cast<char *> (&temp), 4 ))
+    goto data_read_error;
+
+  if (swap)
+    swap_bytes<4> (&temp);
+
+  upper = (temp >> 16) & 0xffff;
+  type = temp & 0xffff;
+
+  if (upper)
+    {
+      // "compressed" format
+      bytes = upper;
+    }
+  else
+    {
+      if (! is.read (reinterpret_cast<char *> (&temp), 4 ))
+        goto data_read_error;
+      if (swap)
+        swap_bytes<4> (&temp);
+      bytes = temp;
+    }
+
+  return 0;
+
+ data_read_error:
+  return 1;
+}
+
+static void
+read_int (std::istream& is, bool swap, int32_t& val)
+{
+  is.read (reinterpret_cast<char *> (&val), 4);
+
+  if (swap)
+    swap_bytes<4> (&val);
+}
+
+// Extract one data element (scalar, matrix, string, etc.) from stream
+// IS and place it in TC, returning the name of the variable.
+//
+// The data is expected to be in Matlab's "Version 5" .mat format,
+// though not all the features of that format are supported.
+//
+// FILENAME is used for error messages.
+
+std::string
+read_mat5_binary_element (std::istream& is, const std::string& filename,
+                          bool swap, bool& global, octave_value& tc)
+{
+  std::string retval;
+
+  global = false;
+
+  // NOTE: these are initialized here instead of closer to where they
+  // are first used to avoid errors from gcc about goto crossing
+  // initialization of variable.
+
+  bool imag;
+  bool isclass = false;
+  bool logicalvar;
+  dim_vector dims;
+  enum arrayclasstype arrayclass;
+  int16_t number = *(reinterpret_cast<const int16_t *>("\x00\x01"));
+  octave_idx_type nzmax;
+  std::string classname;
+
+  // MAT files always use IEEE floating point
+  oct_mach_info::float_format flt_fmt = oct_mach_info::flt_fmt_unknown;
+  if ((number == 1) ^ swap)
+    flt_fmt = oct_mach_info::flt_fmt_ieee_big_endian;
+  else
+    flt_fmt = oct_mach_info::flt_fmt_ieee_little_endian;
+
+  // element type and length
+  int32_t type = 0;
+  int32_t element_length;
+  if (read_mat5_tag (is, swap, type, element_length))
+    return retval;                      // EOF
+
+#ifdef HAVE_ZLIB
+  if (type == miCOMPRESSED)
+    {
+      // If C++ allowed us direct access to the file descriptor of an
+      // ifstream in a uniform way, the code below could be vastly
+      // simplified, and additional copies of the data in memory
+      // wouldn't be needed.
+
+      OCTAVE_LOCAL_BUFFER (char, inbuf, element_length);
+      is.read (inbuf, element_length);
+
+      // We uncompress the first 8 bytes of the header to get the buffer length
+      // This will fail with an error Z_MEM_ERROR
+      uLongf destLen = 8;
+      OCTAVE_LOCAL_BUFFER (unsigned int, tmp, 2);
+      if (uncompress (reinterpret_cast<Bytef *> (tmp), &destLen,
+                      reinterpret_cast<Bytef *> (inbuf), element_length)
+          !=  Z_MEM_ERROR)
+        {
+          // Why should I have to initialize outbuf as I'll just overwrite!!
+          if (swap)
+            swap_bytes<4> (tmp, 2);
+
+          destLen = tmp[1] + 8;
+          std::string outbuf (destLen, ' ');
+
+          // FIXME -- find a way to avoid casting away const here!
+
+          int err = uncompress (reinterpret_cast<Bytef *> (const_cast<char *> (outbuf.c_str ())),
+                                &destLen, reinterpret_cast<Bytef *> (inbuf),
+                                element_length);
+
+          if (err != Z_OK)
+            {
+              std::string msg;
+              switch (err)
+                {
+                case Z_STREAM_END:
+                  msg = "stream end";
+                  break;
+
+                case Z_NEED_DICT:
+                  msg = "need dict";
+                  break;
+
+                case Z_ERRNO:
+                  msg = "errno case";
+                  break;
+
+                case Z_STREAM_ERROR:
+                  msg = "stream error";
+                  break;
+
+                case Z_DATA_ERROR:
+                  msg = "data error";
+                  break;
+
+                case Z_MEM_ERROR:
+                  msg = "mem error";
+                  break;
+
+                case Z_BUF_ERROR:
+                  msg = "buf error";
+                  break;
+
+                case Z_VERSION_ERROR:
+                  msg = "version error";
+                  break;
+                }
+
+              error ("load: error uncompressing data element (%s from zlib)",
+                     msg.c_str ());
+            }
+          else
+            {
+              std::istringstream gz_is (outbuf);
+              retval = read_mat5_binary_element (gz_is, filename,
+                                                 swap, global, tc);
+            }
+        }
+      else
+        error ("load: error probing size of compressed data element");
+
+      return retval;
+    }
+#endif
+
+  std::streampos pos;
+
+  if (type != miMATRIX)
+    {
+      pos = is.tellg ();
+      error ("load: invalid element type = %d", type);
+      goto early_read_error;
+    }
+
+  if (element_length == 0)
+    {
+      tc = Matrix ();
+      return retval;
+    }
+
+  pos = is.tellg ();
+
+  // array flags subelement
+  int32_t len;
+  if (read_mat5_tag (is, swap, type, len) || type != miUINT32 || len != 8)
+    {
+      error ("load: invalid array flags subelement");
+      goto early_read_error;
+    }
+
+  int32_t flags;
+  read_int (is, swap, flags);
+
+  imag = (flags & 0x0800) != 0; // has an imaginary part?
+
+  global = (flags & 0x0400) != 0; // global variable?
+
+  logicalvar = (flags & 0x0200) != 0; // boolean ?
+
+  arrayclass = static_cast<arrayclasstype> (flags & 0xff);
+
+  int32_t tmp_nzmax;
+  read_int (is, swap, tmp_nzmax);   // max number of non-zero in sparse
+  nzmax = tmp_nzmax;
+
+  // dimensions array subelement
+  if (arrayclass != MAT_FILE_WORKSPACE_CLASS)
+    {
+      int32_t dim_len;
+
+      if (read_mat5_tag (is, swap, type, dim_len) || type != miINT32)
+        {
+          error ("load: invalid dimensions array subelement");
+          goto early_read_error;
+        }
+
+      int ndims = dim_len / 4;
+      dims.resize (ndims);
+      for (int i = 0; i < ndims; i++)
+        {
+          int32_t n;
+          read_int (is, swap, n);
+          dims(i) = n;
+        }
+
+      std::streampos tmp_pos = is.tellg ();
+      is.seekg (tmp_pos + static_cast<std::streamoff> (PAD (dim_len) - dim_len));
+    }
+  else
+    {
+      // Why did mathworks decide to not have dims for a workspace!!!
+      dims.resize (2);
+      dims(0) = 1;
+      dims(1) = 1;
+    }
+
+  if (read_mat5_tag (is, swap, type, len) || type != miINT8)
+    {
+      error ("load: invalid array name subelement");
+      goto early_read_error;
+    }
+
+  {
+    OCTAVE_LOCAL_BUFFER (char, name, len+1);
+
+    // Structure field subelements have zero-length array name subelements.
+
+    std::streampos tmp_pos = is.tellg ();
+
+    if (len)
+      {
+        if (! is.read (name, len ))
+          goto data_read_error;
+
+        is.seekg (tmp_pos + static_cast<std::streamoff> (PAD (len)));
+      }
+
+    name[len] = '\0';
+    retval = name;
+  }
+
+  switch (arrayclass)
+    {
+    case MAT_FILE_CELL_CLASS:
+      {
+        Cell cell_array (dims);
+
+        octave_idx_type n = cell_array.numel ();
+
+        for (octave_idx_type i = 0; i < n; i++)
+          {
+            octave_value tc2;
+
+            std::string nm
+              = read_mat5_binary_element (is, filename, swap, global, tc2);
+
+            if (! is || error_state)
+              {
+                error ("load: reading cell data for `%s'", nm.c_str ());
+                goto data_read_error;
+              }
+
+            cell_array(i) = tc2;
+          }
+
+        tc = cell_array;
+      }
+      break;
+
+    case MAT_FILE_SPARSE_CLASS:
+      {
+        octave_idx_type nr = dims(0);
+        octave_idx_type nc = dims(1);
+        SparseMatrix sm;
+        SparseComplexMatrix scm;
+        octave_idx_type *ridx;
+        octave_idx_type *cidx;
+        double *data;
+
+        // Setup return value
+        if (imag)
+          {
+            scm = SparseComplexMatrix (nr, nc, nzmax);
+            ridx = scm.ridx ();
+            cidx = scm.cidx ();
+            data = 0;
+          }
+        else
+          {
+            sm = SparseMatrix (nr, nc, nzmax);
+            ridx = sm.ridx ();
+            cidx = sm.cidx ();
+            data = sm.data ();
+          }
+
+        // row indices
+        std::streampos tmp_pos;
+
+        if (read_mat5_tag (is, swap, type, len))
+          {
+            error ("load: reading sparse row data for `%s'", retval.c_str ());
+            goto data_read_error;
+          }
+
+        tmp_pos = is.tellg ();
+
+        read_mat5_integer_data (is, ridx, nzmax, swap,
+                                static_cast<enum mat5_data_type> (type));
+
+        if (! is || error_state)
+          {
+            error ("load: reading sparse row data for `%s'", retval.c_str ());
+            goto data_read_error;
+          }
+
+        is.seekg (tmp_pos + static_cast<std::streamoff> (PAD (len)));
+
+        // col indices
+        if (read_mat5_tag (is, swap, type, len))
+          {
+            error ("load: reading sparse column data for `%s'", retval.c_str ());
+            goto data_read_error;
+          }
+
+        tmp_pos = is.tellg ();
+
+        read_mat5_integer_data (is, cidx, nc + 1, swap,
+                                static_cast<enum mat5_data_type> (type));
+
+        if (! is || error_state)
+          {
+            error ("load: reading sparse column data for `%s'", retval.c_str ());
+            goto data_read_error;
+          }
+
+        is.seekg (tmp_pos + static_cast<std::streamoff> (PAD (len)));
+
+        // real data subelement
+        if (read_mat5_tag (is, swap, type, len))
+          {
+            error ("load: reading sparse matrix data for `%s'", retval.c_str ());
+            goto data_read_error;
+          }
+
+        octave_idx_type nnz = cidx[nc];
+        NDArray re;
+        if (imag)
+          {
+            re = NDArray (dim_vector (nnz, 1));
+            data = re.fortran_vec ();
+          }
+
+        tmp_pos = is.tellg ();
+        read_mat5_binary_data (is, data, nnz, swap,
+                               static_cast<enum mat5_data_type> (type), flt_fmt);
+
+        if (! is || error_state)
+          {
+            error ("load: reading sparse matrix data for `%s'", retval.c_str ());
+            goto data_read_error;
+          }
+
+        is.seekg (tmp_pos + static_cast<std::streamoff> (PAD (len)));
+
+        // imaginary data subelement
+        if (imag)
+          {
+            NDArray im (dim_vector (static_cast<int> (nnz), 1));
+
+            if (read_mat5_tag (is, swap, type, len))
+              {
+                error ("load: reading sparse matrix data for `%s'", retval.c_str ());
+                goto data_read_error;
+              }
+
+            read_mat5_binary_data (is, im.fortran_vec (), nnz, swap,
+                                   static_cast<enum mat5_data_type> (type), flt_fmt);
+
+            if (! is || error_state)
+              {
+                error ("load: reading imaginary sparse matrix data for `%s'",
+                       retval.c_str ());
+                goto data_read_error;
+              }
+
+            for (octave_idx_type i = 0; i < nnz; i++)
+              scm.xdata (i) = Complex (re (i), im (i));
+
+            tc = scm;
+          }
+        else
+          tc = sm;
+      }
+      break;
+
+    case MAT_FILE_FUNCTION_CLASS:
+      {
+        octave_value tc2;
+        std::string nm
+          = read_mat5_binary_element (is, filename, swap, global, tc2);
+
+        if (! is || error_state)
+          goto data_read_error;
+
+        // Octave can handle both "/" and "\" as a directry seperator
+        // and so can ignore the seperator field of m0. I think the
+        // sentinel field is also save to ignore.
+        Octave_map m0 = tc2.map_value ();
+        Octave_map m1 = m0.contents ("function_handle")(0).map_value ();
+        std::string ftype = m1.contents ("type")(0).string_value ();
+        std::string fname = m1.contents ("function")(0).string_value ();
+        std::string fpath = m1.contents ("file")(0).string_value ();
+
+        if (ftype == "simple" || ftype == "scopedfunction")
+          {
+            if (fpath.length () == 0)
+              // We have a builtin function
+              tc = make_fcn_handle (fname);
+            else
+              {
+                std::string mroot =
+                  m0.contents ("matlabroot")(0).string_value ();
+
+                if ((fpath.length () >= mroot.length ()) &&
+                    fpath.substr (0, mroot.length ()) == mroot &&
+                    OCTAVE_EXEC_PREFIX != mroot)
+                  {
+                    // If fpath starts with matlabroot, and matlabroot
+                    // doesn't equal octave_config_info ("exec_prefix")
+                    // then the function points to a version of Octave
+                    // or Matlab other than the running version. In that
+                    // case we replace with the same function in the
+                    // running version of Octave?
+
+                    // First check if just replacing matlabroot is enough
+                    std::string str = OCTAVE_EXEC_PREFIX +
+                      fpath.substr (mroot.length ());
+                    file_stat fs (str);
+
+                    if (fs.exists ())
+                      {
+                        size_t xpos
+                          = str.find_last_of (file_ops::dir_sep_chars ());
+
+                        std::string dir_name = str.substr (0, xpos);
+
+                        octave_function *fcn
+                          = load_fcn_from_file (str, dir_name, "", fname);
+
+                        if (fcn)
+                          {
+                            octave_value tmp (fcn);
+
+                            tc = octave_value (new octave_fcn_handle (tmp, fname));
+                          }
+                      }
+                    else
+                      {
+                        // Next just search for it anywhere in the
+                        // system path
+                        string_vector names(3);
+                        names(0) = fname + ".oct";
+                        names(1) = fname + ".mex";
+                        names(2) = fname + ".m";
+
+                        dir_path p (load_path::system_path ());
+
+                        str = octave_env::make_absolute (p.find_first_of (names));
+
+                        size_t xpos
+                          = str.find_last_of (file_ops::dir_sep_chars ());
+
+                        std::string dir_name = str.substr (0, xpos);
+
+                        octave_function *fcn
+                          = load_fcn_from_file (str, dir_name, "", fname);
+
+                        if (fcn)
+                          {
+                            octave_value tmp (fcn);
+
+                            tc = octave_value (new octave_fcn_handle (tmp, fname));
+                          }
+                        else
+                          {
+                            warning ("load: can't find the file %s",
+                                     fpath.c_str ());
+                            goto skip_ahead;
+                          }
+                      }
+                  }
+                else
+                  {
+                    size_t xpos
+                      = fpath.find_last_of (file_ops::dir_sep_chars ());
+
+                    std::string dir_name = fpath.substr (0, xpos);
+
+                    octave_function *fcn
+                      = load_fcn_from_file (fpath, dir_name, "", fname);
+
+                    if (fcn)
+                      {
+                        octave_value tmp (fcn);
+
+                        tc = octave_value (new octave_fcn_handle (tmp, fname));
+                      }
+                    else
+                      {
+                        warning ("load: can't find the file %s",
+                                 fpath.c_str ());
+                        goto skip_ahead;
+                      }
+                  }
+              }
+          }
+        else if (ftype == "nested")
+          {
+            warning ("load: can't load nested function");
+            goto skip_ahead;
+          }
+        else if (ftype == "anonymous")
+          {
+            Octave_map m2 = m1.contents ("workspace")(0).map_value ();
+            uint32NDArray MCOS = m2.contents ("MCOS")(0).uint32_array_value ();
+            octave_idx_type off = static_cast<octave_idx_type>(MCOS(4).double_value ());
+            m2 = subsys_ov.map_value ();
+            m2 = m2.contents ("MCOS")(0).map_value ();
+            tc2 = m2.contents ("MCOS")(0).cell_value ()(1 + off).cell_value ()(1);
+            m2 = tc2.map_value ();
+
+            unwind_protect_safe frame;
+
+            // Set up temporary scope to use for evaluating the text
+            // that defines the anonymous function.
+
+            symbol_table::scope_id local_scope = symbol_table::alloc_scope ();
+            frame.add_fcn (symbol_table::erase_scope, local_scope);
+
+            symbol_table::set_scope (local_scope);
+
+            octave_call_stack::push (local_scope, 0);
+            frame.add_fcn (octave_call_stack::pop);
+
+            if (m2.nfields () > 0)
+              {
+                octave_value tmp;
+
+                for (Octave_map::iterator p0 = m2.begin () ;
+                     p0 != m2.end (); p0++)
+                  {
+                    std::string key = m2.key (p0);
+                    octave_value val = m2.contents (p0)(0);
+
+                    symbol_table::varref (key, local_scope, 0) = val;
+                  }
+              }
+
+            int parse_status;
+            octave_value anon_fcn_handle =
+              eval_string (fname.substr (4), true, parse_status);
+
+            if (parse_status == 0)
+              {
+                octave_fcn_handle *fh =
+                  anon_fcn_handle.fcn_handle_value ();
+
+                if (fh)
+                  tc = new octave_fcn_handle (fh->fcn_val (), "@<anonymous>");
+                else
+                  {
+                    error ("load: failed to load anonymous function handle");
+                    goto skip_ahead;
+                  }
+              }
+            else
+              {
+                error ("load: failed to load anonymous function handle");
+                goto skip_ahead;
+              }
+
+            frame.run ();
+          }
+        else
+          {
+            error ("load: invalid function handle type");
+            goto skip_ahead;
+          }
+      }
+      break;
+
+    case MAT_FILE_WORKSPACE_CLASS:
+      {
+        Octave_map m (dim_vector (1, 1));
+        int n_fields = 2;
+        string_vector field (n_fields);
+
+        for (int i = 0; i < n_fields; i++)
+          {
+            int32_t fn_type;
+            int32_t fn_len;
+            if (read_mat5_tag (is, swap, fn_type, fn_len) || fn_type != miINT8)
+              {
+                error ("load: invalid field name subelement");
+                goto data_read_error;
+              }
+
+            OCTAVE_LOCAL_BUFFER (char, elname, fn_len + 1);
+
+            std::streampos tmp_pos = is.tellg ();
+
+            if (fn_len)
+              {
+                if (! is.read (elname, fn_len))
+                  goto data_read_error;
+
+                is.seekg (tmp_pos +
+                          static_cast<std::streamoff> (PAD (fn_len)));
+              }
+
+            elname[fn_len] = '\0';
+
+            field(i) = elname;
+          }
+
+        std::vector<Cell> elt (n_fields);
+
+        for (octave_idx_type i = 0; i < n_fields; i++)
+          elt[i] = Cell (dims);
+
+        octave_idx_type n = dims.numel ();
+
+        // fields subelements
+        for (octave_idx_type j = 0; j < n; j++)
+          {
+            for (octave_idx_type i = 0; i < n_fields; i++)
+              {
+                if (field(i) == "MCOS")
+                  {
+                    octave_value fieldtc;
+                    read_mat5_binary_element (is, filename, swap, global,
+                                              fieldtc);
+                    if (! is || error_state)
+                      goto data_read_error;
+
+                    elt[i](j) = fieldtc;
+                  }
+                else
+                  elt[i](j) = octave_value ();
+              }
+          }
+
+        for (octave_idx_type i = 0; i < n_fields; i++)
+          m.assign (field (i), elt[i]);
+        tc = m;
+      }
+      break;
+
+    case MAT_FILE_OBJECT_CLASS:
+      {
+        isclass = true;
+
+        if (read_mat5_tag (is, swap, type, len) || type != miINT8)
+          {
+            error ("load: invalid class name");
+            goto skip_ahead;
+          }
+
+        {
+          OCTAVE_LOCAL_BUFFER (char, name, len+1);
+
+          std::streampos tmp_pos = is.tellg ();
+
+          if (len)
+            {
+              if (! is.read (name, len ))
+                goto data_read_error;
+
+              is.seekg (tmp_pos + static_cast<std::streamoff> (PAD (len)));
+            }
+
+          name[len] = '\0';
+          classname = name;
+        }
+      }
+      // Fall-through
+    case MAT_FILE_STRUCT_CLASS:
+      {
+        Octave_map m (dim_vector (1, 1));
+        int32_t fn_type;
+        int32_t fn_len;
+        int32_t field_name_length;
+
+        // field name length subelement -- actually the maximum length
+        // of a field name.  The Matlab docs promise this will always
+        // be 32.  We read and use the actual value, on the theory
+        // that eventually someone will recognize that's a waste of
+        // space.
+        if (read_mat5_tag (is, swap, fn_type, fn_len) || fn_type != miINT32)
+          {
+            error ("load: invalid field name length subelement");
+            goto data_read_error;
+          }
+
+        if (! is.read (reinterpret_cast<char *> (&field_name_length), fn_len ))
+          goto data_read_error;
+
+        if (swap)
+          swap_bytes<4> (&field_name_length);
+
+        // field name subelement.  The length of this subelement tells
+        // us how many fields there are.
+        if (read_mat5_tag (is, swap, fn_type, fn_len) || fn_type != miINT8)
+          {
+            error ("load: invalid field name subelement");
+            goto data_read_error;
+          }
+
+        octave_idx_type n_fields = fn_len/field_name_length;
+
+        if (n_fields > 0)
+          {
+            fn_len = PAD (fn_len);
+
+            OCTAVE_LOCAL_BUFFER (char, elname, fn_len);
+
+            if (! is.read (elname, fn_len))
+              goto data_read_error;
+
+            std::vector<Cell> elt (n_fields);
+
+            for (octave_idx_type i = 0; i < n_fields; i++)
+              elt[i] = Cell (dims);
+
+            octave_idx_type n = dims.numel ();
+
+            // fields subelements
+            for (octave_idx_type j = 0; j < n; j++)
+              {
+                for (octave_idx_type i = 0; i < n_fields; i++)
+                  {
+                    octave_value fieldtc;
+                    read_mat5_binary_element (is, filename, swap, global,
+                                              fieldtc);
+                    elt[i](j) = fieldtc;
+                  }
+              }
+
+            for (octave_idx_type i = 0; i < n_fields; i++)
+              {
+                const char *key = elname + i*field_name_length;
+
+                m.assign (key, elt[i]);
+              }
+          }
+
+        if (isclass)
+          {
+            if (classname == "inline")
+              {
+                // inline is not an object in Octave but rather an
+                // overload of a function handle. Special case.
+                tc =
+                  new octave_fcn_inline (m.contents ("expr")(0).string_value (),
+                                         m.contents ("args")(0).string_value ());
+              }
+            else
+              {
+                octave_class* cls
+                  = new octave_class (m, classname,
+                                      std::list<std::string> ());
+
+                if (cls->reconstruct_exemplar ())
+                  {
+
+                    if (! cls->reconstruct_parents ())
+                      warning ("load: unable to reconstruct object inheritance");
+
+                    tc = cls;
+                    if (load_path::find_method (classname, "loadobj") !=
+                        std::string ())
+                      {
+                        octave_value_list tmp = feval ("loadobj", tc, 1);
+
+                        if (! error_state)
+                          tc = tmp(0);
+                        else
+                          goto data_read_error;
+                      }
+                  }
+                else
+                  {
+                    tc = m;
+                    warning ("load: element has been converted to a structure");
+                  }
+              }
+          }
+        else
+          tc = m;
+      }
+      break;
+
+    case MAT_FILE_INT8_CLASS:
+      OCTAVE_MAT5_INTEGER_READ (int8NDArray);
+      break;
+
+    case MAT_FILE_UINT8_CLASS:
+      {
+        OCTAVE_MAT5_INTEGER_READ (uint8NDArray);
+
+        // Logical variables can either be MAT_FILE_UINT8_CLASS or
+        // MAT_FILE_DOUBLE_CLASS, so check if we have a logical
+        // variable and convert it.
+
+        if (logicalvar)
+          {
+            uint8NDArray in = tc.uint8_array_value ();
+            octave_idx_type nel = in.numel ();
+            boolNDArray out (dims);
+
+            for (octave_idx_type i = 0; i < nel; i++)
+              out(i) = in(i).bool_value ();
+
+            tc = out;
+          }
+      }
+      break;
+
+    case MAT_FILE_INT16_CLASS:
+      OCTAVE_MAT5_INTEGER_READ (int16NDArray);
+      break;
+
+    case MAT_FILE_UINT16_CLASS:
+      OCTAVE_MAT5_INTEGER_READ (uint16NDArray);
+      break;
+
+    case MAT_FILE_INT32_CLASS:
+      OCTAVE_MAT5_INTEGER_READ (int32NDArray);
+      break;
+
+    case MAT_FILE_UINT32_CLASS:
+      OCTAVE_MAT5_INTEGER_READ (uint32NDArray);
+      break;
+
+    case MAT_FILE_INT64_CLASS:
+      OCTAVE_MAT5_INTEGER_READ (int64NDArray);
+      break;
+
+    case MAT_FILE_UINT64_CLASS:
+      OCTAVE_MAT5_INTEGER_READ (uint64NDArray);
+      break;
+
+
+    case MAT_FILE_SINGLE_CLASS:
+      {
+        FloatNDArray re (dims);
+
+        // real data subelement
+
+        std::streampos tmp_pos;
+
+        if (read_mat5_tag (is, swap, type, len))
+          {
+            error ("load: reading matrix data for `%s'", retval.c_str ());
+            goto data_read_error;
+          }
+
+        octave_idx_type n = re.numel ();
+        tmp_pos = is.tellg ();
+        read_mat5_binary_data (is, re.fortran_vec (), n, swap,
+                               static_cast<enum mat5_data_type> (type), flt_fmt);
+
+        if (! is || error_state)
+          {
+            error ("load: reading matrix data for `%s'", retval.c_str ());
+            goto data_read_error;
+          }
+
+        is.seekg (tmp_pos + static_cast<std::streamoff> (PAD (len)));
+
+        if (imag)
+          {
+            // imaginary data subelement
+
+            FloatNDArray im (dims);
+
+            if (read_mat5_tag (is, swap, type, len))
+              {
+                error ("load: reading matrix data for `%s'", retval.c_str ());
+                goto data_read_error;
+              }
+
+            n = im.numel ();
+            read_mat5_binary_data (is, im.fortran_vec (), n, swap,
+                                   static_cast<enum mat5_data_type> (type), flt_fmt);
+
+            if (! is || error_state)
+              {
+                error ("load: reading imaginary matrix data for `%s'",
+                       retval.c_str ());
+                goto data_read_error;
+              }
+
+            FloatComplexNDArray ctmp (dims);
+
+            for (octave_idx_type i = 0; i < n; i++)
+              ctmp(i) = FloatComplex (re(i), im(i));
+
+            tc = ctmp;
+          }
+        else
+          tc = re;
+      }
+      break;
+
+    case MAT_FILE_CHAR_CLASS:
+      // handle as a numerical array to start with
+
+    case MAT_FILE_DOUBLE_CLASS:
+    default:
+      {
+        NDArray re (dims);
+
+        // real data subelement
+
+        std::streampos tmp_pos;
+
+        if (read_mat5_tag (is, swap, type, len))
+          {
+            error ("load: reading matrix data for `%s'", retval.c_str ());
+            goto data_read_error;
+          }
+
+        octave_idx_type n = re.numel ();
+        tmp_pos = is.tellg ();
+        read_mat5_binary_data (is, re.fortran_vec (), n, swap,
+                               static_cast<enum mat5_data_type> (type), flt_fmt);
+
+        if (! is || error_state)
+          {
+            error ("load: reading matrix data for `%s'", retval.c_str ());
+            goto data_read_error;
+          }
+
+        is.seekg (tmp_pos + static_cast<std::streamoff> (PAD (len)));
+
+        if (logicalvar)
+          {
+            // Logical variables can either be MAT_FILE_UINT8_CLASS or
+            // MAT_FILE_DOUBLE_CLASS, so check if we have a logical
+            // variable and convert it.
+
+            boolNDArray out (dims);
+
+            for (octave_idx_type i = 0; i < n; i++)
+              out (i) = static_cast<bool> (re (i));
+
+            tc = out;
+          }
+        else if (imag)
+          {
+            // imaginary data subelement
+
+            NDArray im (dims);
+
+            if (read_mat5_tag (is, swap, type, len))
+              {
+                error ("load: reading matrix data for `%s'", retval.c_str ());
+                goto data_read_error;
+              }
+
+            n = im.numel ();
+            read_mat5_binary_data (is, im.fortran_vec (), n, swap,
+                                   static_cast<enum mat5_data_type> (type), flt_fmt);
+
+            if (! is || error_state)
+              {
+                error ("load: reading imaginary matrix data for `%s'",
+                       retval.c_str ());
+                goto data_read_error;
+              }
+
+            ComplexNDArray ctmp (dims);
+
+            for (octave_idx_type i = 0; i < n; i++)
+              ctmp(i) = Complex (re(i), im(i));
+
+            tc = ctmp;
+          }
+        else
+          {
+            if (arrayclass == MAT_FILE_CHAR_CLASS)
+              {
+                if (type == miUTF16 || type == miUTF32)
+                  {
+                    bool found_big_char = false;
+                    for (octave_idx_type i = 0; i < n; i++)
+                      {
+                        if (re(i) > 127) {
+                          re(i) = '?';
+                          found_big_char = true;
+                        }
+                      }
+
+                    if (found_big_char)
+                      warning ("load: can not read non-ASCII portions of UTF characters; replacing unreadable characters with '?'");
+                  }
+                else if (type == miUTF8)
+                  {
+                    // Search for multi-byte encoded UTF8 characters and
+                    // replace with 0x3F for '?'... Give the user a warning
+
+                    bool utf8_multi_byte = false;
+                    for (octave_idx_type i = 0; i < n; i++)
+                      {
+                        unsigned char a = static_cast<unsigned char> (re(i));
+                        if (a > 0x7f)
+                          utf8_multi_byte = true;
+                      }
+
+                    if (utf8_multi_byte)
+                      {
+                        warning ("load: can not read multi-byte encoded UTF8 characters; replacing unreadable characters with '?'");
+                        for (octave_idx_type i = 0; i < n; i++)
+                          {
+                            unsigned char a = static_cast<unsigned char> (re(i));
+                            if (a > 0x7f)
+                              re(i) = '?';
+                          }
+                      }
+                  }
+                tc = re;
+                tc = tc.convert_to_str (false, true, '\'');
+              }
+            else
+              tc = re;
+          }
+      }
+    }
+
+  is.seekg (pos + static_cast<std::streamoff> (element_length));
+
+  if (is.eof ())
+    is.clear ();
+
+  return retval;
+
+ data_read_error:
+ early_read_error:
+  error ("load: trouble reading binary file `%s'", filename.c_str ());
+  return std::string ();
+
+ skip_ahead:
+  warning ("skipping over `%s'", retval.c_str ());
+  is.seekg (pos + static_cast<std::streamoff> (element_length));
+  return read_mat5_binary_element (is, filename, swap, global, tc);
+}
+
+int
+read_mat5_binary_file_header (std::istream& is, bool& swap, bool quiet,
+                              const std::string& filename)
+{
+  int16_t version=0, magic=0;
+  uint64_t subsys_offset;
+
+  is.seekg (116, std::ios::beg);
+  is.read (reinterpret_cast<char *> (&subsys_offset), 8);
+
+  is.seekg (124, std::ios::beg);
+  is.read (reinterpret_cast<char *> (&version), 2);
+  is.read (reinterpret_cast<char *> (&magic), 2);
+
+  if (magic == 0x4d49)
+    swap = 0;
+  else if (magic == 0x494d)
+    swap = 1;
+  else
+    {
+      if (! quiet)
+        error ("load: can't read binary file");
+      return -1;
+    }
+
+  if (! swap)                   // version number is inverse swapped!
+    version = ((version >> 8) & 0xff) + ((version & 0xff) << 8);
+
+  if (version != 1 && !quiet)
+    warning ("load: found version %d binary MAT file, "
+             "but only prepared for version 1", version);
+
+  if (swap)
+    swap_bytes<8> (&subsys_offset, 1);
+
+  if (subsys_offset != 0x2020202020202020ULL && subsys_offset != 0ULL)
+    {
+      // Read the subsystem data block
+      is.seekg (subsys_offset, std::ios::beg);
+
+      octave_value tc;
+      bool global;
+      read_mat5_binary_element (is, filename, swap, global, tc);
+
+      if (!is || error_state)
+        return -1;
+
+      if (tc.is_uint8_type ())
+        {
+          const uint8NDArray itmp = tc.uint8_array_value ();
+          octave_idx_type ilen = itmp.numel ();
+
+          // Why should I have to initialize outbuf as just overwrite
+          std::string outbuf (ilen - 7, ' ');
+
+          // FIXME -- find a way to avoid casting away const here
+          char *ctmp = const_cast<char *> (outbuf.c_str ());
+          for (octave_idx_type j = 8; j < ilen; j++)
+            ctmp[j-8] = itmp(j).char_value ();
+
+          std::istringstream fh_ws (outbuf);
+
+          read_mat5_binary_element (fh_ws, filename, swap, global, subsys_ov);
+
+          if (error_state)
+            return -1;
+        }
+      else
+        return -1;
+
+      // Reposition to just after the header
+      is.seekg (128, std::ios::beg);
+    }
+
+  return 0;
+}
+
+static int
+write_mat5_tag (std::ostream& is, int type, octave_idx_type bytes)
+{
+  int32_t temp;
+
+  if (bytes > 0 && bytes <= 4)
+    temp = (bytes << 16) + type;
+  else
+    {
+      temp = type;
+      if (! is.write (reinterpret_cast<char *> (&temp), 4))
+        goto data_write_error;
+      temp = bytes;
+    }
+
+  if (! is.write (reinterpret_cast<char *> (&temp), 4))
+    goto data_write_error;
+
+  return 0;
+
+ data_write_error:
+  return 1;
+}
+
+// Have to use copy here to avoid writing over data accessed via
+// Matrix::data().
+
+#define MAT5_DO_WRITE(TYPE, data, count, stream) \
+  do \
+    { \
+      OCTAVE_LOCAL_BUFFER (TYPE, ptr, count); \
+      for (octave_idx_type i = 0; i < count; i++) \
+        ptr[i] = static_cast<TYPE> (data[i]); \
+      stream.write (reinterpret_cast<char *> (ptr), count * sizeof (TYPE)); \
+    } \
+  while (0)
+
+// write out the numeric values in M to OS,
+// preceded by the appropriate tag.
+static void
+write_mat5_array (std::ostream& os, const NDArray& m, bool save_as_floats)
+{
+  save_type st = LS_DOUBLE;
+  const double *data = m.data ();
+
+  if (save_as_floats)
+    {
+      if (m.too_large_for_float ())
+        {
+          warning ("save: some values too large to save as floats --");
+          warning ("save: saving as doubles instead");
+        }
+      else
+        st = LS_FLOAT;
+    }
+
+  double max_val, min_val;
+  if (m.all_integers (max_val, min_val))
+    st = get_save_type (max_val, min_val);
+
+  mat5_data_type mst;
+  int size;
+  switch (st)
+    {
+    default:
+    case LS_DOUBLE:  mst = miDOUBLE; size = 8; break;
+    case LS_FLOAT:   mst = miSINGLE; size = 4; break;
+    case LS_U_CHAR:  mst = miUINT8;  size = 1; break;
+    case LS_U_SHORT: mst = miUINT16; size = 2; break;
+    case LS_U_INT:   mst = miUINT32; size = 4; break;
+    case LS_CHAR:    mst = miINT8;   size = 1; break;
+    case LS_SHORT:   mst = miINT16;  size = 2; break;
+    case LS_INT:     mst = miINT32;  size = 4; break;
+    }
+
+  octave_idx_type nel = m.numel ();
+  octave_idx_type len = nel*size;
+
+  write_mat5_tag (os, mst, len);
+
+  {
+    switch (st)
+      {
+      case LS_U_CHAR:
+        MAT5_DO_WRITE (uint8_t, data, nel, os);
+        break;
+
+      case LS_U_SHORT:
+        MAT5_DO_WRITE (uint16_t, data, nel, os);
+        break;
+
+      case LS_U_INT:
+        MAT5_DO_WRITE (uint32_t, data, nel, os);
+        break;
+
+      case LS_U_LONG:
+        MAT5_DO_WRITE (uint64_t, data, nel, os);
+        break;
+
+      case LS_CHAR:
+        MAT5_DO_WRITE (int8_t, data, nel, os);
+        break;
+
+      case LS_SHORT:
+        MAT5_DO_WRITE (int16_t, data, nel, os);
+        break;
+
+      case LS_INT:
+        MAT5_DO_WRITE (int32_t, data, nel, os);
+        break;
+
+      case LS_LONG:
+        MAT5_DO_WRITE (int64_t, data, nel, os);
+        break;
+
+      case LS_FLOAT:
+        MAT5_DO_WRITE (float, data, nel, os);
+        break;
+
+      case LS_DOUBLE: // No conversion necessary.
+        os.write (reinterpret_cast<const char *> (data), len);
+        break;
+
+      default:
+        (*current_liboctave_error_handler)
+          ("unrecognized data format requested");
+        break;
+      }
+  }
+  if (PAD (len) > len)
+    {
+      static char buf[9]="\x00\x00\x00\x00\x00\x00\x00\x00";
+      os.write (buf, PAD (len) - len);
+    }
+}
+
+static void
+write_mat5_array (std::ostream& os, const FloatNDArray& m, bool)
+{
+  save_type st = LS_FLOAT;
+  const float *data = m.data ();
+
+  float max_val, min_val;
+  if (m.all_integers (max_val, min_val))
+    st = get_save_type (max_val, min_val);
+
+  mat5_data_type mst;
+  int size;
+  switch (st)
+    {
+    default:
+    case LS_DOUBLE:  mst = miDOUBLE; size = 8; break;
+    case LS_FLOAT:   mst = miSINGLE; size = 4; break;
+    case LS_U_CHAR:  mst = miUINT8;  size = 1; break;
+    case LS_U_SHORT: mst = miUINT16; size = 2; break;
+    case LS_U_INT:   mst = miUINT32; size = 4; break;
+    case LS_CHAR:    mst = miINT8;   size = 1; break;
+    case LS_SHORT:   mst = miINT16;  size = 2; break;
+    case LS_INT:     mst = miINT32;  size = 4; break;
+    }
+
+  octave_idx_type nel = m.numel ();
+  octave_idx_type len = nel*size;
+
+  write_mat5_tag (os, mst, len);
+
+  {
+    switch (st)
+      {
+      case LS_U_CHAR:
+        MAT5_DO_WRITE (uint8_t, data, nel, os);
+        break;
+
+      case LS_U_SHORT:
+        MAT5_DO_WRITE (uint16_t, data, nel, os);
+        break;
+
+      case LS_U_INT:
+        MAT5_DO_WRITE (uint32_t, data, nel, os);
+        break;
+
+      case LS_U_LONG:
+        MAT5_DO_WRITE (uint64_t, data, nel, os);
+        break;
+
+      case LS_CHAR:
+        MAT5_DO_WRITE (int8_t, data, nel, os);
+        break;
+
+      case LS_SHORT:
+        MAT5_DO_WRITE (int16_t, data, nel, os);
+        break;
+
+      case LS_INT:
+        MAT5_DO_WRITE (int32_t, data, nel, os);
+        break;
+
+      case LS_LONG:
+        MAT5_DO_WRITE (int64_t, data, nel, os);
+        break;
+
+      case LS_FLOAT: // No conversion necessary.
+        os.write (reinterpret_cast<const char *> (data), len);
+        break;
+
+      case LS_DOUBLE:
+        MAT5_DO_WRITE (double, data, nel, os);
+        break;
+
+      default:
+        (*current_liboctave_error_handler)
+          ("unrecognized data format requested");
+        break;
+      }
+  }
+  if (PAD (len) > len)
+    {
+      static char buf[9]="\x00\x00\x00\x00\x00\x00\x00\x00";
+      os.write (buf, PAD (len) - len);
+    }
+}
+
+template <class T>
+void
+write_mat5_integer_data (std::ostream& os, const T *m, int size,
+                         octave_idx_type nel)
+{
+  mat5_data_type mst;
+  unsigned len;
+
+  switch (size)
+    {
+    case 1:
+      mst = miUINT8;
+      break;
+    case 2:
+      mst = miUINT16;
+      break;
+    case 4:
+      mst = miUINT32;
+      break;
+    case 8:
+      mst = miUINT64;
+      break;
+    case -1:
+      mst = miINT8;
+      size = - size;
+      break;
+    case -2:
+      mst = miINT16;
+      size = - size;
+      break;
+    case -4:
+      mst = miINT32;
+      size = - size;
+      break;
+    case -8:
+    default:
+      mst = miINT64;
+      size = - size;
+      break;
+    }
+
+  len = nel*size;
+  write_mat5_tag (os, mst, len);
+
+  os.write (reinterpret_cast<const char *> (m), len);
+
+  if (PAD (len) > len)
+    {
+      static char buf[9]="\x00\x00\x00\x00\x00\x00\x00\x00";
+      os.write (buf, PAD (len) - len);
+    }
+}
+
+template void
+write_mat5_integer_data (std::ostream& os, const octave_int8 *m,
+                         int size, octave_idx_type nel);
+
+template void
+write_mat5_integer_data (std::ostream& os, const octave_int16 *m,
+                         int size, octave_idx_type nel);
+
+template void
+write_mat5_integer_data (std::ostream& os, const octave_int32 *m,
+                         int size, octave_idx_type nel);
+
+template void
+write_mat5_integer_data (std::ostream& os, const octave_int64 *m,
+                         int size, octave_idx_type nel);
+
+template void
+write_mat5_integer_data (std::ostream& os, const octave_uint8 *m,
+                         int size, octave_idx_type nel);
+
+template void
+write_mat5_integer_data (std::ostream& os, const octave_uint16 *m,
+                         int size, octave_idx_type nel);
+
+template void
+write_mat5_integer_data (std::ostream& os, const octave_uint32 *m,
+                         int size, octave_idx_type nel);
+
+template void
+write_mat5_integer_data (std::ostream& os, const octave_uint64 *m,
+                         int size, octave_idx_type nel);
+
+template void
+write_mat5_integer_data (std::ostream& os, const int *m,
+                         int size, octave_idx_type nel);
+
+// Write out cell element values in the cell array to OS, preceded by
+// the appropriate tag.
+
+static bool
+write_mat5_cell_array (std::ostream& os, const Cell& cell,
+                       bool mark_as_global, bool save_as_floats)
+{
+  octave_idx_type nel = cell.numel ();
+
+  for (octave_idx_type i = 0; i < nel; i++)
+    {
+      octave_value ov = cell(i);
+
+      if (! save_mat5_binary_element (os, ov, "", mark_as_global,
+                                      false, save_as_floats))
+        return false;
+    }
+
+  return true;
+}
+
+int
+save_mat5_array_length (const double* val, octave_idx_type nel,
+                        bool save_as_floats)
+{
+  if (nel > 0)
+    {
+      int size = 8;
+
+      if (save_as_floats)
+        {
+          bool too_large_for_float = false;
+          for (octave_idx_type i = 0; i < nel; i++)
+            {
+              double tmp = val[i];
+
+              if (! (xisnan (tmp) || xisinf (tmp))
+                  && fabs (tmp) > FLT_MAX)
+                {
+                  too_large_for_float = true;
+                  break;
+                }
+            }
+
+          if (!too_large_for_float)
+            size = 4;
+        }
+
+      // The code below is disabled since get_save_type currently doesn't
+      // deal with integer types. This will need to be activated if get_save_type
+      // is changed.
+
+      // double max_val = val[0];
+      // double min_val = val[0];
+      // bool all_integers =  true;
+      //
+      // for (int i = 0; i < nel; i++)
+      //   {
+      //     double val = val[i];
+      //
+      //     if (val > max_val)
+      //       max_val = val;
+      //
+      //     if (val < min_val)
+      //       min_val = val;
+      //
+      //     if (D_NINT (val) != val)
+      //       {
+      //         all_integers = false;
+      //         break;
+      //       }
+      //   }
+      //
+      // if (all_integers)
+      //   {
+      //     if (max_val < 256 && min_val > -1)
+      //       size = 1;
+      //     else if (max_val < 65536 && min_val > -1)
+      //       size = 2;
+      //     else if (max_val < 4294967295UL && min_val > -1)
+      //       size = 4;
+      //     else if (max_val < 128 && min_val >= -128)
+      //       size = 1;
+      //     else if (max_val < 32768 && min_val >= -32768)
+      //       size = 2;
+      //     else if (max_val <= 2147483647L && min_val >= -2147483647L)
+      //       size = 4;
+      //   }
+
+      return 8 + nel * size;
+    }
+  else
+    return 8;
+}
+
+int
+save_mat5_array_length (const float* /* val */, octave_idx_type nel, bool)
+{
+  if (nel > 0)
+    {
+      int size = 4;
+
+
+      // The code below is disabled since get_save_type currently doesn't
+      // deal with integer types. This will need to be activated if get_save_type
+      // is changed.
+
+      // float max_val = val[0];
+      // float min_val = val[0];
+      // bool all_integers =  true;
+      //
+      // for (int i = 0; i < nel; i++)
+      //   {
+      //     float val = val[i];
+      //
+      //     if (val > max_val)
+      //       max_val = val;
+      //
+      //     if (val < min_val)
+      //       min_val = val;
+      //
+      //     if (D_NINT (val) != val)
+      //       {
+      //         all_integers = false;
+      //         break;
+      //       }
+      //   }
+      //
+      // if (all_integers)
+      //   {
+      //     if (max_val < 256 && min_val > -1)
+      //       size = 1;
+      //     else if (max_val < 65536 && min_val > -1)
+      //       size = 2;
+      //     else if (max_val < 4294967295UL && min_val > -1)
+      //       size = 4;
+      //     else if (max_val < 128 && min_val >= -128)
+      //       size = 1;
+      //     else if (max_val < 32768 && min_val >= -32768)
+      //       size = 2;
+      //     else if (max_val <= 2147483647L && min_val >= -2147483647L)
+      //       size = 4;
+      //   }
+
+      // Round nel up to nearest even number of elements. Take into account
+      // Short tags for 4 byte elements.
+      return PAD ((nel > 0 && nel * size <= 4 ? 4 : 8) + nel * size);
+    }
+  else
+    return 8;
+}
+
+int
+save_mat5_array_length (const Complex* val, octave_idx_type nel,
+                        bool save_as_floats)
+{
+  int ret;
+
+  OCTAVE_LOCAL_BUFFER (double, tmp, nel);
+
+  for (octave_idx_type i = 1; i < nel; i++)
+    tmp[i] = std::real (val[i]);
+
+  ret = save_mat5_array_length (tmp, nel, save_as_floats);
+
+  for (octave_idx_type i = 1; i < nel; i++)
+    tmp[i] = std::imag (val[i]);
+
+  ret += save_mat5_array_length (tmp, nel, save_as_floats);
+
+  return ret;
+}
+
+int
+save_mat5_array_length (const FloatComplex* val, octave_idx_type nel,
+                        bool save_as_floats)
+{
+  int ret;
+
+  OCTAVE_LOCAL_BUFFER (float, tmp, nel);
+
+  for (octave_idx_type i = 1; i < nel; i++)
+    tmp[i] = std::real (val[i]);
+
+  ret = save_mat5_array_length (tmp, nel, save_as_floats);
+
+  for (octave_idx_type i = 1; i < nel; i++)
+    tmp[i] = std::imag (val[i]);
+
+  ret += save_mat5_array_length (tmp, nel, save_as_floats);
+
+  return ret;
+}
+
+int
+save_mat5_element_length (const octave_value& tc, const std::string& name,
+                          bool save_as_floats, bool mat7_format)
+{
+  size_t max_namelen = (mat7_format ? 63 : 31);
+  size_t len = name.length ();
+  std::string cname = tc.class_name ();
+  int ret = 32;
+
+  if (len > 4)
+    ret += PAD (len > max_namelen ? max_namelen : len);
+
+  ret += PAD (4 * tc.ndims ());
+
+  if (tc.is_string ())
+    {
+      charNDArray chm = tc.char_array_value ();
+      ret += 8;
+      if (chm.numel () > 2)
+        ret += PAD (2 * chm.numel ());
+    }
+  else if (tc.is_sparse_type ())
+    {
+      if (tc.is_complex_type ())
+        {
+          const SparseComplexMatrix m = tc.sparse_complex_matrix_value ();
+          octave_idx_type nc = m.cols ();
+          octave_idx_type nnz = m.nnz ();
+
+          ret += 16 + save_mat5_array_length (m.data (), nnz, save_as_floats);
+          if (nnz > 1)
+            ret += PAD (nnz * sizeof (int32_t));
+          if (nc > 0)
+            ret += PAD ((nc + 1) * sizeof (int32_t));
+        }
+      else
+        {
+          const SparseMatrix m = tc.sparse_matrix_value ();
+          octave_idx_type nc = m.cols ();
+          octave_idx_type nnz = m.nnz ();
+
+          ret += 16 + save_mat5_array_length (m.data (), nnz, save_as_floats);
+          if (nnz > 1)
+            ret += PAD (nnz * sizeof (int32_t));
+          if (nc > 0)
+            ret += PAD ((nc + 1) * sizeof (int32_t));
+        }
+    }
+
+#define INT_LEN(nel, size) \
+  { \
+    ret += 8; \
+    octave_idx_type sz = nel * size; \
+    if (sz > 4) \
+      ret += PAD (sz);  \
+  }
+
+  else if (cname == "int8")
+    INT_LEN (tc.int8_array_value ().numel (), 1)
+  else if (cname == "int16")
+    INT_LEN (tc.int16_array_value ().numel (), 2)
+  else if (cname == "int32")
+    INT_LEN (tc.int32_array_value ().numel (), 4)
+  else if (cname == "int64")
+    INT_LEN (tc.int64_array_value ().numel (), 8)
+  else if (cname == "uint8")
+    INT_LEN (tc.uint8_array_value ().numel (), 1)
+  else if (cname == "uint16")
+    INT_LEN (tc.uint16_array_value ().numel (), 2)
+  else if (cname == "uint32")
+    INT_LEN (tc.uint32_array_value ().numel (), 4)
+  else if (cname == "uint64")
+    INT_LEN (tc.uint64_array_value ().numel (), 8)
+  else if (tc.is_bool_type ())
+    INT_LEN (tc.bool_array_value ().numel (), 1)
+  else if (tc.is_real_scalar () || tc.is_real_matrix () || tc.is_range ())
+    {
+      if (tc.is_single_type ())
+        {
+          const FloatNDArray m = tc.float_array_value ();
+          ret += save_mat5_array_length (m.fortran_vec (), m.numel (),
+                                         save_as_floats);
+        }
+      else
+        {
+          const NDArray m = tc.array_value ();
+          ret += save_mat5_array_length (m.fortran_vec (), m.numel (),
+                                         save_as_floats);
+        }
+    }
+  else if (tc.is_cell ())
+    {
+      Cell cell = tc.cell_value ();
+      octave_idx_type nel = cell.numel ();
+
+      for (int i = 0; i < nel; i++)
+        ret += 8 +
+          save_mat5_element_length (cell (i), "", save_as_floats, mat7_format);
+    }
+  else if (tc.is_complex_scalar () || tc.is_complex_matrix ())
+    {
+      if (tc.is_single_type ())
+        {
+          const FloatComplexNDArray m = tc.float_complex_array_value ();
+          ret += save_mat5_array_length (m.fortran_vec (), m.numel (),
+                                         save_as_floats);
+        }
+      else
+        {
+          const ComplexNDArray m = tc.complex_array_value ();
+          ret += save_mat5_array_length (m.fortran_vec (), m.numel (),
+                                         save_as_floats);
+        }
+    }
+  else if (tc.is_map () || tc.is_inline_function () || tc.is_object ())
+    {
+      int fieldcnt = 0;
+      const Octave_map m = tc.map_value ();
+      octave_idx_type nel = m.numel ();
+
+      if (tc.is_inline_function ())
+        // length of "inline" is 6
+        ret += 8 + PAD (6 > max_namelen ? max_namelen : 6);
+      else if (tc.is_object ())
+        {
+          size_t classlen = tc.class_name (). length ();
+
+          ret += 8 + PAD (classlen > max_namelen ? max_namelen : classlen);
+        }
+
+      for (Octave_map::const_iterator i = m.begin (); i != m.end (); i++)
+        fieldcnt++;
+
+      ret += 16 + fieldcnt * (max_namelen + 1);
+
+
+      for (octave_idx_type j = 0; j < nel; j++)
+        {
+
+          for (Octave_map::const_iterator i = m.begin (); i != m.end (); i++)
+            {
+              const Cell elts = m.contents (i);
+
+              ret += 8 + save_mat5_element_length (elts(j), "",
+                                               save_as_floats, mat7_format);
+            }
+        }
+    }
+  else
+    ret = -1;
+
+  return ret;
+}
+
+static void
+write_mat5_sparse_index_vector (std::ostream& os,
+                                const octave_idx_type *idx,
+                                octave_idx_type nel)
+{
+  int tmp = sizeof (int32_t);
+
+  OCTAVE_LOCAL_BUFFER (int32_t, tmp_idx, nel);
+
+  for (octave_idx_type i = 0; i < nel; i++)
+    tmp_idx[i] = idx[i];
+
+  write_mat5_integer_data (os, tmp_idx, -tmp, nel);
+}
+
+static void
+gripe_dim_too_large (const std::string& name)
+{
+  warning ("save: skipping %s: dimension too large for MAT format",
+           name.c_str ());
+}
+
+// save the data from TC along with the corresponding NAME on stream
+// OS in the MatLab version 5 binary format.  Return true on success.
+
+bool
+save_mat5_binary_element (std::ostream& os,
+                          const octave_value& tc, const std::string& name,
+                          bool mark_as_global, bool mat7_format,
+                          bool save_as_floats, bool compressing)
+{
+  int32_t flags = 0;
+  int32_t nnz_32 = 0;
+  std::string cname = tc.class_name ();
+  size_t max_namelen = (mat7_format ? 63 : 31);
+
+  dim_vector dv = tc.dims ();
+  int nd = tc.ndims ();
+  int dim_len = 4*nd;
+
+  static octave_idx_type max_dim_val = std::numeric_limits<int32_t>::max ();
+
+  for (int i = 0; i < nd; i++)
+    {
+      if (dv(i) > max_dim_val)
+        {
+          gripe_dim_too_large (name);
+          goto skip_to_next;
+        }
+    }
+
+  if (tc.is_sparse_type ())
+    {
+      octave_idx_type nnz;
+      octave_idx_type nc;
+
+      if (tc.is_complex_type ())
+        {
+          SparseComplexMatrix scm = tc.sparse_complex_matrix_value ();
+          nnz = scm.nzmax ();
+          nc = scm.cols ();
+        }
+      else
+        {
+          SparseMatrix sm = tc.sparse_matrix_value ();
+          nnz = sm.nzmax ();
+          nc = sm.cols ();
+        }
+
+      if (nnz > max_dim_val || nc + 1 > max_dim_val)
+        {
+          gripe_dim_too_large (name);
+          goto skip_to_next;
+        }
+
+      nnz_32 = nnz;
+    }
+  else if (dv.numel () > max_dim_val)
+    {
+      gripe_dim_too_large (name);
+      goto skip_to_next;
+    }
+
+#ifdef HAVE_ZLIB
+  if (mat7_format && !compressing)
+    {
+      bool ret = false;
+
+      std::ostringstream buf;
+
+      // The code seeks backwards in the stream to fix the header. Can't
+      // do this with zlib, so use a stringstream.
+      ret = save_mat5_binary_element (buf, tc, name, mark_as_global, true,
+                                      save_as_floats, true);
+
+      if (ret)
+        {
+          // destLen must be at least 0.1% larger than source buffer
+          // + 12 bytes. Reality is it must be larger again than that.
+          std::string buf_str = buf.str ();
+          uLongf srcLen = buf_str.length ();
+          uLongf destLen = srcLen * 101 / 100 + 12;
+          OCTAVE_LOCAL_BUFFER (char, out_buf, destLen);
+
+          if (compress (reinterpret_cast<Bytef *> (out_buf), &destLen,
+                        reinterpret_cast<const Bytef *> (buf_str.c_str ()), srcLen) == Z_OK)
+            {
+              write_mat5_tag (os, miCOMPRESSED,
+                              static_cast<octave_idx_type> (destLen));
+
+              os.write (out_buf, destLen);
+            }
+          else
+            {
+              error ("save: error compressing data element");
+              ret = false;
+            }
+        }
+
+      return ret;
+    }
+#endif
+
+  write_mat5_tag (os, miMATRIX, save_mat5_element_length
+                  (tc, name, save_as_floats, mat7_format));
+
+  // array flags subelement
+  write_mat5_tag (os, miUINT32, 8);
+
+  if (tc.is_bool_type ())
+    flags |= 0x0200;
+
+  if (mark_as_global)
+    flags |= 0x0400;
+
+  if (tc.is_complex_scalar () || tc.is_complex_matrix ())
+    flags |= 0x0800;
+
+  if (tc.is_string ())
+    flags |= MAT_FILE_CHAR_CLASS;
+  else if (cname == "int8")
+    flags |= MAT_FILE_INT8_CLASS;
+  else if (cname == "int16")
+    flags |= MAT_FILE_INT16_CLASS;
+  else if (cname == "int32")
+    flags |= MAT_FILE_INT32_CLASS;
+  else if (cname == "int64")
+    flags |= MAT_FILE_INT64_CLASS;
+  else if (cname == "uint8" || tc.is_bool_type ())
+    flags |= MAT_FILE_UINT8_CLASS;
+  else if (cname == "uint16")
+    flags |= MAT_FILE_UINT16_CLASS;
+  else if (cname == "uint32")
+    flags |= MAT_FILE_UINT32_CLASS;
+  else if (cname == "uint64")
+    flags |= MAT_FILE_UINT64_CLASS;
+  else if (tc.is_sparse_type ())
+    flags |= MAT_FILE_SPARSE_CLASS;
+  else if (tc.is_real_scalar () || tc.is_real_matrix () || tc.is_range ()
+           || tc.is_complex_scalar () || tc.is_complex_matrix ())
+    {
+      if (tc.is_single_type ())
+        flags |= MAT_FILE_SINGLE_CLASS;
+      else
+        flags |= MAT_FILE_DOUBLE_CLASS;
+    }
+  else if (tc.is_map ())
+    flags |= MAT_FILE_STRUCT_CLASS;
+  else if (tc.is_cell ())
+    flags |= MAT_FILE_CELL_CLASS;
+  else if (tc.is_inline_function () || tc.is_object ())
+    flags |= MAT_FILE_OBJECT_CLASS;
+  else
+    {
+      gripe_wrong_type_arg ("save", tc, false);
+      goto error_cleanup;
+    }
+
+  os.write (reinterpret_cast<char *> (&flags), 4);
+  os.write (reinterpret_cast<char *> (&nnz_32), 4);
+
+  write_mat5_tag (os, miINT32, dim_len);
+
+  for (int i = 0; i < nd; i++)
+    {
+      int32_t n = dv(i);
+      os.write (reinterpret_cast<char *> (&n), 4);
+    }
+
+  if (PAD (dim_len) > dim_len)
+    {
+      static char buf[9]="\x00\x00\x00\x00\x00\x00\x00\x00";
+      os.write (buf, PAD (dim_len) - dim_len);
+    }
+
+  // array name subelement
+  {
+    size_t namelen = name.length ();
+
+    if (namelen > max_namelen)
+      namelen = max_namelen; // only 31 or 63 char names permitted in mat file
+
+    int paddedlength = PAD (namelen);
+
+    write_mat5_tag (os, miINT8, namelen);
+    OCTAVE_LOCAL_BUFFER (char, paddedname, paddedlength);
+    memset (paddedname, 0, paddedlength);
+    strncpy (paddedname, name.c_str (), namelen);
+    os.write (paddedname, paddedlength);
+  }
+
+  // data element
+  if (tc.is_string ())
+    {
+      charNDArray chm = tc.char_array_value ();
+      octave_idx_type nel = chm.numel ();
+      octave_idx_type len = nel*2;
+      octave_idx_type paddedlength = PAD (len);
+
+      OCTAVE_LOCAL_BUFFER (int16_t, buf, nel+3);
+      write_mat5_tag (os, miUINT16, len);
+
+      const char *s = chm.data ();
+
+      for (octave_idx_type i = 0; i < nel; i++)
+        buf[i] = *s++ & 0x00FF;
+
+      os.write (reinterpret_cast<char *> (buf), len);
+
+      if (paddedlength > len)
+        {
+          static char padbuf[9]="\x00\x00\x00\x00\x00\x00\x00\x00";
+          os.write (padbuf, paddedlength - len);
+        }
+    }
+  else if (tc.is_sparse_type ())
+    {
+      if (tc.is_complex_type ())
+        {
+          const SparseComplexMatrix m = tc.sparse_complex_matrix_value ();
+          octave_idx_type nnz = m.nnz ();
+          octave_idx_type nc = m.cols ();
+
+          write_mat5_sparse_index_vector (os, m.ridx (), nnz);
+          write_mat5_sparse_index_vector (os, m.cidx (), nc + 1);
+
+          NDArray buf (dim_vector (nnz, 1));
+
+          for (octave_idx_type i = 0; i < nnz; i++)
+            buf (i) = std::real (m.data (i));
+
+          write_mat5_array (os, buf, save_as_floats);
+
+          for (octave_idx_type i = 0; i < nnz; i++)
+            buf (i) = std::imag (m.data (i));
+
+          write_mat5_array (os, buf, save_as_floats);
+        }
+      else
+        {
+          const SparseMatrix m = tc.sparse_matrix_value ();
+          octave_idx_type nnz = m.nnz ();
+          octave_idx_type nc = m.cols ();
+
+          write_mat5_sparse_index_vector (os, m.ridx (), nnz);
+          write_mat5_sparse_index_vector (os, m.cidx (), nc + 1);
+
+          // FIXME
+          // Is there a way to easily do without this buffer
+          NDArray buf (dim_vector (nnz, 1));
+
+          for (int i = 0; i < nnz; i++)
+            buf (i) = m.data (i);
+
+          write_mat5_array (os, buf, save_as_floats);
+        }
+    }
+  else if (cname == "int8")
+    {
+      int8NDArray m = tc.int8_array_value ();
+
+      write_mat5_integer_data (os, m.fortran_vec (), -1, m.numel ());
+    }
+  else if (cname == "int16")
+    {
+      int16NDArray m = tc.int16_array_value ();
+
+      write_mat5_integer_data (os, m.fortran_vec (), -2, m.numel ());
+    }
+  else if (cname == "int32")
+    {
+      int32NDArray m = tc.int32_array_value ();
+
+      write_mat5_integer_data (os, m.fortran_vec (), -4, m.numel ());
+    }
+  else if (cname == "int64")
+    {
+      int64NDArray m = tc.int64_array_value ();
+
+      write_mat5_integer_data (os, m.fortran_vec (), -8, m.numel ());
+    }
+  else if (cname == "uint8")
+    {
+      uint8NDArray m = tc.uint8_array_value ();
+
+      write_mat5_integer_data (os, m.fortran_vec (), 1, m.numel ());
+    }
+  else if (cname == "uint16")
+    {
+      uint16NDArray m = tc.uint16_array_value ();
+
+      write_mat5_integer_data (os, m.fortran_vec (), 2, m.numel ());
+    }
+  else if (cname == "uint32")
+    {
+      uint32NDArray m = tc.uint32_array_value ();
+
+      write_mat5_integer_data (os, m.fortran_vec (), 4, m.numel ());
+    }
+  else if (cname == "uint64")
+    {
+      uint64NDArray m = tc.uint64_array_value ();
+
+      write_mat5_integer_data (os, m.fortran_vec (), 8, m.numel ());
+    }
+  else if (tc.is_bool_type ())
+    {
+      uint8NDArray m (tc.bool_array_value ());
+
+      write_mat5_integer_data (os, m.fortran_vec (), 1, m.numel ());
+    }
+  else if (tc.is_real_scalar () || tc.is_real_matrix () || tc.is_range ())
+    {
+      if (tc.is_single_type ())
+        {
+          FloatNDArray m = tc.float_array_value ();
+
+          write_mat5_array (os, m, save_as_floats);
+        }
+      else
+        {
+          NDArray m = tc.array_value ();
+
+          write_mat5_array (os, m, save_as_floats);
+        }
+    }
+  else if (tc.is_cell ())
+    {
+      Cell cell = tc.cell_value ();
+
+      if (! write_mat5_cell_array (os, cell, mark_as_global, save_as_floats))
+        goto error_cleanup;
+    }
+  else if (tc.is_complex_scalar () || tc.is_complex_matrix ())
+    {
+      if (tc.is_single_type ())
+        {
+          FloatComplexNDArray m_cmplx = tc.float_complex_array_value ();
+
+          write_mat5_array (os, ::real (m_cmplx), save_as_floats);
+          write_mat5_array (os, ::imag (m_cmplx), save_as_floats);
+        }
+      else
+        {
+          ComplexNDArray m_cmplx = tc.complex_array_value ();
+
+          write_mat5_array (os, ::real (m_cmplx), save_as_floats);
+          write_mat5_array (os, ::imag (m_cmplx), save_as_floats);
+        }
+    }
+  else if (tc.is_map () || tc.is_inline_function () || tc.is_object ())
+    {
+      if (tc.is_inline_function () || tc.is_object ())
+        {
+          std::string classname = tc.is_object () ? tc.class_name () : "inline";
+          size_t namelen = classname.length ();
+
+          if (namelen > max_namelen)
+            namelen = max_namelen; // only 31 or 63 char names permitted
+
+          int paddedlength = PAD (namelen);
+
+          write_mat5_tag (os, miINT8, namelen);
+          OCTAVE_LOCAL_BUFFER (char, paddedname, paddedlength);
+          memset (paddedname, 0, paddedlength);
+          strncpy (paddedname, classname.c_str (), namelen);
+          os.write (paddedname, paddedlength);
+        }
+
+      Octave_map m;
+
+      if (tc.is_object () &&
+          load_path::find_method (tc.class_name (), "saveobj") != std::string ())
+        {
+          octave_value_list tmp = feval ("saveobj", tc, 1);
+          if (! error_state)
+            m = tmp(0).map_value ();
+          else
+            goto error_cleanup;
+        }
+      else
+        m = tc.map_value ();
+
+      // an Octave structure */
+      // recursively write each element of the structure
+      {
+        char buf[64];
+        int32_t maxfieldnamelength = max_namelen + 1;
+
+        octave_idx_type nf = m.nfields ();
+
+        write_mat5_tag (os, miINT32, 4);
+        os.write (reinterpret_cast<char *> (&maxfieldnamelength), 4);
+        write_mat5_tag (os, miINT8, nf*maxfieldnamelength);
+
+        // Iterating over the list of keys will preserve the order of
+        // the fields.
+        string_vector keys = m.keys ();
+
+        for (octave_idx_type i = 0; i < nf; i++)
+          {
+            std::string key = keys(i);
+
+            // write the name of each element
+            memset (buf, 0, max_namelen + 1);
+            // only 31 or 63 char names permitted
+            strncpy (buf, key.c_str (), max_namelen);
+            os.write (buf, max_namelen + 1);
+          }
+
+        octave_idx_type len = m.numel ();
+
+        // Create temporary copy of structure contents to avoid
+        // multiple calls of the contents method.
+        std::vector<const octave_value *> elts (nf);
+        for (octave_idx_type i = 0; i < nf; i++)
+          elts[i] = m.contents (keys(i)).data ();
+
+        for (octave_idx_type j = 0; j < len; j++)
+          {
+            // write the data of each element
+
+            // Iterating over the list of keys will preserve the order
+            // of the fields.
+            for (octave_idx_type i = 0; i < nf; i++)
+              {
+                bool retval2 = save_mat5_binary_element (os, elts[i][j], "",
+                                                         mark_as_global,
+                                                         false,
+                                                         save_as_floats);
+                if (! retval2)
+                  goto error_cleanup;
+              }
+          }
+      }
+    }
+  else
+    gripe_wrong_type_arg ("save", tc, false);
+
+ skip_to_next:
+  return true;
+
+ error_cleanup:
+  error ("save: error while writing `%s' to MAT file", name.c_str ());
+
+  return false;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/ls-mat5.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,61 @@
+/*
+
+Copyright (C) 2003-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if !defined (octave_ls_mat5_h)
+#define octave_ls_mat5_h 1
+
+enum mat5_data_type
+  {
+    miINT8 = 1,                 // 8 bit signed
+    miUINT8,                    // 8 bit unsigned
+    miINT16,                    // 16 bit signed
+    miUINT16,                   // 16 bit unsigned
+    miINT32,                    // 32 bit signed
+    miUINT32,                   // 32 bit unsigned
+    miSINGLE,                   // IEEE 754 single precision float
+    miRESERVE1,
+    miDOUBLE,                   // IEEE 754 double precision float
+    miRESERVE2,
+    miRESERVE3,
+    miINT64,                    // 64 bit signed
+    miUINT64,                   // 64 bit unsigned
+    miMATRIX,                   // MATLAB array
+    miCOMPRESSED,               // Compressed data
+    miUTF8,                     // Unicode UTF-8 Encoded Character Data
+    miUTF16,                    // Unicode UTF-16 Encoded Character Data
+    miUTF32                     // Unicode UTF-32 Encoded Character Data
+  };
+
+extern int
+read_mat5_binary_file_header (std::istream& is, bool& swap,
+                              bool quiet = false,
+                              const std::string& filename = std::string ());
+extern std::string
+read_mat5_binary_element (std::istream& is, const std::string& filename,
+                          bool swap, bool& global, octave_value& tc);
+extern bool
+save_mat5_binary_element (std::ostream& os,
+                          const octave_value& tc, const std::string& name,
+                          bool mark_as_global, bool mat7_format,
+                          bool save_as_floats, bool compressing = false);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/ls-oct-binary.cc	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,307 @@
+/*
+
+Copyright (C) 1996-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <cfloat>
+#include <cstring>
+#include <cctype>
+
+#include <fstream>
+#include <iomanip>
+#include <iostream>
+#include <string>
+#include <vector>
+
+#include "byte-swap.h"
+#include "data-conv.h"
+#include "file-ops.h"
+#include "glob-match.h"
+#include "lo-mappers.h"
+#include "mach-info.h"
+#include "oct-env.h"
+#include "oct-time.h"
+#include "quit.h"
+#include "str-vec.h"
+#include "oct-locbuf.h"
+
+#include "Cell.h"
+#include "defun.h"
+#include "error.h"
+#include "gripes.h"
+#include "load-save.h"
+#include "oct-obj.h"
+#include "oct-map.h"
+#include "ov-cell.h"
+#include "pager.h"
+#include "pt-exp.h"
+#include "sysdep.h"
+#include "unwind-prot.h"
+#include "utils.h"
+#include "variables.h"
+#include "version.h"
+#include "dMatrix.h"
+
+#include "ls-utils.h"
+#include "ls-oct-binary.h"
+
+// Extract one value (scalar, matrix, string, etc.) from stream IS and
+// place it in TC, returning the name of the variable.  If the value
+// is tagged as global in the file, return TRUE in GLOBAL.  If SWAP
+// is TRUE, swap bytes after reading.
+//
+// The data is expected to be in the following format:
+//
+// Header (one per file):
+// =====================
+//
+//   object               type            bytes
+//   ------               ----            -----
+//   magic number         string             10
+//
+//   float format         integer             1
+//
+//
+// Data (one set for each item):
+// ============================
+//
+//   object               type            bytes
+//   ------               ----            -----
+//   name_length          integer             4
+//
+//   name                 string    name_length
+//
+//   doc_length           integer             4
+//
+//   doc                  string     doc_length
+//
+//   global flag          integer             1
+//
+//   data type            char                1
+//
+// In general "data type" is 255, and in that case the next arguments
+// in the data set are
+//
+//   object               type            bytes
+//   ------               ----            -----
+//   type_length          integer             4
+//
+//   type                 string    type_length
+//
+// The string "type" is then used with octave_value_typeinfo::lookup_type
+// to create an octave_value of the correct type. The specific load/save
+// function is then called.
+//
+// For backward compatiablity "data type" can also be a value between 1
+// and 7, where this defines a hardcoded octave_value of the type
+//
+//   data type                  octave_value
+//   ---------                  ------------
+//   1                          scalar
+//   2                          matrix
+//   3                          complex scalar
+//   4                          complex matrix
+//   5                          string   (old style storage)
+//   6                          range
+//   7                          string
+//
+// Except for "data type" equal 5 that requires special treatment, these
+// old style "data type" value also cause the specific load/save functions
+// to be called. FILENAME is used for error messages.
+
+std::string
+read_binary_data (std::istream& is, bool swap,
+                  oct_mach_info::float_format fmt,
+                  const std::string& filename, bool& global,
+                  octave_value& tc, std::string& doc)
+{
+  std::string retval;
+
+  unsigned char tmp = 0;
+
+  int32_t name_len = 0;
+  int32_t doc_len = 0;
+
+  doc.resize (0);
+
+  // We expect to fail here, at the beginning of a record, so not
+  // being able to read another name should not result in an error.
+
+  is.read (reinterpret_cast<char *> (&name_len), 4);
+  if (! is)
+    return retval;
+  if (swap)
+    swap_bytes<4> (&name_len);
+
+  {
+    OCTAVE_LOCAL_BUFFER (char, name, name_len+1);
+    name[name_len] = '\0';
+    if (! is.read (reinterpret_cast<char *> (name), name_len))
+      goto data_read_error;
+    retval = name;
+  }
+
+  is.read (reinterpret_cast<char *> (&doc_len), 4);
+  if (! is)
+    goto data_read_error;
+  if (swap)
+    swap_bytes<4> (&doc_len);
+
+  {
+    OCTAVE_LOCAL_BUFFER (char, tdoc, doc_len+1);
+    tdoc[doc_len] = '\0';
+    if (! is.read (reinterpret_cast<char *> (tdoc), doc_len))
+      goto data_read_error;
+    doc = tdoc;
+  }
+
+  if (! is.read (reinterpret_cast<char *> (&tmp), 1))
+    goto data_read_error;
+  global = tmp ? 1 : 0;
+
+  tmp = 0;
+  if (! is.read (reinterpret_cast<char *> (&tmp), 1))
+    goto data_read_error;
+
+  // All cases except 255 kept for backwards compatibility
+  switch (tmp)
+    {
+    case 1:
+      tc = octave_value_typeinfo::lookup_type ("scalar");
+      break;
+
+    case 2:
+      tc = octave_value_typeinfo::lookup_type ("matrix");
+      break;
+
+    case 3:
+      tc = octave_value_typeinfo::lookup_type ("complex scalar");
+      break;
+
+    case 4:
+      tc = octave_value_typeinfo::lookup_type ("complex matrix");
+      break;
+
+    case 5:
+      {
+        // FIXMEX
+        // This is cruft, since its for a save type that is old. Maybe
+        // this is taking backward compatability too far!!
+        int32_t len;
+        if (! is.read (reinterpret_cast<char *> (&len), 4))
+          goto data_read_error;
+        if (swap)
+          swap_bytes<4> (&len);
+        OCTAVE_LOCAL_BUFFER (char, s, len+1);
+        if (! is.read (reinterpret_cast<char *> (s), len))
+          goto data_read_error;
+        s[len] = '\0';
+        tc = s;
+
+        // Early return, since don't want rest of this function
+        return retval;
+      }
+      break;
+
+    case 6:
+      tc = octave_value_typeinfo::lookup_type ("range");
+      break;
+
+    case 7:
+      tc = octave_value_typeinfo::lookup_type ("string");
+      break;
+
+    case 255:
+      {
+        // Read the saved variable type
+        int32_t len;
+        if (! is.read (reinterpret_cast<char *> (&len), 4))
+          goto data_read_error;
+        if (swap)
+          swap_bytes<4> (&len);
+        OCTAVE_LOCAL_BUFFER (char, s, len+1);
+        if (! is.read (s, len))
+          goto data_read_error;
+        s[len] = '\0';
+        std::string typ = s;
+        tc = octave_value_typeinfo::lookup_type (typ);
+      }
+      break;
+    default:
+      goto data_read_error;
+      break;
+    }
+
+  if (!tc.load_binary (is, swap, fmt))
+    {
+    data_read_error:
+      error ("load: trouble reading binary file `%s'", filename.c_str ());
+    }
+
+  return retval;
+}
+
+// Save the data from TC along with the corresponding NAME, help
+// string DOC, and global flag MARK_AS_GLOBAL on stream OS in the
+// binary format described above for read_binary_data.
+
+bool
+save_binary_data (std::ostream& os, const octave_value& tc,
+                  const std::string& name, const std::string& doc,
+                  bool mark_as_global, bool save_as_floats)
+{
+  int32_t name_len = name.length ();
+
+  os.write (reinterpret_cast<char *> (&name_len), 4);
+  os << name;
+
+  int32_t doc_len = doc.length ();
+
+  os.write (reinterpret_cast<char *> (&doc_len), 4);
+  os << doc;
+
+  unsigned char tmp;
+
+  tmp = mark_as_global;
+  os.write (reinterpret_cast<char *> (&tmp), 1);
+
+  // 255 flags the new binary format
+  tmp = 255;
+  os.write (reinterpret_cast<char *> (&tmp), 1);
+
+  // Write the string corresponding to the octave_value type
+  std::string typ = tc.type_name ();
+  int32_t len = typ.length ();
+  os.write (reinterpret_cast<char *> (&len), 4);
+  const char *btmp = typ.data ();
+  os.write (btmp, len);
+
+  // The octave_value of tc is const. Make a copy...
+  octave_value val = tc;
+
+  // Call specific save function
+  bool success = val.save_binary (os, save_as_floats);
+
+  return (os && success);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/ls-oct-binary.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,37 @@
+/*
+
+Copyright (C) 2003-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if !defined (octave_ls_oct_binary_h)
+#define octave_ls_oct_binary_h 1
+
+extern OCTINTERP_API bool
+save_binary_data (std::ostream& os, const octave_value& tc,
+                  const std::string& name, const std::string& doc,
+                  bool mark_as_global, bool save_as_floats);
+
+extern OCTINTERP_API std::string
+read_binary_data (std::istream& is, bool swap,
+                  oct_mach_info::float_format fmt,
+                  const std::string& filename, bool& global,
+                  octave_value& tc, std::string& doc);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/ls-utils.cc	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,88 @@
+/*
+
+Copyright (C) 2003-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "data-conv.h"
+
+#include "ls-utils.h"
+
+// MAX_VAL and MIN_VAL are assumed to have integral values even though
+// they are stored in doubles.
+
+save_type
+get_save_type (double /* max_val */, double /* min_val */)
+{
+  save_type st = LS_DOUBLE;
+
+  // Matlab doesn't seem to load the UINT32 type correctly, so let's
+  // avoid it (and the other unsigned types, even though they may not
+  // have the same problem.  And apparently, there are problems with
+  // other smaller types as well.  If we avoid them all, then maybe we
+  // will avoid problems.  Unfortunately, we won't be able to save
+  // space...
+
+  //  if (max_val < 256 && min_val > -1)
+  //    st = LS_U_CHAR;
+  //  else if (max_val < 65536 && min_val > -1)
+  //    st = LS_U_SHORT;
+  //  else if (max_val < 4294967295UL && min_val > -1)
+  //    st = LS_U_INT;
+  //  else if (max_val < 128 && min_val >= -128)
+  //    st = LS_CHAR;
+  //  else if (max_val < 32768 && min_val >= -32768)
+  //    st = LS_SHORT;
+  //  else if (max_val <= 2147483647L && min_val >= -2147483647L)
+  //    st = LS_INT;
+
+  return st;
+}
+
+save_type
+get_save_type (float /* max_val */, float /* min_val */)
+{
+  save_type st = LS_FLOAT;
+
+  // Matlab doesn't seem to load the UINT32 type correctly, so let's
+  // avoid it (and the other unsigned types, even though they may not
+  // have the same problem.  And apparently, there are problems with
+  // other smaller types as well.  If we avoid them all, then maybe we
+  // will avoid problems.  Unfortunately, we won't be able to save
+  // space...
+
+  //  if (max_val < 256 && min_val > -1)
+  //    st = LS_U_CHAR;
+  //  else if (max_val < 65536 && min_val > -1)
+  //    st = LS_U_SHORT;
+  //  else if (max_val < 4294967295UL && min_val > -1)
+  //    st = LS_U_INT;
+  //  else if (max_val < 128 && min_val >= -128)
+  //    st = LS_CHAR;
+  //  else if (max_val < 32768 && min_val >= -32768)
+  //    st = LS_SHORT;
+  //  else if (max_val <= 2147483647L && min_val >= -2147483647L)
+  //    st = LS_INT;
+
+  return st;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/ls-utils.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,32 @@
+/*
+
+Copyright (C) 2003-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if !defined (octave_ls_utils_h)
+#define octave_ls_utils 1
+
+extern save_type
+get_save_type (double max_val, double min_val);
+
+extern save_type
+get_save_type (float max_val, float min_val);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/matherr.c	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,53 @@
+/*
+
+Copyright (C) 1997-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#if defined (EXCEPTION_IN_MATH)
+
+#include "lo-math.h"
+
+int
+matherr (struct exception *x)
+{
+  /* Possibly print our own message someday.  Should probably be
+     user-switchable. */
+
+  switch (x->type)
+    {
+    case DOMAIN:
+    case SING:
+    case OVERFLOW:
+    case UNDERFLOW:
+    case TLOSS:
+    case PLOSS:
+    default:
+      break;
+    }
+
+  /* But don't print the system message. */
+
+  return 1;
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/mex.cc	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,3540 @@
+/*
+
+Copyright (C) 2006-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#include <config.h>
+
+#include <cfloat>
+#include <csetjmp>
+#include <cstdarg>
+#include <cstdlib>
+#include <cstring>
+#include <cctype>
+
+#include <set>
+
+#include "f77-fcn.h"
+#include "lo-ieee.h"
+#include "oct-locbuf.h"
+
+// mxArray must be declared as a class before including mexproto.h.
+class mxArray;
+#include "Cell.h"
+#include "mexproto.h"
+#include "oct-map.h"
+#include "oct-obj.h"
+#include "ov.h"
+#include "ov-mex-fcn.h"
+#include "ov-usr-fcn.h"
+#include "pager.h"
+#include "parse.h"
+#include "toplev.h"
+#include "unwind-prot.h"
+#include "utils.h"
+#include "variables.h"
+#include "graphics.h"
+
+// #define DEBUG 1
+
+static void
+xfree (void *ptr)
+{
+  ::free (ptr);
+}
+
+static mwSize
+max_str_len (mwSize m, const char **str)
+{
+  int max_len = 0;
+
+  for (mwSize i = 0; i < m; i++)
+    {
+      mwSize tmp = strlen (str[i]);
+
+      if (tmp > max_len)
+        max_len = tmp;
+    }
+
+  return max_len;
+}
+
+static int
+valid_key (const char *key)
+{
+  int retval = 0;
+
+  int nel = strlen (key);
+
+  if (nel > 0)
+    {
+      if (isalpha (key[0]))
+        {
+          for (int i = 1; i < nel; i++)
+            {
+              if (! (isalnum (key[i]) || key[i] == '_'))
+                goto done;
+            }
+
+          retval = 1;
+        }
+    }
+
+ done:
+
+  return retval;
+}
+
+// ------------------------------------------------------------------
+
+// A class to provide the default implemenation of some of the virtual
+// functions declared in the mxArray class.
+
+class mxArray_base : public mxArray
+{
+protected:
+
+  mxArray_base (void) : mxArray (xmxArray ()) { }
+
+public:
+
+  mxArray *dup (void) const = 0;
+
+  ~mxArray_base (void) { }
+
+  bool is_octave_value (void) const { return false; }
+
+  int is_cell (void) const = 0;
+
+  int is_char (void) const = 0;
+
+  int is_class (const char *name_arg) const
+  {
+    int retval = 0;
+
+    const char *cname = get_class_name ();
+
+    if (cname && name_arg)
+      retval = ! strcmp (cname, name_arg);
+
+    return retval;
+  }
+
+  int is_complex (void) const = 0;
+
+  int is_double (void) const = 0;
+
+  int is_function_handle (void) const = 0;
+
+  int is_int16 (void) const = 0;
+
+  int is_int32 (void) const = 0;
+
+  int is_int64 (void) const = 0;
+
+  int is_int8 (void) const = 0;
+
+  int is_logical (void) const = 0;
+
+  int is_numeric (void) const = 0;
+
+  int is_single (void) const = 0;
+
+  int is_sparse (void) const = 0;
+
+  int is_struct (void) const = 0;
+
+  int is_uint16 (void) const = 0;
+
+  int is_uint32 (void) const = 0;
+
+  int is_uint64 (void) const = 0;
+
+  int is_uint8 (void) const = 0;
+
+  int is_logical_scalar (void) const
+  {
+    return is_logical () && get_number_of_elements () == 1;
+  }
+
+  int is_logical_scalar_true (void) const = 0;
+
+  mwSize get_m (void) const = 0;
+
+  mwSize get_n (void) const = 0;
+
+  mwSize *get_dimensions (void) const = 0;
+
+  mwSize get_number_of_dimensions (void) const = 0;
+
+  void set_m (mwSize m) = 0;
+
+  void set_n (mwSize n) = 0;
+
+  void set_dimensions (mwSize *dims_arg, mwSize ndims_arg) = 0;
+
+  mwSize get_number_of_elements (void) const = 0;
+
+  int is_empty (void) const = 0;
+
+  mxClassID get_class_id (void) const = 0;
+
+  const char *get_class_name (void) const = 0;
+
+  void set_class_name (const char *name_arg) = 0;
+
+  mxArray *get_cell (mwIndex /*idx*/) const
+  {
+    invalid_type_error ();
+    return 0;
+  }
+
+  void set_cell (mwIndex idx, mxArray *val) = 0;
+
+  double get_scalar (void) const = 0;
+
+  void *get_data (void) const = 0;
+
+  void *get_imag_data (void) const = 0;
+
+  void set_data (void *pr) = 0;
+
+  void set_imag_data (void *pi) = 0;
+
+  mwIndex *get_ir (void) const = 0;
+
+  mwIndex *get_jc (void) const = 0;
+
+  mwSize get_nzmax (void) const = 0;
+
+  void set_ir (mwIndex *ir) = 0;
+
+  void set_jc (mwIndex *jc) = 0;
+
+  void set_nzmax (mwSize nzmax) = 0;
+
+  int add_field (const char *key) = 0;
+
+  void remove_field (int key_num) = 0;
+
+  mxArray *get_field_by_number (mwIndex index, int key_num) const = 0;
+
+  void set_field_by_number (mwIndex index, int key_num, mxArray *val) = 0;
+
+  int get_number_of_fields (void) const = 0;
+
+  const char *get_field_name_by_number (int key_num) const = 0;
+
+  int get_field_number (const char *key) const = 0;
+
+  int get_string (char *buf, mwSize buflen) const = 0;
+
+  char *array_to_string (void) const = 0;
+
+  mwIndex calc_single_subscript (mwSize nsubs, mwIndex *subs) const = 0;
+
+  size_t get_element_size (void) const = 0;
+
+  bool mutation_needed (void) const { return false; }
+
+  mxArray *mutate (void) const { return 0; }
+
+protected:
+
+  octave_value as_octave_value (void) const = 0;
+
+  mxArray_base (const mxArray_base&) : mxArray (xmxArray ()) { }
+
+  void invalid_type_error (void) const
+  {
+    error ("invalid type for operation");
+  }
+
+  void error (const char *msg) const
+  {
+    // FIXME
+    ::error ("%s", msg);
+  }
+};
+
+static mwIndex
+calc_single_subscript_internal (mwSize ndims, const mwSize *dims,
+                                mwSize nsubs, const mwIndex *subs)
+{
+  mwIndex retval = 0;
+
+  switch (nsubs)
+    {
+    case 0:
+      break;
+
+    case 1:
+      retval = subs[0];
+      break;
+
+    default:
+      {
+        // Both nsubs and ndims should be at least 2 here.
+
+        mwSize n = nsubs <= ndims ? nsubs : ndims;
+
+        retval = subs[--n];
+
+        while (--n >= 0)
+          retval = dims[n] * retval + subs[n];
+      }
+      break;
+    }
+
+  return retval;
+}
+
+// The object that handles values pass to MEX files from Octave.  Some
+// methods in this class may set mutate_flag to TRUE to tell the
+// mxArray class to convert to the Matlab-style representation and
+// then invoke the method on that object instead (for example, getting
+// a pointer to real or imaginary data from a complex object requires
+// a mutation but getting a pointer to real data from a real object
+// does not).  Changing the representation causes a copy so we try to
+// avoid it unless it is really necessary.  Once the conversion
+// happens, we delete this representation, so the conversion can only
+// happen once per call to a MEX file.
+
+static inline void *maybe_mark_foreign (void *ptr);
+
+class mxArray_octave_value : public mxArray_base
+{
+public:
+
+  mxArray_octave_value (const octave_value& ov)
+    : mxArray_base (), val (ov), mutate_flag (false),
+      id (mxUNKNOWN_CLASS), class_name (0), ndims (-1), dims (0) { }
+
+  mxArray *dup (void) const
+  {
+    mxArray *retval = val.as_mxArray ();
+
+    if (! retval)
+      retval = new mxArray_octave_value (*this);
+
+    return retval;
+  }
+
+  ~mxArray_octave_value (void)
+  {
+    mxFree (class_name);
+    mxFree (dims);
+  }
+
+  bool is_octave_value (void) const { return true; }
+
+  int is_cell (void) const { return val.is_cell (); }
+
+  int is_char (void) const { return val.is_string (); }
+
+  int is_complex (void) const { return val.is_complex_type (); }
+
+  int is_double (void) const { return val.is_double_type (); }
+
+  int is_function_handle (void) const { return val.is_function_handle (); }
+
+  int is_int16 (void) const { return val.is_int16_type (); }
+
+  int is_int32 (void) const { return val.is_int32_type (); }
+
+  int is_int64 (void) const { return val.is_int64_type (); }
+
+  int is_int8 (void) const { return val.is_int8_type (); }
+
+  int is_logical (void) const { return val.is_bool_type (); }
+
+  int is_numeric (void) const { return val.is_numeric_type (); }
+
+  int is_single (void) const { return val.is_single_type (); }
+
+  int is_sparse (void) const { return val.is_sparse_type (); }
+
+  int is_struct (void) const { return val.is_map (); }
+
+  int is_uint16 (void) const { return val.is_uint16_type (); }
+
+  int is_uint32 (void) const { return val.is_uint32_type (); }
+
+  int is_uint64 (void) const { return val.is_uint64_type (); }
+
+  int is_uint8 (void) const { return val.is_uint8_type (); }
+
+  int is_range (void) const { return val.is_range (); }
+
+  int is_real_type (void) const { return val.is_real_type (); }
+
+  int is_logical_scalar_true (void) const
+  {
+    return (is_logical_scalar () && val.is_true ());
+  }
+
+  mwSize get_m (void) const { return val.rows (); }
+
+  mwSize get_n (void) const
+  {
+    mwSize n = 1;
+
+    // Force dims and ndims to be cached.
+    get_dimensions ();
+
+    for (mwIndex i = ndims - 1; i > 0; i--)
+      n *= dims[i];
+
+    return n;
+  }
+
+  mwSize *get_dimensions (void) const
+  {
+    if (! dims)
+      {
+        ndims = val.ndims ();
+
+        dims = static_cast<mwSize *> (malloc (ndims * sizeof (mwSize)));
+
+        dim_vector dv = val.dims ();
+
+        for (mwIndex i = 0; i < ndims; i++)
+          dims[i] = dv(i);
+      }
+
+    return dims;
+  }
+
+  mwSize get_number_of_dimensions (void) const
+  {
+    // Force dims and ndims to be cached.
+    get_dimensions ();
+
+    return ndims;
+  }
+
+  void set_m (mwSize /*m*/) { request_mutation (); }
+
+  void set_n (mwSize /*n*/) { request_mutation (); }
+
+  void set_dimensions (mwSize */*dims_arg*/, mwSize /*ndims_arg*/)
+  {
+    request_mutation ();
+  }
+
+  mwSize get_number_of_elements (void) const { return val.numel (); }
+
+  int is_empty (void) const { return val.is_empty (); }
+
+  mxClassID get_class_id (void) const
+  {
+    id = mxUNKNOWN_CLASS;
+
+    std::string cn = val.class_name ();
+
+    if (cn == "cell")
+      id = mxCELL_CLASS;
+    else if (cn == "struct")
+      id = mxSTRUCT_CLASS;
+    else if (cn == "logical")
+      id = mxLOGICAL_CLASS;
+    else if (cn == "char")
+      id = mxCHAR_CLASS;
+    else if (cn == "double")
+      id = mxDOUBLE_CLASS;
+    else if (cn == "single")
+      id = mxSINGLE_CLASS;
+    else if (cn == "int8")
+      id = mxINT8_CLASS;
+    else if (cn == "uint8")
+      id = mxUINT8_CLASS;
+    else if (cn == "int16")
+      id = mxINT16_CLASS;
+    else if (cn == "uint16")
+      id = mxUINT16_CLASS;
+    else if (cn == "int32")
+      id = mxINT32_CLASS;
+    else if (cn == "uint32")
+      id = mxUINT32_CLASS;
+    else if (cn == "int64")
+      id = mxINT64_CLASS;
+    else if (cn == "uint64")
+      id = mxUINT64_CLASS;
+    else if (cn == "function_handle")
+      id = mxFUNCTION_CLASS;
+
+    return id;
+  }
+
+  const char *get_class_name (void) const
+  {
+    if (! class_name)
+      {
+        std::string s = val.class_name ();
+        class_name = strsave (s.c_str ());
+      }
+
+    return class_name;
+  }
+
+  // Not allowed.
+  void set_class_name (const char */*name_arg*/) { request_mutation (); }
+
+  mxArray *get_cell (mwIndex /*idx*/) const
+  {
+    request_mutation ();
+    return 0;
+  }
+
+  // Not allowed.
+  void set_cell (mwIndex /*idx*/, mxArray */*val*/) { request_mutation (); }
+
+  double get_scalar (void) const { return val.scalar_value (true); }
+
+  void *get_data (void) const
+  {
+    void *retval = val.mex_get_data ();
+
+    if (retval)
+      maybe_mark_foreign (retval);
+    else
+      request_mutation ();
+
+    return retval;
+  }
+
+  void *get_imag_data (void) const
+  {
+    void *retval = 0;
+
+    if (is_numeric () && is_real_type ())
+      retval = 0;
+    else
+      request_mutation ();
+
+    return retval;
+  }
+
+  // Not allowed.
+  void set_data (void */*pr*/) { request_mutation (); }
+
+  // Not allowed.
+  void set_imag_data (void */*pi*/) { request_mutation (); }
+
+  mwIndex *get_ir (void) const
+  {
+    return static_cast<mwIndex *> (maybe_mark_foreign (val.mex_get_ir ()));
+  }
+
+  mwIndex *get_jc (void) const
+  {
+    return static_cast<mwIndex *> (maybe_mark_foreign (val.mex_get_jc ()));
+  }
+
+  mwSize get_nzmax (void) const { return val.nzmax (); }
+
+  // Not allowed.
+  void set_ir (mwIndex */*ir*/) { request_mutation (); }
+
+  // Not allowed.
+  void set_jc (mwIndex */*jc*/) { request_mutation (); }
+
+  // Not allowed.
+  void set_nzmax (mwSize /*nzmax*/) { request_mutation (); }
+
+  // Not allowed.
+  int add_field (const char */*key*/)
+  {
+    request_mutation ();
+    return 0;
+  }
+
+  // Not allowed.
+  void remove_field (int /*key_num*/) { request_mutation (); }
+
+  mxArray *get_field_by_number (mwIndex /*index*/, int /*key_num*/) const
+  {
+    request_mutation ();
+    return 0;
+  }
+
+  // Not allowed.
+  void set_field_by_number (mwIndex /*index*/, int /*key_num*/, mxArray */*val*/)
+  {
+    request_mutation ();
+  }
+
+  int get_number_of_fields (void) const { return val.nfields (); }
+
+  const char *get_field_name_by_number (int /*key_num*/) const
+  {
+    request_mutation ();
+    return 0;
+  }
+
+  int get_field_number (const char */*key*/) const
+  {
+    request_mutation ();
+    return 0;
+  }
+
+  int get_string (char *buf, mwSize buflen) const
+  {
+    int retval = 1;
+
+    mwSize nel = get_number_of_elements ();
+
+    if (val.is_string () && nel < buflen)
+      {
+        charNDArray tmp = val.char_array_value ();
+
+        const char *p = tmp.data ();
+
+        for (mwIndex i = 0; i < nel; i++)
+          buf[i] = p[i];
+
+        buf[nel] = 0;
+
+        retval = 0;
+      }
+
+    return retval;
+  }
+
+  char *array_to_string (void) const
+  {
+    // FIXME -- this is suposed to handle multi-byte character
+    // strings.
+
+    char *buf = 0;
+
+    if (val.is_string ())
+      {
+        mwSize nel = get_number_of_elements ();
+
+        buf = static_cast<char *> (malloc (nel + 1));
+
+        if (buf)
+          {
+            charNDArray tmp = val.char_array_value ();
+
+            const char *p = tmp.data ();
+
+            for (mwIndex i = 0; i < nel; i++)
+              buf[i] = p[i];
+
+            buf[nel] = '\0';
+          }
+      }
+
+    return buf;
+  }
+
+  mwIndex calc_single_subscript (mwSize nsubs, mwIndex *subs) const
+  {
+    // Force ndims, dims to be cached.
+    get_dimensions ();
+
+    return calc_single_subscript_internal (ndims, dims, nsubs, subs);
+  }
+
+  size_t get_element_size (void) const
+  {
+    // Force id to be cached.
+    get_class_id ();
+
+    switch (id)
+      {
+      case mxCELL_CLASS: return sizeof (mxArray *);
+      case mxSTRUCT_CLASS: return sizeof (mxArray *);
+      case mxLOGICAL_CLASS: return sizeof (mxLogical);
+      case mxCHAR_CLASS: return sizeof (mxChar);
+      case mxDOUBLE_CLASS: return sizeof (double);
+      case mxSINGLE_CLASS: return sizeof (float);
+      case mxINT8_CLASS: return 1;
+      case mxUINT8_CLASS: return 1;
+      case mxINT16_CLASS: return 2;
+      case mxUINT16_CLASS: return 2;
+      case mxINT32_CLASS: return 4;
+      case mxUINT32_CLASS: return 4;
+      case mxINT64_CLASS: return 8;
+      case mxUINT64_CLASS: return 8;
+      case mxFUNCTION_CLASS: return 0;
+      default: return 0;
+      }
+  }
+
+  bool mutation_needed (void) const { return mutate_flag; }
+
+  void request_mutation (void) const
+  {
+    if (mutate_flag)
+      panic_impossible ();
+
+    mutate_flag = true;
+  }
+
+  mxArray *mutate (void) const { return val.as_mxArray (); }
+
+protected:
+
+  octave_value as_octave_value (void) const { return val; }
+
+  mxArray_octave_value (const mxArray_octave_value& arg)
+    : mxArray_base (arg), val (arg.val), mutate_flag (arg.mutate_flag),
+      id (arg.id), class_name (strsave (arg.class_name)), ndims (arg.ndims),
+      dims (ndims > 0 ? static_cast<mwSize *> (malloc (ndims * sizeof (mwSize))) : 0)
+  {
+    if (dims)
+      {
+        for (mwIndex i = 0; i < ndims; i++)
+          dims[i] = arg.dims[i];
+      }
+  }
+
+private:
+
+  octave_value val;
+
+  mutable bool mutate_flag;
+
+  // Caching these does not cost much or lead to much duplicated
+  // code.  For other things, we just request mutation to a
+  // Matlab-style mxArray object.
+
+  mutable mxClassID id;
+  mutable char *class_name;
+  mutable mwSize ndims;
+  mutable mwSize *dims;
+
+  // No assignment!  FIXME -- should this be implemented?  Note that we
+  // do have a copy constructor.
+
+  mxArray_octave_value& operator = (const mxArray_octave_value&);
+};
+
+// The base class for the Matlab-style representation, used to handle
+// things that are common to all Matlab-style objects.
+
+class mxArray_matlab : public mxArray_base
+{
+protected:
+
+  mxArray_matlab (mxClassID id_arg = mxUNKNOWN_CLASS)
+    : mxArray_base (), class_name (0), id (id_arg), ndims (0), dims (0) { }
+
+  mxArray_matlab (mxClassID id_arg, mwSize ndims_arg, const mwSize *dims_arg)
+    : mxArray_base (), class_name (0), id (id_arg),
+      ndims (ndims_arg < 2 ? 2 : ndims_arg),
+      dims (static_cast<mwSize *> (malloc (ndims * sizeof (mwSize))))
+  {
+    if (ndims_arg < 2)
+      {
+        dims[0] = 1;
+        dims[1] = 1;
+      }
+
+    for (mwIndex i = 0; i < ndims_arg; i++)
+      dims[i] = dims_arg[i];
+
+    for (mwIndex i = ndims - 1; i > 1; i--)
+      {
+        if (dims[i] == 1)
+          ndims--;
+        else
+          break;
+      }
+  }
+
+  mxArray_matlab (mxClassID id_arg, const dim_vector& dv)
+    : mxArray_base (), class_name (0), id (id_arg),
+      ndims (dv.length ()),
+      dims (static_cast<mwSize *> (malloc (ndims * sizeof (mwSize))))
+  {
+    for (mwIndex i = 0; i < ndims; i++)
+      dims[i] = dv(i);
+
+    for (mwIndex i = ndims - 1; i > 1; i--)
+      {
+        if (dims[i] == 1)
+          ndims--;
+        else
+          break;
+      }
+  }
+
+  mxArray_matlab (mxClassID id_arg, mwSize m, mwSize n)
+    : mxArray_base (), class_name (0), id (id_arg), ndims (2),
+      dims (static_cast<mwSize *> (malloc (ndims * sizeof (mwSize))))
+  {
+    dims[0] = m;
+    dims[1] = n;
+  }
+
+public:
+
+  ~mxArray_matlab (void)
+  {
+    mxFree (class_name);
+    mxFree (dims);
+  }
+
+  int is_cell (void) const { return id == mxCELL_CLASS; }
+
+  int is_char (void) const { return id == mxCHAR_CLASS; }
+
+  int is_complex (void) const { return 0; }
+
+  int is_double (void) const { return id == mxDOUBLE_CLASS; }
+
+  int is_function_handle (void) const { return id == mxFUNCTION_CLASS; }
+
+  int is_int16 (void) const { return id == mxINT16_CLASS; }
+
+  int is_int32 (void) const { return id == mxINT32_CLASS; }
+
+  int is_int64 (void) const { return id == mxINT64_CLASS; }
+
+  int is_int8 (void) const { return id == mxINT8_CLASS; }
+
+  int is_logical (void) const { return id == mxLOGICAL_CLASS; }
+
+  int is_numeric (void) const
+  {
+    return (id == mxDOUBLE_CLASS || id == mxSINGLE_CLASS
+            || id == mxINT8_CLASS || id == mxUINT8_CLASS
+            || id == mxINT16_CLASS || id == mxUINT16_CLASS
+            || id == mxINT32_CLASS || id == mxUINT32_CLASS
+            || id == mxINT64_CLASS || id == mxUINT64_CLASS);
+  }
+
+  int is_single (void) const { return id == mxSINGLE_CLASS; }
+
+  int is_sparse (void) const { return 0; }
+
+  int is_struct (void) const { return id == mxSTRUCT_CLASS; }
+
+  int is_uint16 (void) const { return id == mxUINT16_CLASS; }
+
+  int is_uint32 (void) const { return id == mxUINT32_CLASS; }
+
+  int is_uint64 (void) const { return id == mxUINT64_CLASS; }
+
+  int is_uint8 (void) const { return id == mxUINT8_CLASS; }
+
+  int is_logical_scalar_true (void) const
+  {
+    return (is_logical_scalar ()
+            && static_cast<mxLogical *> (get_data ())[0] != 0);
+  }
+
+  mwSize get_m (void) const { return dims[0]; }
+
+  mwSize get_n (void) const
+  {
+    mwSize n = 1;
+
+    for (mwSize i = ndims - 1 ; i > 0 ; i--)
+      n *= dims[i];
+
+    return n;
+  }
+
+  mwSize *get_dimensions (void) const { return dims; }
+
+  mwSize get_number_of_dimensions (void) const { return ndims; }
+
+  void set_m (mwSize m) { dims[0] = m; }
+
+  void set_n (mwSize n) { dims[1] = n; }
+
+  void set_dimensions (mwSize *dims_arg, mwSize ndims_arg)
+  {
+    dims = dims_arg;
+    ndims = ndims_arg;
+  }
+
+  mwSize get_number_of_elements (void) const
+  {
+    mwSize retval = dims[0];
+
+    for (mwIndex i = 1; i < ndims; i++)
+      retval *= dims[i];
+
+    return retval;
+  }
+
+  int is_empty (void) const { return get_number_of_elements () == 0; }
+
+  mxClassID get_class_id (void) const { return id; }
+
+  const char *get_class_name (void) const
+  {
+    switch (id)
+      {
+      case mxCELL_CLASS: return "cell";
+      case mxSTRUCT_CLASS: return "struct";
+      case mxLOGICAL_CLASS: return "logical";
+      case mxCHAR_CLASS: return "char";
+      case mxDOUBLE_CLASS: return "double";
+      case mxSINGLE_CLASS: return "single";
+      case mxINT8_CLASS: return "int8";
+      case mxUINT8_CLASS: return "uint8";
+      case mxINT16_CLASS: return "int16";
+      case mxUINT16_CLASS: return "uint16";
+      case mxINT32_CLASS: return "int32";
+      case mxUINT32_CLASS: return "uint32";
+      case mxINT64_CLASS: return "int64";
+      case mxUINT64_CLASS: return "uint64";
+      case mxFUNCTION_CLASS: return "function_handle";
+      default: return "unknown";
+      }
+  }
+
+  void set_class_name (const char *name_arg)
+  {
+    mxFree (class_name);
+    class_name = static_cast<char *> (malloc (strlen (name_arg) + 1));
+    strcpy (class_name, name_arg);
+  }
+
+  mxArray *get_cell (mwIndex /*idx*/) const
+  {
+    invalid_type_error ();
+    return 0;
+  }
+
+  void set_cell (mwIndex /*idx*/, mxArray */*val*/)
+  {
+    invalid_type_error ();
+  }
+
+  double get_scalar (void) const
+  {
+    invalid_type_error ();
+    return 0;
+  }
+
+  void *get_data (void) const
+  {
+    invalid_type_error ();
+    return 0;
+  }
+
+  void *get_imag_data (void) const
+  {
+    invalid_type_error ();
+    return 0;
+  }
+
+  void set_data (void */*pr*/)
+  {
+    invalid_type_error ();
+  }
+
+  void set_imag_data (void */*pi*/)
+  {
+    invalid_type_error ();
+  }
+
+  mwIndex *get_ir (void) const
+  {
+    invalid_type_error ();
+    return 0;
+  }
+
+  mwIndex *get_jc (void) const
+  {
+    invalid_type_error ();
+    return 0;
+  }
+
+  mwSize get_nzmax (void) const
+  {
+    invalid_type_error ();
+    return 0;
+  }
+
+  void set_ir (mwIndex */*ir*/)
+  {
+    invalid_type_error ();
+  }
+
+  void set_jc (mwIndex */*jc*/)
+  {
+    invalid_type_error ();
+  }
+
+  void set_nzmax (mwSize /*nzmax*/)
+  {
+    invalid_type_error ();
+  }
+
+  int add_field (const char */*key*/)
+  {
+    invalid_type_error ();
+    return -1;
+  }
+
+  void remove_field (int /*key_num*/)
+  {
+    invalid_type_error ();
+  }
+
+  mxArray *get_field_by_number (mwIndex /*index*/, int /*key_num*/) const
+  {
+    invalid_type_error ();
+    return 0;
+  }
+
+  void set_field_by_number (mwIndex /*index*/, int /*key_num*/, mxArray */*val*/)
+  {
+    invalid_type_error ();
+  }
+
+  int get_number_of_fields (void) const
+  {
+    invalid_type_error ();
+    return 0;
+  }
+
+  const char *get_field_name_by_number (int /*key_num*/) const
+  {
+    invalid_type_error ();
+    return 0;
+  }
+
+  int get_field_number (const char */*key*/) const
+  {
+    return -1;
+  }
+
+  int get_string (char */*buf*/, mwSize /*buflen*/) const
+  {
+    invalid_type_error ();
+    return 0;
+  }
+
+  char *array_to_string (void) const
+  {
+    invalid_type_error ();
+    return 0;
+  }
+
+  mwIndex calc_single_subscript (mwSize nsubs, mwIndex *subs) const
+  {
+    return calc_single_subscript_internal (ndims, dims, nsubs, subs);
+  }
+
+  size_t get_element_size (void) const
+  {
+    switch (id)
+      {
+      case mxCELL_CLASS: return sizeof (mxArray *);
+      case mxSTRUCT_CLASS: return sizeof (mxArray *);
+      case mxLOGICAL_CLASS: return sizeof (mxLogical);
+      case mxCHAR_CLASS: return sizeof (mxChar);
+      case mxDOUBLE_CLASS: return sizeof (double);
+      case mxSINGLE_CLASS: return sizeof (float);
+      case mxINT8_CLASS: return 1;
+      case mxUINT8_CLASS: return 1;
+      case mxINT16_CLASS: return 2;
+      case mxUINT16_CLASS: return 2;
+      case mxINT32_CLASS: return 4;
+      case mxUINT32_CLASS: return 4;
+      case mxINT64_CLASS: return 8;
+      case mxUINT64_CLASS: return 8;
+      case mxFUNCTION_CLASS: return 0;
+      default: return 0;
+      }
+  }
+
+protected:
+
+  mxArray_matlab (const mxArray_matlab& val)
+    : mxArray_base (val), class_name (strsave (val.class_name)),
+      id (val.id), ndims (val.ndims),
+      dims (static_cast<mwSize *> (malloc (ndims * sizeof (mwSize))))
+  {
+    for (mwIndex i = 0; i < ndims; i++)
+      dims[i] = val.dims[i];
+  }
+
+  dim_vector
+  dims_to_dim_vector (void) const
+  {
+    mwSize nd = get_number_of_dimensions ();
+
+    mwSize *d = get_dimensions ();
+
+    dim_vector dv;
+    dv.resize (nd);
+
+    for (mwIndex i = 0; i < nd; i++)
+      dv(i) = d[i];
+
+    return dv;
+  }
+
+private:
+
+  char *class_name;
+
+  mxClassID id;
+
+  mwSize ndims;
+  mwSize *dims;
+
+  void invalid_type_error (void) const
+  {
+    error ("invalid type for operation");
+  }
+
+  // No assignment!  FIXME -- should this be implemented?  Note that we
+  // do have a copy constructor.
+
+  mxArray_matlab& operator = (const mxArray_matlab&);
+};
+
+// Matlab-style numeric, character, and logical data.
+
+class mxArray_number : public mxArray_matlab
+{
+public:
+
+  mxArray_number (mxClassID id_arg, mwSize ndims_arg, const mwSize *dims_arg,
+                  mxComplexity flag = mxREAL)
+    : mxArray_matlab (id_arg, ndims_arg, dims_arg),
+      pr (calloc (get_number_of_elements (), get_element_size ())),
+      pi (flag == mxCOMPLEX ? calloc (get_number_of_elements (), get_element_size ()) : 0) { }
+
+  mxArray_number (mxClassID id_arg, const dim_vector& dv,
+                  mxComplexity flag = mxREAL)
+    : mxArray_matlab (id_arg, dv),
+      pr (calloc (get_number_of_elements (), get_element_size ())),
+      pi (flag == mxCOMPLEX ? calloc (get_number_of_elements (), get_element_size ()) : 0) { }
+
+  mxArray_number (mxClassID id_arg, mwSize m, mwSize n, mxComplexity flag = mxREAL)
+    : mxArray_matlab (id_arg, m, n),
+      pr (calloc (get_number_of_elements (), get_element_size ())),
+      pi (flag == mxCOMPLEX ? calloc (get_number_of_elements (), get_element_size ()) : 0) { }
+
+  mxArray_number (mxClassID id_arg, double val)
+    : mxArray_matlab (id_arg, 1, 1),
+      pr (calloc (get_number_of_elements (), get_element_size ())),
+      pi (0)
+  {
+    double *dpr = static_cast<double *> (pr);
+    dpr[0] = val;
+  }
+
+  mxArray_number (mxClassID id_arg, mxLogical val)
+    : mxArray_matlab (id_arg, 1, 1),
+      pr (calloc (get_number_of_elements (), get_element_size ())),
+      pi (0)
+  {
+    mxLogical *lpr = static_cast<mxLogical *> (pr);
+    lpr[0] = val;
+  }
+
+  mxArray_number (const char *str)
+    : mxArray_matlab (mxCHAR_CLASS,
+                      str ? (strlen (str) ? 1 : 0) : 0,
+                      str ? strlen (str) : 0),
+      pr (calloc (get_number_of_elements (), get_element_size ())),
+      pi (0)
+  {
+    mxChar *cpr = static_cast<mxChar *> (pr);
+    mwSize nel = get_number_of_elements ();
+    for (mwIndex i = 0; i < nel; i++)
+      cpr[i] = str[i];
+  }
+
+  // FIXME??
+  mxArray_number (mwSize m, const char **str)
+    : mxArray_matlab (mxCHAR_CLASS, m, max_str_len (m, str)),
+      pr (calloc (get_number_of_elements (), get_element_size ())),
+      pi (0)
+  {
+    mxChar *cpr = static_cast<mxChar *> (pr);
+
+    mwSize *dv = get_dimensions ();
+
+    mwSize nc = dv[1];
+
+    for (mwIndex j = 0; j < m; j++)
+      {
+        const char *ptr = str[j];
+
+        size_t tmp_len = strlen (ptr);
+
+        for (size_t i = 0; i < tmp_len; i++)
+          cpr[m*i+j] = static_cast<mxChar> (ptr[i]);
+
+        for (size_t i = tmp_len; i < static_cast<size_t>(nc); i++)
+          cpr[m*i+j] = static_cast<mxChar> (' ');
+      }
+  }
+
+  mxArray_number *dup (void) const { return new mxArray_number (*this); }
+
+  ~mxArray_number (void)
+  {
+    mxFree (pr);
+    mxFree (pi);
+  }
+
+  int is_complex (void) const { return pi != 0; }
+
+  double get_scalar (void) const
+  {
+    double retval = 0;
+
+    switch (get_class_id ())
+      {
+      case mxLOGICAL_CLASS:
+        retval = *(static_cast<bool *> (pr));
+        break;
+
+      case mxCHAR_CLASS:
+        retval = *(static_cast<mxChar *> (pr));
+        break;
+
+      case mxSINGLE_CLASS:
+        retval = *(static_cast<float *> (pr));
+        break;
+
+      case mxDOUBLE_CLASS:
+        retval = *(static_cast<double *> (pr));
+        break;
+
+      case mxINT8_CLASS:
+        retval = *(static_cast<int8_t *> (pr));
+        break;
+
+      case mxUINT8_CLASS:
+        retval = *(static_cast<uint8_t *> (pr));
+        break;
+
+      case mxINT16_CLASS:
+        retval = *(static_cast<int16_t *> (pr));
+        break;
+
+      case mxUINT16_CLASS:
+        retval = *(static_cast<uint16_t *> (pr));
+        break;
+
+      case mxINT32_CLASS:
+        retval = *(static_cast<int32_t *> (pr));
+        break;
+
+      case mxUINT32_CLASS:
+        retval = *(static_cast<uint32_t *> (pr));
+        break;
+
+      case mxINT64_CLASS:
+        retval = *(static_cast<int64_t *> (pr));
+        break;
+
+      case mxUINT64_CLASS:
+        retval = *(static_cast<uint64_t *> (pr));
+        break;
+
+      default:
+        panic_impossible ();
+      }
+
+    return retval;
+  }
+
+  void *get_data (void) const { return pr; }
+
+  void *get_imag_data (void) const { return pi; }
+
+  void set_data (void *pr_arg) { pr = pr_arg; }
+
+  void set_imag_data (void *pi_arg) { pi = pi_arg; }
+
+  int get_string (char *buf, mwSize buflen) const
+  {
+    int retval = 0;
+
+    mwSize nel = get_number_of_elements ();
+
+    if (! (nel < buflen))
+      {
+        retval = 1;
+        if (buflen > 0)
+          nel = buflen-1;
+      }
+
+    if (nel < buflen)
+      {
+        mxChar *ptr = static_cast<mxChar *> (pr);
+
+        for (mwIndex i = 0; i < nel; i++)
+          buf[i] = static_cast<char> (ptr[i]);
+
+        buf[nel] = 0;
+      }
+
+    return retval;
+  }
+
+  char *array_to_string (void) const
+  {
+    // FIXME -- this is suposed to handle multi-byte character
+    // strings.
+
+    mwSize nel = get_number_of_elements ();
+
+    char *buf = static_cast<char *> (malloc (nel + 1));
+
+    if (buf)
+      {
+        mxChar *ptr = static_cast<mxChar *> (pr);
+
+        for (mwIndex i = 0; i < nel; i++)
+          buf[i] = static_cast<char> (ptr[i]);
+
+        buf[nel] = '\0';
+      }
+
+    return buf;
+  }
+
+protected:
+
+  template <typename ELT_T, typename ARRAY_T, typename ARRAY_ELT_T>
+  octave_value
+  int_to_ov (const dim_vector& dv) const
+  {
+    octave_value retval;
+
+    mwSize nel = get_number_of_elements ();
+
+    ELT_T *ppr = static_cast<ELT_T *> (pr);
+
+    if (pi)
+      error ("complex integer types are not supported");
+    else
+      {
+        ARRAY_T val (dv);
+
+        ARRAY_ELT_T *ptr = val.fortran_vec ();
+
+        for (mwIndex i = 0; i < nel; i++)
+          ptr[i] = ppr[i];
+
+        retval = val;
+      }
+
+    return retval;
+  }
+
+  octave_value as_octave_value (void) const
+  {
+    octave_value retval;
+
+    dim_vector dv = dims_to_dim_vector ();
+
+    switch (get_class_id ())
+      {
+      case mxLOGICAL_CLASS:
+        retval = int_to_ov<bool, boolNDArray, bool> (dv);
+        break;
+
+      case mxCHAR_CLASS:
+        {
+          mwSize nel = get_number_of_elements ();
+
+          mxChar *ppr = static_cast<mxChar *> (pr);
+
+          charNDArray val (dv);
+
+          char *ptr = val.fortran_vec ();
+
+          for (mwIndex i = 0; i < nel; i++)
+            ptr[i] = static_cast<char> (ppr[i]);
+
+          retval = val;
+        }
+        break;
+
+      case mxSINGLE_CLASS:
+        {
+          mwSize nel = get_number_of_elements ();
+
+          float *ppr = static_cast<float *> (pr);
+
+          if (pi)
+            {
+              FloatComplexNDArray val (dv);
+
+              FloatComplex *ptr = val.fortran_vec ();
+
+              float *ppi = static_cast<float *> (pi);
+
+              for (mwIndex i = 0; i < nel; i++)
+                ptr[i] = FloatComplex (ppr[i], ppi[i]);
+
+              retval = val;
+            }
+          else
+            {
+              FloatNDArray val (dv);
+
+              float *ptr = val.fortran_vec ();
+
+              for (mwIndex i = 0; i < nel; i++)
+                ptr[i] = ppr[i];
+
+              retval = val;
+            }
+        }
+        break;
+
+      case mxDOUBLE_CLASS:
+        {
+          mwSize nel = get_number_of_elements ();
+
+          double *ppr = static_cast<double *> (pr);
+
+          if (pi)
+            {
+              ComplexNDArray val (dv);
+
+              Complex *ptr = val.fortran_vec ();
+
+              double *ppi = static_cast<double *> (pi);
+
+              for (mwIndex i = 0; i < nel; i++)
+                ptr[i] = Complex (ppr[i], ppi[i]);
+
+              retval = val;
+            }
+          else
+            {
+              NDArray val (dv);
+
+              double *ptr = val.fortran_vec ();
+
+              for (mwIndex i = 0; i < nel; i++)
+                ptr[i] = ppr[i];
+
+              retval = val;
+            }
+        }
+        break;
+
+      case mxINT8_CLASS:
+        retval = int_to_ov<int8_t, int8NDArray, octave_int8> (dv);
+        break;
+
+      case mxUINT8_CLASS:
+        retval = int_to_ov<uint8_t, uint8NDArray, octave_uint8> (dv);
+        break;
+
+      case mxINT16_CLASS:
+        retval = int_to_ov<int16_t, int16NDArray, octave_int16> (dv);
+        break;
+
+      case mxUINT16_CLASS:
+        retval = int_to_ov<uint16_t, uint16NDArray, octave_uint16> (dv);
+        break;
+
+      case mxINT32_CLASS:
+        retval = int_to_ov<int32_t, int32NDArray, octave_int32> (dv);
+        break;
+
+      case mxUINT32_CLASS:
+        retval = int_to_ov<uint32_t, uint32NDArray, octave_uint32> (dv);
+        break;
+
+      case mxINT64_CLASS:
+        retval = int_to_ov<int64_t, int64NDArray, octave_int64> (dv);
+        break;
+
+      case mxUINT64_CLASS:
+        retval = int_to_ov<uint64_t, uint64NDArray, octave_uint64> (dv);
+        break;
+
+      default:
+        panic_impossible ();
+      }
+
+    return retval;
+  }
+
+  mxArray_number (const mxArray_number& val)
+    : mxArray_matlab (val),
+      pr (malloc (get_number_of_elements () * get_element_size ())),
+      pi (val.pi ? malloc (get_number_of_elements () * get_element_size ()) : 0)
+  {
+    size_t nbytes = get_number_of_elements () * get_element_size ();
+
+    if (pr)
+      memcpy (pr, val.pr, nbytes);
+
+    if (pi)
+      memcpy (pi, val.pi, nbytes);
+  }
+
+private:
+
+  void *pr;
+  void *pi;
+
+  // No assignment!  FIXME -- should this be implemented?  Note that we
+  // do have a copy constructor.
+
+  mxArray_number& operator = (const mxArray_number&);
+};
+
+// Matlab-style sparse arrays.
+
+class mxArray_sparse : public mxArray_matlab
+{
+public:
+
+  mxArray_sparse (mxClassID id_arg, mwSize m, mwSize n, mwSize nzmax_arg,
+                  mxComplexity flag = mxREAL)
+    : mxArray_matlab (id_arg, m, n), nzmax (nzmax_arg),
+      pr (calloc (nzmax, get_element_size ())),
+      pi (flag == mxCOMPLEX ? calloc (nzmax, get_element_size ()) : 0),
+      ir (static_cast<mwIndex *> (calloc (nzmax, sizeof (mwIndex)))),
+      jc (static_cast<mwIndex *> (calloc (n + 1, sizeof (mwIndex))))
+    { }
+
+  mxArray_sparse *dup (void) const { return new mxArray_sparse (*this); }
+
+  ~mxArray_sparse (void)
+  {
+    mxFree (pr);
+    mxFree (pi);
+    mxFree (ir);
+    mxFree (jc);
+  }
+
+  int is_complex (void) const { return pi != 0; }
+
+  int is_sparse (void) const { return 1; }
+
+  void *get_data (void) const { return pr; }
+
+  void *get_imag_data (void) const { return pi; }
+
+  void set_data (void *pr_arg) { pr = pr_arg; }
+
+  void set_imag_data (void *pi_arg) { pi = pi_arg; }
+
+  mwIndex *get_ir (void) const { return ir; }
+
+  mwIndex *get_jc (void) const { return jc; }
+
+  mwSize get_nzmax (void) const { return nzmax; }
+
+  void set_ir (mwIndex *ir_arg) { ir = ir_arg; }
+
+  void set_jc (mwIndex *jc_arg) { jc = jc_arg; }
+
+  void set_nzmax (mwSize nzmax_arg) { nzmax = nzmax_arg; }
+
+protected:
+
+  octave_value as_octave_value (void) const
+  {
+    octave_value retval;
+
+    dim_vector dv = dims_to_dim_vector ();
+
+    switch (get_class_id ())
+      {
+      case mxLOGICAL_CLASS:
+        {
+          bool *ppr = static_cast<bool *> (pr);
+
+          SparseBoolMatrix val (get_m (), get_n (),
+                                static_cast<octave_idx_type> (nzmax));
+
+          for (mwIndex i = 0; i < nzmax; i++)
+            {
+              val.xdata (i) = ppr[i];
+              val.xridx (i) = ir[i];
+            }
+
+          for (mwIndex i = 0; i < get_n () + 1; i++)
+            val.xcidx (i) = jc[i];
+
+          retval = val;
+        }
+        break;
+
+      case mxSINGLE_CLASS:
+        error ("single precision sparse data type not supported");
+        break;
+
+      case mxDOUBLE_CLASS:
+        {
+          if (pi)
+            {
+              double *ppr = static_cast<double *> (pr);
+              double *ppi = static_cast<double *> (pi);
+
+              SparseComplexMatrix val (get_m (), get_n (),
+                                       static_cast<octave_idx_type> (nzmax));
+
+              for (mwIndex i = 0; i < nzmax; i++)
+                {
+                  val.xdata (i) = Complex (ppr[i], ppi[i]);
+                  val.xridx (i) = ir[i];
+                }
+
+              for (mwIndex i = 0; i < get_n () + 1; i++)
+                val.xcidx (i) = jc[i];
+
+              retval = val;
+            }
+          else
+            {
+              double *ppr = static_cast<double *> (pr);
+
+              SparseMatrix val (get_m (), get_n (),
+                                static_cast<octave_idx_type> (nzmax));
+
+              for (mwIndex i = 0; i < nzmax; i++)
+                {
+                  val.xdata (i) = ppr[i];
+                  val.xridx (i) = ir[i];
+                }
+
+              for (mwIndex i = 0; i < get_n () + 1; i++)
+                val.xcidx (i) = jc[i];
+
+              retval = val;
+            }
+        }
+        break;
+
+      default:
+        panic_impossible ();
+      }
+
+    return retval;
+  }
+
+private:
+
+  mwSize nzmax;
+
+  void *pr;
+  void *pi;
+  mwIndex *ir;
+  mwIndex *jc;
+
+  mxArray_sparse (const mxArray_sparse& val)
+    : mxArray_matlab (val), nzmax (val.nzmax),
+      pr (malloc (nzmax * get_element_size ())),
+      pi (val.pi ? malloc (nzmax * get_element_size ()) : 0),
+      ir (static_cast<mwIndex *> (malloc (nzmax * sizeof (mwIndex)))),
+      jc (static_cast<mwIndex *> (malloc (nzmax * sizeof (mwIndex))))
+  {
+    size_t nbytes = nzmax * get_element_size ();
+
+    if (pr)
+      memcpy (pr, val.pr, nbytes);
+
+    if (pi)
+      memcpy (pi, val.pi, nbytes);
+
+    if (ir)
+      memcpy (ir, val.ir, nzmax * sizeof (mwIndex));
+
+    if (jc)
+      memcpy (jc, val.jc, (val.get_n () + 1) * sizeof (mwIndex));
+  }
+
+  // No assignment!  FIXME -- should this be implemented?  Note that we
+  // do have a copy constructor.
+
+  mxArray_sparse& operator = (const mxArray_sparse&);
+};
+
+// Matlab-style struct arrays.
+
+class mxArray_struct : public mxArray_matlab
+{
+public:
+
+  mxArray_struct (mwSize ndims_arg, const mwSize *dims_arg, int num_keys_arg,
+                  const char **keys)
+    : mxArray_matlab (mxSTRUCT_CLASS, ndims_arg, dims_arg), nfields (num_keys_arg),
+      fields (static_cast<char **> (calloc (nfields, sizeof (char *)))),
+      data (static_cast<mxArray **> (calloc (nfields * get_number_of_elements (), sizeof (mxArray *))))
+  {
+    init (keys);
+  }
+
+  mxArray_struct (const dim_vector& dv, int num_keys_arg, const char **keys)
+    : mxArray_matlab (mxSTRUCT_CLASS, dv), nfields (num_keys_arg),
+      fields (static_cast<char **> (calloc (nfields, sizeof (char *)))),
+      data (static_cast<mxArray **> (calloc (nfields * get_number_of_elements (), sizeof (mxArray *))))
+  {
+    init (keys);
+  }
+
+  mxArray_struct (mwSize m, mwSize n, int num_keys_arg, const char **keys)
+    : mxArray_matlab (mxSTRUCT_CLASS, m, n), nfields (num_keys_arg),
+      fields (static_cast<char **> (calloc (nfields, sizeof (char *)))),
+      data (static_cast<mxArray **> (calloc (nfields * get_number_of_elements (), sizeof (mxArray *))))
+  {
+    init (keys);
+  }
+
+  void init (const char **keys)
+  {
+    for (int i = 0; i < nfields; i++)
+      fields[i] = strsave (keys[i]);
+  }
+
+  mxArray_struct *dup (void) const { return new mxArray_struct (*this); }
+
+  ~mxArray_struct (void)
+  {
+    for (int i = 0; i < nfields; i++)
+      mxFree (fields[i]);
+
+    mxFree (fields);
+
+    mwSize ntot = nfields * get_number_of_elements ();
+
+    for  (mwIndex i = 0; i < ntot; i++)
+      delete data[i];
+
+    mxFree (data);
+  }
+
+  int add_field (const char *key)
+  {
+    int retval = -1;
+
+    if (valid_key (key))
+      {
+        nfields++;
+
+        fields = static_cast<char **> (mxRealloc (fields, nfields * sizeof (char *)));
+
+        if (fields)
+          {
+            fields[nfields-1] = strsave (key);
+
+            mwSize nel = get_number_of_elements ();
+
+            mwSize ntot = nfields * nel;
+
+            mxArray **new_data = static_cast<mxArray **> (malloc (ntot * sizeof (mxArray *)));
+
+            if (new_data)
+              {
+                mwIndex j = 0;
+                mwIndex k = 0;
+                mwIndex n = 0;
+
+                for (mwIndex i = 0; i < ntot; i++)
+                  {
+                    if (++n == nfields)
+                      {
+                        new_data[j++] = 0;
+                        n = 0;
+                      }
+                    else
+                      new_data[j++] = data[k++];
+                  }
+
+                mxFree (data);
+
+                data = new_data;
+
+                retval = nfields - 1;
+              }
+          }
+      }
+
+    return retval;
+  }
+
+  void remove_field (int key_num)
+  {
+    if (key_num >= 0 && key_num < nfields)
+      {
+        mwSize nel = get_number_of_elements ();
+
+        mwSize ntot = nfields * nel;
+
+        int new_nfields = nfields - 1;
+
+        char **new_fields = static_cast<char **> (malloc (new_nfields * sizeof (char *)));
+
+        mxArray **new_data = static_cast<mxArray **> (malloc (new_nfields * nel * sizeof (mxArray *)));
+
+        for (int i = 0; i < key_num; i++)
+          new_fields[i] = fields[i];
+
+        for (int i = key_num + 1; i < nfields; i++)
+          new_fields[i-1] = fields[i];
+
+        if (new_nfields > 0)
+          {
+            mwIndex j = 0;
+            mwIndex k = 0;
+            mwIndex n = 0;
+
+            for (mwIndex i = 0; i < ntot; i++)
+              {
+                if (n == key_num)
+                  k++;
+                else
+                  new_data[j++] = data[k++];
+
+                if (++n == nfields)
+                  n = 0;
+              }
+          }
+
+        nfields = new_nfields;
+
+        mxFree (fields);
+        mxFree (data);
+
+        fields = new_fields;
+        data = new_data;
+      }
+  }
+
+  mxArray *get_field_by_number (mwIndex index, int key_num) const
+  {
+    return key_num >= 0 && key_num < nfields
+      ? data[nfields * index + key_num] : 0;
+  }
+
+  void set_field_by_number (mwIndex index, int key_num, mxArray *val);
+
+  int get_number_of_fields (void) const { return nfields; }
+
+  const char *get_field_name_by_number (int key_num) const
+  {
+    return key_num >= 0 && key_num < nfields ? fields[key_num] : 0;
+  }
+
+  int get_field_number (const char *key) const
+  {
+    int retval = -1;
+
+    for (int i = 0; i < nfields; i++)
+      {
+        if (! strcmp (key, fields[i]))
+          {
+            retval = i;
+            break;
+          }
+      }
+
+    return retval;
+  }
+
+  void *get_data (void) const { return data; }
+
+  void set_data (void *data_arg) { data = static_cast<mxArray **> (data_arg); }
+
+protected:
+
+  octave_value as_octave_value (void) const
+  {
+    dim_vector dv = dims_to_dim_vector ();
+
+    string_vector keys (fields, nfields);
+
+    octave_map m;
+
+    mwSize ntot = nfields * get_number_of_elements ();
+
+    for (int i = 0; i < nfields; i++)
+      {
+        Cell c (dv);
+
+        octave_value *p = c.fortran_vec ();
+
+        mwIndex k = 0;
+        for (mwIndex j = i; j < ntot; j += nfields)
+          p[k++] = mxArray::as_octave_value (data[j]);
+
+        m.assign (keys[i], c);
+      }
+
+    return m;
+  }
+
+private:
+
+  int nfields;
+
+  char **fields;
+
+  mxArray **data;
+
+  mxArray_struct (const mxArray_struct& val)
+    : mxArray_matlab (val), nfields (val.nfields),
+      fields (static_cast<char **> (malloc (nfields * sizeof (char *)))),
+      data (static_cast<mxArray **> (malloc (nfields * get_number_of_elements () * sizeof (mxArray *))))
+  {
+    for (int i = 0; i < nfields; i++)
+      fields[i] = strsave (val.fields[i]);
+
+    mwSize nel = get_number_of_elements ();
+
+    for (mwIndex i = 0; i < nel * nfields; i++)
+      {
+        mxArray *ptr = val.data[i];
+        data[i] = ptr ? ptr->dup () : 0;
+      }
+  }
+
+  // No assignment!  FIXME -- should this be implemented?  Note that we
+  // do have a copy constructor.
+
+  mxArray_struct& operator = (const mxArray_struct& val);
+};
+
+// Matlab-style cell arrays.
+
+class mxArray_cell : public mxArray_matlab
+{
+public:
+
+  mxArray_cell (mwSize ndims_arg, const mwSize *dims_arg)
+    : mxArray_matlab (mxCELL_CLASS, ndims_arg, dims_arg),
+      data (static_cast<mxArray **> (calloc (get_number_of_elements (), sizeof (mxArray *)))) { }
+
+  mxArray_cell (const dim_vector& dv)
+    : mxArray_matlab (mxCELL_CLASS, dv),
+      data (static_cast<mxArray **> (calloc (get_number_of_elements (), sizeof (mxArray *)))) { }
+
+  mxArray_cell (mwSize m, mwSize n)
+    : mxArray_matlab (mxCELL_CLASS, m, n),
+      data (static_cast<mxArray **> (calloc (get_number_of_elements (), sizeof (mxArray *)))) { }
+
+  mxArray_cell *dup (void) const { return new mxArray_cell (*this); }
+
+  ~mxArray_cell (void)
+  {
+    mwSize nel = get_number_of_elements ();
+
+    for  (mwIndex i = 0; i < nel; i++)
+      delete data[i];
+
+    mxFree (data);
+  }
+
+  mxArray *get_cell (mwIndex idx) const
+  {
+    return idx >= 0 && idx < get_number_of_elements () ? data[idx] : 0;
+  }
+
+  void set_cell (mwIndex idx, mxArray *val);
+
+  void *get_data (void) const { return data; }
+
+  void set_data (void *data_arg) { data = static_cast<mxArray **> (data_arg); }
+
+protected:
+
+  octave_value as_octave_value (void) const
+  {
+    dim_vector dv = dims_to_dim_vector ();
+
+    Cell c (dv);
+
+    mwSize nel = get_number_of_elements ();
+
+    octave_value *p = c.fortran_vec ();
+
+    for (mwIndex i = 0; i < nel; i++)
+      p[i] = mxArray::as_octave_value (data[i]);
+
+    return c;
+  }
+
+private:
+
+  mxArray **data;
+
+  mxArray_cell (const mxArray_cell& val)
+    : mxArray_matlab (val),
+      data (static_cast<mxArray **> (malloc (get_number_of_elements () * sizeof (mxArray *))))
+  {
+    mwSize nel = get_number_of_elements ();
+
+    for (mwIndex i = 0; i < nel; i++)
+      {
+        mxArray *ptr = val.data[i];
+        data[i] = ptr ? ptr->dup () : 0;
+      }
+  }
+
+  // No assignment!  FIXME -- should this be implemented?  Note that we
+  // do have a copy constructor.
+
+  mxArray_cell& operator = (const mxArray_cell&);
+};
+
+// ------------------------------------------------------------------
+
+mxArray::mxArray (const octave_value& ov)
+  : rep (new mxArray_octave_value (ov)), name (0) { }
+
+mxArray::mxArray (mxClassID id, mwSize ndims, const mwSize *dims, mxComplexity flag)
+  : rep (new mxArray_number (id, ndims, dims, flag)), name (0) { }
+
+mxArray::mxArray (mxClassID id, const dim_vector& dv, mxComplexity flag)
+  : rep (new mxArray_number (id, dv, flag)), name (0) { }
+
+mxArray::mxArray (mxClassID id, mwSize m, mwSize n, mxComplexity flag)
+  : rep (new mxArray_number (id, m, n, flag)), name (0) { }
+
+mxArray::mxArray (mxClassID id, double val)
+  : rep (new mxArray_number (id, val)), name (0) { }
+
+mxArray::mxArray (mxClassID id, mxLogical val)
+  : rep (new mxArray_number (id, val)), name (0) { }
+
+mxArray::mxArray (const char *str)
+  : rep (new mxArray_number (str)), name (0) { }
+
+mxArray::mxArray (mwSize m, const char **str)
+  : rep (new mxArray_number (m, str)), name (0) { }
+
+mxArray::mxArray (mxClassID id, mwSize m, mwSize n, mwSize nzmax, mxComplexity flag)
+  : rep (new mxArray_sparse (id, m, n, nzmax, flag)), name (0) { }
+
+mxArray::mxArray (mwSize ndims, const mwSize *dims, int num_keys, const char **keys)
+  : rep (new mxArray_struct (ndims, dims, num_keys, keys)), name (0) { }
+
+mxArray::mxArray (const dim_vector& dv, int num_keys, const char **keys)
+  : rep (new mxArray_struct (dv, num_keys, keys)), name (0) { }
+
+mxArray::mxArray (mwSize m, mwSize n, int num_keys, const char **keys)
+  : rep (new mxArray_struct (m, n, num_keys, keys)), name (0) { }
+
+mxArray::mxArray (mwSize ndims, const mwSize *dims)
+  : rep (new mxArray_cell (ndims, dims)), name (0) { }
+
+mxArray::mxArray (const dim_vector& dv)
+  : rep (new mxArray_cell (dv)), name (0) { }
+
+mxArray::mxArray (mwSize m, mwSize n)
+  : rep (new mxArray_cell (m, n)), name (0) { }
+
+mxArray::~mxArray (void)
+{
+  mxFree (name);
+
+  delete rep;
+}
+
+void
+mxArray::set_name (const char *name_arg)
+{
+  mxFree (name);
+  name = strsave (name_arg);
+}
+
+octave_value
+mxArray::as_octave_value (mxArray *ptr)
+{
+  return ptr ? ptr->as_octave_value () : octave_value (Matrix ());
+}
+
+octave_value
+mxArray::as_octave_value (void) const
+{
+  return rep->as_octave_value ();
+}
+
+void
+mxArray::maybe_mutate (void) const
+{
+  if (rep->is_octave_value ())
+    {
+      // The mutate function returns a pointer to a complete new
+      // mxArray object (or 0, if no mutation happened).  We just want
+      // to replace the existing rep with the rep from the new object.
+
+      mxArray *new_val = rep->mutate ();
+
+      if (new_val)
+        {
+          delete rep;
+          rep = new_val->rep;
+          new_val->rep = 0;
+          delete new_val;
+        }
+    }
+}
+
+// ------------------------------------------------------------------
+
+// A class to manage calls to MEX functions.  Mostly deals with memory
+// management.
+
+class mex
+{
+public:
+
+  mex (octave_mex_function *f)
+    : curr_mex_fcn (f), memlist (), arraylist (), fname (0) { }
+
+  ~mex (void)
+  {
+    if (! memlist.empty ())
+      error ("mex: %s: cleanup failed", function_name ());
+
+    mxFree (fname);
+  }
+
+  const char *function_name (void) const
+  {
+    if (! fname)
+      {
+        octave_function *fcn = octave_call_stack::current ();
+
+        if (fcn)
+          {
+            std::string nm = fcn->name ();
+            fname = mxArray::strsave (nm.c_str ());
+          }
+        else
+          fname = mxArray::strsave ("unknown");
+      }
+
+    return fname;
+  }
+
+  // Free all unmarked pointers obtained from malloc and calloc.
+  static void cleanup (void *ptr)
+  {
+    mex *context = static_cast<mex *> (ptr);
+
+    // We can't use mex::free here because it modifies memlist.
+    for (std::set<void *>::iterator p = context->memlist.begin ();
+         p != context->memlist.end (); p++)
+      xfree (*p);
+
+    context->memlist.clear ();
+
+    // We can't use mex::free_value here because it modifies arraylist.
+    for (std::set<mxArray *>::iterator p = context->arraylist.begin ();
+         p != context->arraylist.end (); p++)
+      delete *p;
+
+    context->arraylist.clear ();
+  }
+
+  // Allocate memory.
+  void *malloc_unmarked (size_t n)
+  {
+    void *ptr = gnulib::malloc (n);
+
+    if (! ptr)
+      {
+        // FIXME -- could use "octave_new_handler();" instead
+
+        error ("%s: failed to allocate %d bytes of memory",
+               function_name (), n);
+
+        abort ();
+      }
+
+    global_mark (ptr);
+
+    return ptr;
+  }
+
+  // Allocate memory to be freed on exit.
+  void *malloc (size_t n)
+  {
+    void *ptr = malloc_unmarked (n);
+
+    mark (ptr);
+
+    return ptr;
+  }
+
+  // Allocate memory and initialize to 0.
+  void *calloc_unmarked (size_t n, size_t t)
+  {
+    void *ptr = malloc_unmarked (n*t);
+
+    memset (ptr, 0, n*t);
+
+    return ptr;
+  }
+
+  // Allocate memory to be freed on exit and initialize to 0.
+  void *calloc (size_t n, size_t t)
+  {
+    void *ptr = calloc_unmarked (n, t);
+
+    mark (ptr);
+
+    return ptr;
+  }
+
+  // Reallocate a pointer obtained from malloc or calloc. If the
+  // pointer is NULL, allocate using malloc.  We don't need an
+  // "unmarked" version of this.
+  void *realloc (void *ptr, size_t n)
+  {
+    void *v;
+
+    if (ptr)
+      {
+        v = gnulib::realloc (ptr, n);
+
+        std::set<void *>::iterator p = memlist.find (ptr);
+
+        if (v && p != memlist.end ())
+          {
+            memlist.erase (p);
+            memlist.insert (v);
+          }
+
+        p = global_memlist.find (ptr);
+
+        if (v && p != global_memlist.end ())
+          {
+            global_memlist.erase (p);
+            global_memlist.insert (v);
+          }
+      }
+    else
+      v = malloc (n);
+
+    return v;
+  }
+
+  // Free a pointer obtained from malloc or calloc.
+  void free (void *ptr)
+  {
+    if (ptr)
+      {
+        unmark (ptr);
+
+        std::set<void *>::iterator p = global_memlist.find (ptr);
+
+        if (p != global_memlist.end ())
+          {
+            global_memlist.erase (p);
+
+            xfree (ptr);
+          }
+        else
+          {
+            p = foreign_memlist.find (ptr);
+
+            if (p != foreign_memlist.end ())
+              foreign_memlist.erase (p);
+#ifdef DEBUG
+            else
+              warning ("mxFree: skipping memory not allocated by mxMalloc, mxCalloc, or mxRealloc");
+#endif
+          }
+      }
+  }
+
+  // Mark a pointer to be freed on exit.
+  void mark (void *ptr)
+  {
+#ifdef DEBUG
+    if (memlist.find (ptr) != memlist.end ())
+      warning ("%s: double registration ignored", function_name ());
+#endif
+
+    memlist.insert (ptr);
+  }
+
+  // Unmark a pointer to be freed on exit, either because it was
+  // made persistent, or because it was already freed.
+  void unmark (void *ptr)
+  {
+    std::set<void *>::iterator p = memlist.find (ptr);
+
+    if (p != memlist.end ())
+      memlist.erase (p);
+#ifdef DEBUG
+    else
+      warning ("%s: value not marked", function_name ());
+#endif
+  }
+
+  mxArray *mark_array (mxArray *ptr)
+  {
+    arraylist.insert (ptr);
+    return ptr;
+  }
+
+  void unmark_array (mxArray *ptr)
+  {
+    std::set<mxArray *>::iterator p = arraylist.find (ptr);
+
+    if (p != arraylist.end ())
+      arraylist.erase (p);
+  }
+
+  // Mark a pointer as one we allocated.
+  void mark_foreign (void *ptr)
+  {
+#ifdef DEBUG
+    if (foreign_memlist.find (ptr) != foreign_memlist.end ())
+      warning ("%s: double registration ignored", function_name ());
+#endif
+
+    foreign_memlist.insert (ptr);
+  }
+
+  // Unmark a pointer as one we allocated.
+  void unmark_foreign (void *ptr)
+  {
+    std::set<void *>::iterator p = foreign_memlist.find (ptr);
+
+    if (p != foreign_memlist.end ())
+      foreign_memlist.erase (p);
+#ifdef DEBUG
+    else
+      warning ("%s: value not marked", function_name ());
+#endif
+
+  }
+
+  // Make a new array value and initialize from an octave value; it will be
+  // freed on exit unless marked as persistent.
+  mxArray *make_value (const octave_value& ov)
+  {
+    return mark_array (new mxArray (ov));
+  }
+
+  // Free an array and its contents.
+  bool free_value (mxArray *ptr)
+  {
+    bool inlist = false;
+
+    std::set<mxArray *>::iterator p = arraylist.find (ptr);
+
+    if (p != arraylist.end ())
+      {
+        inlist = true;
+        arraylist.erase (p);
+        delete ptr;
+      }
+#ifdef DEBUG
+    else
+      warning ("mex::free_value: skipping memory not allocated by mex::make_value");
+#endif
+
+    return inlist;
+  }
+
+  octave_mex_function *current_mex_function (void) const
+  {
+    return curr_mex_fcn;
+  }
+
+  // 1 if error should be returned to MEX file, 0 if abort.
+  int trap_feval_error;
+
+  // longjmp return point if mexErrMsgTxt or error.
+  jmp_buf jump;
+
+  // Trigger a long jump back to the mex calling function.
+  void abort (void) { longjmp (jump, 1); }
+
+private:
+
+  // Pointer to the mex function that corresponds to this mex context.
+  octave_mex_function *curr_mex_fcn;
+
+  // List of memory resources that need to be freed upon exit.
+  std::set<void *> memlist;
+
+  // List of mxArray objects that need to be freed upon exit.
+  std::set<mxArray *> arraylist;
+
+  // List of memory resources we know about, but that were allocated
+  // elsewhere.
+  std::set<void *> foreign_memlist;
+
+  // The name of the currently executing function.
+  mutable char *fname;
+
+  // List of memory resources we allocated.
+  static std::set<void *> global_memlist;
+
+  // Mark a pointer as one we allocated.
+  void global_mark (void *ptr)
+  {
+#ifdef DEBUG
+    if (global_memlist.find (ptr) != global_memlist.end ())
+      warning ("%s: double registration ignored", function_name ());
+#endif
+
+    global_memlist.insert (ptr);
+  }
+
+  // Unmark a pointer as one we allocated.
+  void global_unmark (void *ptr)
+  {
+    std::set<void *>::iterator p = global_memlist.find (ptr);
+
+    if (p != global_memlist.end ())
+      global_memlist.erase (p);
+#ifdef DEBUG
+    else
+      warning ("%s: value not marked", function_name ());
+#endif
+
+  }
+
+  // No copying!
+
+  mex (const mex&);
+
+  mex& operator = (const mex&);
+};
+
+// List of memory resources we allocated.
+std::set<void *> mex::global_memlist;
+
+// Current context.
+mex *mex_context = 0;
+
+void *
+mxArray::malloc (size_t n)
+{
+  return mex_context ? mex_context->malloc_unmarked (n) : gnulib::malloc (n);
+}
+
+void *
+mxArray::calloc (size_t n, size_t t)
+{
+  return mex_context ? mex_context->calloc_unmarked (n, t) : ::calloc (n, t);
+}
+
+static inline void *
+maybe_mark_foreign (void *ptr)
+{
+  if (mex_context)
+    mex_context->mark_foreign (ptr);
+
+  return ptr;
+}
+
+static inline mxArray *
+maybe_unmark_array (mxArray *ptr)
+{
+  if (mex_context)
+    mex_context->unmark_array (ptr);
+
+  return ptr;
+}
+
+static inline void *
+maybe_unmark (void *ptr)
+{
+  if (mex_context)
+    mex_context->unmark (ptr);
+
+  return ptr;
+}
+
+void
+mxArray_struct::set_field_by_number (mwIndex index, int key_num, mxArray *val)
+{
+  if (key_num >= 0 && key_num < nfields)
+    data[nfields * index + key_num] = maybe_unmark_array (val);
+}
+
+void
+mxArray_cell::set_cell (mwIndex idx, mxArray *val)
+{
+  if (idx >= 0 && idx < get_number_of_elements ())
+    data[idx] = maybe_unmark_array (val);
+}
+
+// ------------------------------------------------------------------
+
+// C interface to mxArray objects:
+
+// Floating point predicates.
+
+int
+mxIsFinite (const double v)
+{
+  return lo_ieee_finite (v) != 0;
+}
+
+int
+mxIsInf (const double v)
+{
+  return lo_ieee_isinf (v) != 0;
+}
+
+int
+mxIsNaN (const double v)
+{
+  return lo_ieee_isnan (v) != 0;
+}
+
+double
+mxGetEps (void)
+{
+  return DBL_EPSILON;
+}
+
+double
+mxGetInf (void)
+{
+  return lo_ieee_inf_value ();
+}
+
+double
+mxGetNaN (void)
+{
+  return lo_ieee_nan_value ();
+}
+
+// Memory management.
+void *
+mxCalloc (size_t n, size_t size)
+{
+  return mex_context ? mex_context->calloc (n, size) : calloc (n, size);
+}
+
+void *
+mxMalloc (size_t n)
+{
+  return mex_context ? mex_context->malloc (n) : gnulib::malloc (n);
+}
+
+void *
+mxRealloc (void *ptr, size_t size)
+{
+  return mex_context ? mex_context->realloc (ptr, size) : gnulib::realloc (ptr, size);
+}
+
+void
+mxFree (void *ptr)
+{
+  if (mex_context)
+    mex_context->free (ptr);
+  else
+    xfree (ptr);
+}
+
+static inline mxArray *
+maybe_mark_array (mxArray *ptr)
+{
+  return mex_context ? mex_context->mark_array (ptr) : ptr;
+}
+
+// Constructors.
+mxArray *
+mxCreateCellArray (mwSize ndims, const mwSize *dims)
+{
+  return maybe_mark_array (new mxArray (ndims, dims));
+}
+
+mxArray *
+mxCreateCellMatrix (mwSize m, mwSize n)
+{
+  return maybe_mark_array (new mxArray (m, n));
+}
+
+mxArray *
+mxCreateCharArray (mwSize ndims, const mwSize *dims)
+{
+  return maybe_mark_array (new mxArray (mxCHAR_CLASS, ndims, dims));
+}
+
+mxArray *
+mxCreateCharMatrixFromStrings (mwSize m, const char **str)
+{
+  return maybe_mark_array (new mxArray (m, str));
+}
+
+mxArray *
+mxCreateDoubleMatrix (mwSize m, mwSize n, mxComplexity flag)
+{
+  return maybe_mark_array (new mxArray (mxDOUBLE_CLASS, m, n, flag));
+}
+
+mxArray *
+mxCreateDoubleScalar (double val)
+{
+  return maybe_mark_array (new mxArray (mxDOUBLE_CLASS, val));
+}
+
+mxArray *
+mxCreateLogicalArray (mwSize ndims, const mwSize *dims)
+{
+  return maybe_mark_array (new mxArray (mxLOGICAL_CLASS, ndims, dims));
+}
+
+mxArray *
+mxCreateLogicalMatrix (mwSize m, mwSize n)
+{
+  return maybe_mark_array (new mxArray (mxLOGICAL_CLASS, m, n));
+}
+
+mxArray *
+mxCreateLogicalScalar (mxLogical val)
+{
+  return maybe_mark_array (new mxArray (mxLOGICAL_CLASS, val));
+}
+
+mxArray *
+mxCreateNumericArray (mwSize ndims, const mwSize *dims, mxClassID class_id,
+                      mxComplexity flag)
+{
+  return maybe_mark_array (new mxArray (class_id, ndims, dims, flag));
+}
+
+mxArray *
+mxCreateNumericMatrix (mwSize m, mwSize n, mxClassID class_id, mxComplexity flag)
+{
+  return maybe_mark_array (new mxArray (class_id, m, n, flag));
+}
+
+mxArray *
+mxCreateSparse (mwSize m, mwSize n, mwSize nzmax, mxComplexity flag)
+{
+  return maybe_mark_array (new mxArray (mxDOUBLE_CLASS, m, n, nzmax, flag));
+}
+
+mxArray *
+mxCreateSparseLogicalMatrix (mwSize m, mwSize n, mwSize nzmax)
+{
+  return maybe_mark_array (new mxArray (mxLOGICAL_CLASS, m, n, nzmax));
+}
+
+mxArray *
+mxCreateString (const char *str)
+{
+  return maybe_mark_array (new mxArray (str));
+}
+
+mxArray *
+mxCreateStructArray (mwSize ndims, const mwSize *dims, int num_keys, const char **keys)
+{
+  return maybe_mark_array (new mxArray (ndims, dims, num_keys, keys));
+}
+
+mxArray *
+mxCreateStructMatrix (mwSize m, mwSize n, int num_keys, const char **keys)
+{
+  return maybe_mark_array (new mxArray (m, n, num_keys, keys));
+}
+
+// Copy constructor.
+mxArray *
+mxDuplicateArray (const mxArray *ptr)
+{
+  return maybe_mark_array (ptr->dup ());
+}
+
+// Destructor.
+void
+mxDestroyArray (mxArray *ptr)
+{
+  if (! (mex_context && mex_context->free_value (ptr)))
+    delete ptr;
+}
+
+// Type Predicates.
+int
+mxIsCell (const mxArray *ptr)
+{
+  return ptr->is_cell ();
+}
+
+int
+mxIsChar (const mxArray *ptr)
+{
+  return ptr->is_char ();
+}
+
+int
+mxIsClass (const mxArray *ptr, const char *name)
+{
+  return ptr->is_class (name);
+}
+
+int
+mxIsComplex (const mxArray *ptr)
+{
+  return ptr->is_complex ();
+}
+
+int
+mxIsDouble (const mxArray *ptr)
+{
+  return ptr->is_double ();
+}
+
+int
+mxIsFunctionHandle (const mxArray *ptr)
+{
+  return ptr->is_function_handle ();
+}
+
+int
+mxIsInt16 (const mxArray *ptr)
+{
+  return ptr->is_int16 ();
+}
+
+int
+mxIsInt32 (const mxArray *ptr)
+{
+  return ptr->is_int32 ();
+}
+
+int
+mxIsInt64 (const mxArray *ptr)
+{
+  return ptr->is_int64 ();
+}
+
+int
+mxIsInt8 (const mxArray *ptr)
+{
+  return ptr->is_int8 ();
+}
+
+int
+mxIsLogical (const mxArray *ptr)
+{
+  return ptr->is_logical ();
+}
+
+int
+mxIsNumeric (const mxArray *ptr)
+{
+  return ptr->is_numeric ();
+}
+
+int
+mxIsSingle (const mxArray *ptr)
+{
+  return ptr->is_single ();
+}
+
+int
+mxIsSparse (const mxArray *ptr)
+{
+  return ptr->is_sparse ();
+}
+
+int
+mxIsStruct (const mxArray *ptr)
+{
+  return ptr->is_struct ();
+}
+
+int
+mxIsUint16 (const mxArray *ptr)
+{
+  return ptr->is_uint16 ();
+}
+
+int
+mxIsUint32 (const mxArray *ptr)
+{
+  return ptr->is_uint32 ();
+}
+
+int
+mxIsUint64 (const mxArray *ptr)
+{
+  return ptr->is_uint64 ();
+}
+
+int
+mxIsUint8 (const mxArray *ptr)
+{
+  return ptr->is_uint8 ();
+}
+
+// Odd type+size predicate.
+int
+mxIsLogicalScalar (const mxArray *ptr)
+{
+  return ptr->is_logical_scalar ();
+}
+
+// Odd type+size+value predicate.
+int
+mxIsLogicalScalarTrue (const mxArray *ptr)
+{
+  return ptr->is_logical_scalar_true ();
+}
+
+// Size predicate.
+int
+mxIsEmpty (const mxArray *ptr)
+{
+  return ptr->is_empty ();
+}
+
+// Just plain odd thing to ask of a value.
+int
+mxIsFromGlobalWS (const mxArray */*ptr*/)
+{
+  // FIXME
+  abort ();
+  return 0;
+}
+
+// Dimension extractors.
+size_t
+mxGetM (const mxArray *ptr)
+{
+  return ptr->get_m ();
+}
+
+size_t
+mxGetN (const mxArray *ptr)
+{
+  return ptr->get_n ();
+}
+
+mwSize *
+mxGetDimensions (const mxArray *ptr)
+{
+  return ptr->get_dimensions ();
+}
+
+mwSize
+mxGetNumberOfDimensions (const mxArray *ptr)
+{
+  return ptr->get_number_of_dimensions ();
+}
+
+size_t
+mxGetNumberOfElements (const mxArray *ptr)
+{
+  return ptr->get_number_of_elements ();
+}
+
+// Dimension setters.
+void
+mxSetM (mxArray *ptr, mwSize m)
+{
+  ptr->set_m (m);
+}
+
+void
+mxSetN (mxArray *ptr, mwSize n)
+{
+  ptr->set_n (n);
+}
+
+void
+mxSetDimensions (mxArray *ptr, const mwSize *dims, mwSize ndims)
+{
+  ptr->set_dimensions (static_cast<mwSize *> (
+                         maybe_unmark (const_cast<mwSize *> (dims))),
+                       ndims);
+}
+
+// Data extractors.
+double *
+mxGetPr (const mxArray *ptr)
+{
+  return static_cast<double *> (ptr->get_data ());
+}
+
+double *
+mxGetPi (const mxArray *ptr)
+{
+  return static_cast<double *> (ptr->get_imag_data ());
+}
+
+double
+mxGetScalar (const mxArray *ptr)
+{
+  return ptr->get_scalar ();
+}
+
+mxChar *
+mxGetChars (const mxArray *ptr)
+{
+  return static_cast<mxChar *> (ptr->get_data ());
+}
+
+mxLogical *
+mxGetLogicals (const mxArray *ptr)
+{
+  return static_cast<mxLogical *> (ptr->get_data ());
+}
+
+void *
+mxGetData (const mxArray *ptr)
+{
+  return ptr->get_data ();
+}
+
+void *
+mxGetImagData (const mxArray *ptr)
+{
+  return ptr->get_imag_data ();
+}
+
+// Data setters.
+void
+mxSetPr (mxArray *ptr, double *pr)
+{
+  ptr->set_data (maybe_unmark (pr));
+}
+
+void
+mxSetPi (mxArray *ptr, double *pi)
+{
+  ptr->set_imag_data (maybe_unmark (pi));
+}
+
+void
+mxSetData (mxArray *ptr, void *pr)
+{
+  ptr->set_data (maybe_unmark (pr));
+}
+
+void
+mxSetImagData (mxArray *ptr, void *pi)
+{
+  ptr->set_imag_data (maybe_unmark (pi));
+}
+
+// Classes.
+mxClassID
+mxGetClassID (const mxArray *ptr)
+{
+  return ptr->get_class_id ();
+}
+
+const char *
+mxGetClassName (const mxArray *ptr)
+{
+  return ptr->get_class_name ();
+}
+
+void
+mxSetClassName (mxArray *ptr, const char *name)
+{
+  ptr->set_class_name (name);
+}
+
+// Cell support.
+mxArray *
+mxGetCell (const mxArray *ptr, mwIndex idx)
+{
+  return ptr->get_cell (idx);
+}
+
+void
+mxSetCell (mxArray *ptr, mwIndex idx, mxArray *val)
+{
+  ptr->set_cell (idx, val);
+}
+
+// Sparse support.
+mwIndex *
+mxGetIr (const mxArray *ptr)
+{
+  return ptr->get_ir ();
+}
+
+mwIndex *
+mxGetJc (const mxArray *ptr)
+{
+  return ptr->get_jc ();
+}
+
+mwSize
+mxGetNzmax (const mxArray *ptr)
+{
+  return ptr->get_nzmax ();
+}
+
+void
+mxSetIr (mxArray *ptr, mwIndex *ir)
+{
+  ptr->set_ir (static_cast <mwIndex *> (maybe_unmark (ir)));
+}
+
+void
+mxSetJc (mxArray *ptr, mwIndex *jc)
+{
+  ptr->set_jc (static_cast<mwIndex *> (maybe_unmark (jc)));
+}
+
+void
+mxSetNzmax (mxArray *ptr, mwSize nzmax)
+{
+  ptr->set_nzmax (nzmax);
+}
+
+// Structure support.
+int
+mxAddField (mxArray *ptr, const char *key)
+{
+  return ptr->add_field (key);
+}
+
+void
+mxRemoveField (mxArray *ptr, int key_num)
+{
+  ptr->remove_field (key_num);
+}
+
+mxArray *
+mxGetField (const mxArray *ptr, mwIndex index, const char *key)
+{
+  int key_num = mxGetFieldNumber (ptr, key);
+  return mxGetFieldByNumber (ptr, index, key_num);
+}
+
+mxArray *
+mxGetFieldByNumber (const mxArray *ptr, mwIndex index, int key_num)
+{
+  return ptr->get_field_by_number (index, key_num);
+}
+
+void
+mxSetField (mxArray *ptr, mwIndex index, const char *key, mxArray *val)
+{
+  int key_num = mxGetFieldNumber (ptr, key);
+  mxSetFieldByNumber (ptr, index, key_num, val);
+}
+
+void
+mxSetFieldByNumber (mxArray *ptr, mwIndex index, int key_num, mxArray *val)
+{
+  ptr->set_field_by_number (index, key_num, val);
+}
+
+int
+mxGetNumberOfFields (const mxArray *ptr)
+{
+  return ptr->get_number_of_fields ();
+}
+
+const char *
+mxGetFieldNameByNumber (const mxArray *ptr, int key_num)
+{
+  return ptr->get_field_name_by_number (key_num);
+}
+
+int
+mxGetFieldNumber (const mxArray *ptr, const char *key)
+{
+  return ptr->get_field_number (key);
+}
+
+int
+mxGetString (const mxArray *ptr, char *buf, mwSize buflen)
+{
+  return ptr->get_string (buf, buflen);
+}
+
+char *
+mxArrayToString (const mxArray *ptr)
+{
+  return ptr->array_to_string ();
+}
+
+mwIndex
+mxCalcSingleSubscript (const mxArray *ptr, mwSize nsubs, mwIndex *subs)
+{
+  return ptr->calc_single_subscript (nsubs, subs);
+}
+
+size_t
+mxGetElementSize (const mxArray *ptr)
+{
+  return ptr->get_element_size ();
+}
+
+// ------------------------------------------------------------------
+
+typedef void (*cmex_fptr) (int nlhs, mxArray **plhs, int nrhs, mxArray **prhs);
+typedef F77_RET_T (*fmex_fptr) (int& nlhs, mxArray **plhs, int& nrhs, mxArray **prhs);
+
+octave_value_list
+call_mex (bool have_fmex, void *f, const octave_value_list& args,
+          int nargout_arg, octave_mex_function *curr_mex_fcn)
+{
+  // Use at least 1 for nargout since even for zero specified args,
+  // still want to be able to return an ans.
+
+  volatile int nargout = nargout_arg;
+
+  int nargin = args.length ();
+  OCTAVE_LOCAL_BUFFER (mxArray *, argin, nargin);
+  for (int i = 0; i < nargin; i++)
+    argin[i] = 0;
+
+  int nout = nargout == 0 ? 1 : nargout;
+  OCTAVE_LOCAL_BUFFER (mxArray *, argout, nout);
+  for (int i = 0; i < nout; i++)
+    argout[i] = 0;
+
+  unwind_protect_safe frame;
+
+  // Save old mex pointer.
+  frame.protect_var (mex_context);
+
+  mex context (curr_mex_fcn);
+
+  frame.add (mex::cleanup, static_cast<void *> (&context));
+
+  for (int i = 0; i < nargin; i++)
+    argin[i] = context.make_value (args(i));
+
+  if (setjmp (context.jump) == 0)
+    {
+      mex_context = &context;
+
+      if (have_fmex)
+        {
+          fmex_fptr fcn = FCN_PTR_CAST (fmex_fptr, f);
+
+          int tmp_nargout = nargout;
+          int tmp_nargin = nargin;
+
+          fcn (tmp_nargout, argout, tmp_nargin, argin);
+        }
+      else
+        {
+          cmex_fptr fcn = FCN_PTR_CAST (cmex_fptr, f);
+
+          fcn (nargout, argout, nargin, argin);
+        }
+    }
+
+  // Convert returned array entries back into octave values.
+
+  octave_value_list retval;
+
+  if (! error_state)
+    {
+      if (nargout == 0 && argout[0])
+        {
+          // We have something for ans.
+          nargout = 1;
+        }
+
+      retval.resize (nargout);
+
+      for (int i = 0; i < nargout; i++)
+        retval(i) = mxArray::as_octave_value (argout[i]);
+    }
+
+  // Clean up mex resources.
+  frame.run ();
+
+  return retval;
+}
+
+// C interface to mex functions:
+
+const char *
+mexFunctionName (void)
+{
+  return mex_context ? mex_context->function_name () : "unknown";
+}
+
+int
+mexCallMATLAB (int nargout, mxArray *argout[], int nargin, mxArray *argin[],
+               const char *fname)
+{
+  octave_value_list args;
+
+  // FIXME -- do we need unwind protect to clean up args?  Off hand, I
+  // would say that this problem is endemic to Octave and we will
+  // continue to have memory leaks after Ctrl-C until proper exception
+  // handling is implemented.  longjmp() only clears the stack, so any
+  // class which allocates data on the heap is going to leak.
+
+  args.resize (nargin);
+
+  for (int i = 0; i < nargin; i++)
+    args(i) = mxArray::as_octave_value (argin[i]);
+
+  octave_value_list retval = feval (fname, args, nargout);
+
+  if (error_state && mex_context->trap_feval_error == 0)
+    {
+      // FIXME -- is this the correct way to clean up?  abort() is
+      // going to trigger a long jump, so the normal class destructors
+      // will not be called.  Hopefully this will reduce things to a
+      // tiny leak.  Maybe create a new octave memory tracer type
+      // which prints a friendly message every time it is
+      // created/copied/deleted to check this.
+
+      args.resize (0);
+      retval.resize (0);
+      mex_context->abort ();
+    }
+
+  int num_to_copy = retval.length ();
+
+  if (nargout < retval.length ())
+    num_to_copy = nargout;
+
+  for (int i = 0; i < num_to_copy; i++)
+    {
+      // FIXME -- it would be nice to avoid copying the value here,
+      // but there is no way to steal memory from a matrix, never mind
+      // that matrix memory is allocated by new[] and mxArray memory
+      // is allocated by malloc().
+      argout[i] = mex_context->make_value (retval (i));
+    }
+
+  while (num_to_copy < nargout)
+    argout[num_to_copy++] = 0;
+
+  if (error_state)
+    {
+      error_state = 0;
+      return 1;
+    }
+  else
+    return 0;
+}
+
+void
+mexSetTrapFlag (int flag)
+{
+  if (mex_context)
+    mex_context->trap_feval_error = flag;
+}
+
+int
+mexEvalString (const char *s)
+{
+  int retval = 0;
+
+  int parse_status;
+
+  octave_value_list ret;
+
+  ret = eval_string (s, false, parse_status, 0);
+
+  if (parse_status || error_state)
+    {
+      error_state = 0;
+
+      retval = 1;
+    }
+
+  return retval;
+}
+
+void
+mexErrMsgTxt (const char *s)
+{
+  if (s && strlen (s) > 0)
+    error ("%s: %s", mexFunctionName (), s);
+  else
+    // Just set the error state; don't print msg.
+    error ("");
+
+  mex_context->abort ();
+}
+
+void
+mexErrMsgIdAndTxt (const char *id, const char *fmt, ...)
+{
+  if (fmt && strlen (fmt) > 0)
+    {
+      const char *fname = mexFunctionName ();
+      size_t len = strlen (fname) + 2 + strlen (fmt) + 1;
+      OCTAVE_LOCAL_BUFFER (char, tmpfmt, len);
+      sprintf (tmpfmt, "%s: %s", fname, fmt);
+      va_list args;
+      va_start (args, fmt);
+      verror_with_id (id, tmpfmt, args);
+      va_end (args);
+    }
+  else
+    // Just set the error state; don't print msg.
+    error ("");
+
+  mex_context->abort ();
+}
+
+void
+mexWarnMsgTxt (const char *s)
+{
+  warning ("%s", s);
+}
+
+void
+mexWarnMsgIdAndTxt (const char *id, const char *fmt, ...)
+{
+  // FIXME -- is this right?  What does Matlab do if fmt is NULL or
+  // an empty string?
+
+  if (fmt && strlen (fmt) > 0)
+    {
+      const char *fname = mexFunctionName ();
+      size_t len = strlen (fname) + 2 + strlen (fmt) + 1;
+      OCTAVE_LOCAL_BUFFER (char, tmpfmt, len);
+      sprintf (tmpfmt, "%s: %s", fname, fmt);
+      va_list args;
+      va_start (args, fmt);
+      vwarning_with_id (id, tmpfmt, args);
+      va_end (args);
+    }
+}
+
+int
+mexPrintf (const char *fmt, ...)
+{
+  int retval;
+  va_list args;
+  va_start (args, fmt);
+  retval = octave_vformat (octave_stdout, fmt, args);
+  va_end (args);
+  return retval;
+}
+
+mxArray *
+mexGetVariable (const char *space, const char *name)
+{
+  mxArray *retval = 0;
+
+  octave_value val;
+
+  if (! strcmp (space, "global"))
+    val = get_global_value (name);
+  else
+    {
+      // FIXME -- should this be in variables.cc?
+
+      unwind_protect frame;
+
+      bool caller = ! strcmp (space, "caller");
+      bool base = ! strcmp (space, "base");
+
+      if (caller || base)
+        {
+          if (caller)
+            octave_call_stack::goto_caller_frame ();
+          else
+            octave_call_stack::goto_base_frame ();
+
+          if (! error_state)
+            frame.add_fcn (octave_call_stack::pop);
+
+          val = symbol_table::varval (name);
+        }
+      else
+        mexErrMsgTxt ("mexGetVariable: symbol table does not exist");
+    }
+
+  if (val.is_defined ())
+    {
+      retval = mex_context->make_value (val);
+
+      retval->set_name (name);
+    }
+
+  return retval;
+}
+
+const mxArray *
+mexGetVariablePtr (const char *space, const char *name)
+{
+  return mexGetVariable (space, name);
+}
+
+int
+mexPutVariable (const char *space, const char *name, mxArray *ptr)
+{
+  if (! ptr)
+    return 1;
+
+  if (! name)
+    return 1;
+
+  if (name[0] == '\0')
+    name = ptr->get_name ();
+
+  if (! name || name[0] == '\0')
+    return 1;
+
+  if (! strcmp (space, "global"))
+    set_global_value (name, mxArray::as_octave_value (ptr));
+  else
+    {
+      // FIXME -- should this be in variables.cc?
+
+      unwind_protect frame;
+
+      bool caller = ! strcmp (space, "caller");
+      bool base = ! strcmp (space, "base");
+
+      if (caller || base)
+        {
+          if (caller)
+            octave_call_stack::goto_caller_frame ();
+          else
+            octave_call_stack::goto_base_frame ();
+
+          if (! error_state)
+            frame.add_fcn (octave_call_stack::pop);
+
+          symbol_table::varref (name) = mxArray::as_octave_value (ptr);
+        }
+      else
+        mexErrMsgTxt ("mexPutVariable: symbol table does not exist");
+    }
+
+  return 0;
+}
+
+void
+mexMakeArrayPersistent (mxArray *ptr)
+{
+  maybe_unmark_array (ptr);
+}
+
+void
+mexMakeMemoryPersistent (void *ptr)
+{
+  maybe_unmark (ptr);
+}
+
+int
+mexAtExit (void (*f) (void))
+{
+  if (mex_context)
+    {
+      octave_mex_function *curr_mex_fcn = mex_context->current_mex_function ();
+
+      assert (curr_mex_fcn);
+
+      curr_mex_fcn->atexit (f);
+    }
+
+  return 0;
+}
+
+const mxArray *
+mexGet (double handle, const char *property)
+{
+  mxArray *m = 0;
+  octave_value ret = get_property_from_handle (handle, property, "mexGet");
+
+  if (!error_state && ret.is_defined ())
+    m = ret.as_mxArray ();
+  return m;
+}
+
+int
+mexIsGlobal (const mxArray *ptr)
+{
+  return mxIsFromGlobalWS (ptr);
+}
+
+int
+mexIsLocked (void)
+{
+  int retval = 0;
+
+  if (mex_context)
+    {
+      const char *fname = mexFunctionName ();
+
+      retval = mislocked (fname);
+    }
+
+  return retval;
+}
+
+std::map<std::string,int> mex_lock_count;
+
+void
+mexLock (void)
+{
+  if (mex_context)
+    {
+      const char *fname = mexFunctionName ();
+
+      if (mex_lock_count.find (fname) == mex_lock_count.end ())
+        mex_lock_count[fname] = 1;
+      else
+        mex_lock_count[fname]++;
+
+      mlock ();
+    }
+}
+
+int
+mexSet (double handle, const char *property, mxArray *val)
+{
+  bool ret =
+    set_property_in_handle (handle, property, mxArray::as_octave_value (val),
+                            "mexSet");
+  return (ret ? 0 : 1);
+}
+
+void
+mexUnlock (void)
+{
+  if (mex_context)
+    {
+      const char *fname = mexFunctionName ();
+
+      std::map<std::string,int>::iterator p = mex_lock_count.find (fname);
+
+      if (p != mex_lock_count.end ())
+        {
+          int count = --mex_lock_count[fname];
+
+          if (count == 0)
+            {
+              munlock (fname);
+
+              mex_lock_count.erase (p);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/mex.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,175 @@
+/*
+
+Copyright (C) 2001-2012 Paul Kienzle
+
+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/>.
+
+*/
+
+/*
+
+This code was originally distributed as part of Octave Forge under
+the following terms:
+
+Author: Paul Kienzle
+I grant this code to the public domain.
+2001-03-22
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+*/
+
+/* mex.h is for use in C-programs only; do NOT include it in mex.cc */
+
+#if ! defined (MEX_H)
+#define MEX_H
+
+#define HAVE_OCTAVE
+
+typedef void mxArray;
+
+#if ! defined (__cplusplus)
+typedef int bool;
+#endif
+
+/* -V4 stuff */
+#if defined (V4)
+#define Matrix mxArray
+#define REAL mxREAL
+#endif
+
+#define mxMAXNAME 64
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if defined (V4)
+void mexFunction (int nlhs, mxArray* plhs[], int nrhs, mxArray *prhs[]);
+#else
+void mexFunction (int nlhs, mxArray* plhs[], int nrhs, const mxArray *prhs[]);
+#endif
+
+#include "mexproto.h"
+
+/* V4 floating point routines renamed in V5.  */
+#define mexIsNaN mxIsNaN
+#define mexIsFinite mxIsFinite
+#define mexIsInf mxIsInf
+#define mexGetEps mxGetEps
+#define mexGetInf mxGetInf
+#define mexGetNaN mxGetNan
+
+#define mexGetGlobal(nm) mexGetArray (nm, "global")
+#define mexGetMatrix(nm) mexGetArray (nm, "caller")
+#define mexGetMatrixPtr(nm) mexGetArrayPtr (nm, "caller")
+
+#define mexGetArray(nm, space) mexGetVariable (space, nm)
+#define mexGetArrayPtr(nm, space) mexGetVariablePtr (space, nm)
+
+#define mexPutMatrix(ptr) mexPutVariable ("caller", "", ptr)
+#define mexPutArray(ptr, space) mexPutVariable (space, "", ptr)
+
+#define mxCreateFull mxCreateDoubleMatrix
+
+#define mxCreateScalarDouble mxCreateDoubleScalar
+
+#define mxFreeMatrix mxDestroyArray
+
+#define mxIsString mxIsChar
+
+/* Apparently these are also defined.  */
+
+#ifndef UINT64_T
+#define UINT64_T uint64_t
+#endif
+
+#ifndef uint64_T
+#define uint64_T uint64_t
+#endif
+
+#ifndef INT64_T
+#define INT64_T int64_t
+#endif
+
+#ifndef int64_T
+#define int64_T int64_t
+#endif
+
+#ifndef UINT32_T
+#define UINT32_T uint32_t
+#endif
+
+#ifndef uint32_T
+#define uint32_T uint32_t
+#endif
+
+#ifndef INT32_T
+#define INT32_T int32_t
+#endif
+
+#ifndef int32_T
+#define int32_T int32_t
+#endif
+
+#ifndef UINT16_T
+#define UINT16_T uint16_t
+#endif
+
+#ifndef uint16_T
+#define uint16_T uint16_t
+#endif
+
+#ifndef INT16_T
+#define INT16_T int16_t
+#endif
+
+#ifndef int16_T
+#define int16_T int16_t
+#endif
+
+#ifndef UINT8_T
+#define UINT8_T uint8_t
+#endif
+
+#ifndef uint8_T
+#define uint8_T uint8_t
+#endif
+
+#ifndef INT8_T
+#define INT8_T int8_t
+#endif
+
+#ifndef int8_T
+#define int8_T int8_t
+#endif
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/mexproto.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,279 @@
+/*
+
+Copyright (C) 2006-2012 Paul Kienzle
+
+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/>.
+
+*/
+
+/*
+
+This code was originally distributed as part of Octave Forge under
+the following terms:
+
+Author: Paul Kienzle
+I grant this code to the public domain.
+2001-03-22
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+*/
+
+/* mex.h is for use in C-programs only; do NOT include it in mex.cc */
+
+#if ! defined (MEXPROTO_H)
+#define MEXPROTO_H
+
+#if defined (__cplusplus)
+#include <cstdlib>
+extern "C" {
+#else
+#include <stdlib.h>
+#endif
+
+/* The definition of OCTINTERP_API is normally provided by Octave's
+   config.h file.  This is provided for the case of mex.h included by
+   user programs that don't use Octave's config.h.  */
+#if ! defined (OCTINTERP_API)
+#if defined (_MSC_VER)
+#define OCTINTERP_API __declspec(dllimport)
+#else
+/* All other compilers, at least for now.  */
+#define OCTINTERP_API
+#endif
+#endif
+
+#define MXARRAY_TYPEDEFS_ONLY
+#include "mxarray.h"
+#undef MXARRAY_TYPEDEFS_ONLY
+
+/* Interface to the interpreter.  */
+extern OCTINTERP_API const char *mexFunctionName (void);
+
+extern OCTINTERP_API int mexCallMATLAB (int nargout, mxArray *argout[], int nargin, mxArray *argin[], const char *fname);
+
+extern OCTINTERP_API void mexSetTrapFlag (int flag);
+extern OCTINTERP_API int mexEvalString (const char *s);
+extern OCTINTERP_API void mexErrMsgTxt (const char *s);
+extern OCTINTERP_API void mexErrMsgIdAndTxt (const char *id, const char *s, ...);
+extern OCTINTERP_API void mexWarnMsgTxt (const char *s);
+extern OCTINTERP_API void mexWarnMsgIdAndTxt (const char *id, const char *s, ...);
+extern OCTINTERP_API int mexPrintf (const char *fmt, ...);
+
+extern OCTINTERP_API mxArray *mexGetVariable (const char *space, const char *name);
+extern OCTINTERP_API const mxArray *mexGetVariablePtr (const char *space, const char *name);
+
+extern OCTINTERP_API int mexPutVariable (const char *space, const char *name, mxArray *ptr);
+
+extern OCTINTERP_API void mexMakeArrayPersistent (mxArray *ptr);
+extern OCTINTERP_API void mexMakeMemoryPersistent (void *ptr);
+
+extern OCTINTERP_API int mexAtExit (void (*f) (void));
+extern OCTINTERP_API const mxArray *mexGet (double handle, const char *property);
+extern OCTINTERP_API int mexIsGlobal (const mxArray *ptr);
+extern OCTINTERP_API int mexIsLocked (void);
+extern OCTINTERP_API void mexLock (void);
+extern OCTINTERP_API int mexSet (double handle, const char *property, mxArray *val);
+extern OCTINTERP_API void mexUnlock (void);
+
+/* Floating point predicates.  */
+extern OCTINTERP_API int mxIsFinite (double v);
+extern OCTINTERP_API int mxIsInf (double v);
+extern OCTINTERP_API int mxIsNaN (double v);
+
+/* Floating point values.  */
+extern OCTINTERP_API double mxGetEps (void);
+extern OCTINTERP_API double mxGetInf (void);
+extern OCTINTERP_API double mxGetNaN (void);
+
+/* Memory management.  */
+extern OCTINTERP_API void *mxCalloc (size_t n, size_t size);
+extern OCTINTERP_API void *mxMalloc (size_t n);
+extern OCTINTERP_API void *mxRealloc (void *ptr, size_t size);
+extern OCTINTERP_API void mxFree (void *ptr);
+
+/* Constructors.  */
+extern OCTINTERP_API mxArray *mxCreateCellArray (mwSize ndims, const mwSize *dims);
+extern OCTINTERP_API mxArray *mxCreateCellMatrix (mwSize m, mwSize n);
+extern OCTINTERP_API mxArray *mxCreateCharArray (mwSize ndims, const mwSize *dims);
+extern OCTINTERP_API mxArray *mxCreateCharMatrixFromStrings (mwSize m, const char **str);
+extern OCTINTERP_API mxArray *mxCreateDoubleMatrix (mwSize nr, mwSize nc, mxComplexity flag);
+extern OCTINTERP_API mxArray *mxCreateDoubleScalar (double val);
+extern OCTINTERP_API mxArray *mxCreateLogicalArray (mwSize ndims, const mwSize *dims);
+extern OCTINTERP_API mxArray *mxCreateLogicalMatrix (mwSize m, mwSize n);
+extern OCTINTERP_API mxArray *mxCreateLogicalScalar (mxLogical val);
+extern OCTINTERP_API mxArray *mxCreateNumericArray (mwSize ndims, const mwSize *dims, mxClassID class_id, mxComplexity flag);
+extern OCTINTERP_API mxArray *mxCreateNumericMatrix (mwSize m, mwSize n, mxClassID class_id, mxComplexity flag);
+extern OCTINTERP_API mxArray *mxCreateSparse (mwSize m, mwSize n, mwSize nzmax, mxComplexity flag);
+extern OCTINTERP_API mxArray *mxCreateSparseLogicalMatrix (mwSize m, mwSize n, mwSize nzmax);
+extern OCTINTERP_API mxArray *mxCreateString (const char *str);
+extern OCTINTERP_API mxArray *mxCreateStructArray (mwSize ndims, const mwSize *dims, int num_keys, const char **keys);
+extern OCTINTERP_API mxArray *mxCreateStructMatrix (mwSize rows, mwSize cols, int num_keys, const char **keys);
+
+/* Copy constructor.  */
+extern OCTINTERP_API mxArray *mxDuplicateArray (const mxArray *v);
+
+/* Destructor.  */
+extern OCTINTERP_API void mxDestroyArray (mxArray *v);
+
+/* Type Predicates.  */
+extern OCTINTERP_API int mxIsCell (const mxArray *ptr);
+extern OCTINTERP_API int mxIsChar (const mxArray *ptr);
+extern OCTINTERP_API int mxIsClass (const mxArray *ptr, const char *name);
+extern OCTINTERP_API int mxIsComplex (const mxArray *ptr);
+extern OCTINTERP_API int mxIsDouble (const mxArray *ptr);
+extern OCTINTERP_API int mxIsFunctionHandle (const mxArray *ptr);
+extern OCTINTERP_API int mxIsInt16 (const mxArray *ptr);
+extern OCTINTERP_API int mxIsInt32 (const mxArray *ptr);
+extern OCTINTERP_API int mxIsInt64 (const mxArray *ptr);
+extern OCTINTERP_API int mxIsInt8 (const mxArray *ptr);
+extern OCTINTERP_API int mxIsLogical (const mxArray *ptr);
+extern OCTINTERP_API int mxIsNumeric (const mxArray *ptr);
+extern OCTINTERP_API int mxIsSingle (const mxArray *ptr);
+extern OCTINTERP_API int mxIsSparse (const mxArray *ptr);
+extern OCTINTERP_API int mxIsStruct (const mxArray *ptr);
+extern OCTINTERP_API int mxIsUint16 (const mxArray *ptr);
+extern OCTINTERP_API int mxIsUint32 (const mxArray *ptr);
+extern OCTINTERP_API int mxIsUint64 (const mxArray *ptr);
+extern OCTINTERP_API int mxIsUint8 (const mxArray *ptr);
+
+/* Odd type+size predicate.  */
+extern OCTINTERP_API int mxIsLogicalScalar (const mxArray *ptr);
+
+/* Odd type+size+value predicate.  */
+extern OCTINTERP_API int mxIsLogicalScalarTrue (const mxArray *ptr);
+
+/* Size predicate.  */
+extern OCTINTERP_API int mxIsEmpty (const mxArray *ptr);
+
+/* Just plain odd thing to ask of a value.  */
+extern OCTINTERP_API int mxIsFromGlobalWS (const mxArray *ptr);
+
+/* Dimension extractors.  */
+extern OCTINTERP_API size_t mxGetM (const mxArray *ptr);
+extern OCTINTERP_API size_t mxGetN (const mxArray *ptr);
+extern OCTINTERP_API mwSize *mxGetDimensions (const mxArray *ptr);
+extern OCTINTERP_API mwSize mxGetNumberOfDimensions (const mxArray *ptr);
+extern OCTINTERP_API size_t mxGetNumberOfElements (const mxArray *ptr);
+
+/* Dimension setters.  */
+extern OCTINTERP_API void mxSetM (mxArray *ptr, mwSize M);
+extern OCTINTERP_API void mxSetN (mxArray *ptr, mwSize N);
+extern OCTINTERP_API void mxSetDimensions (mxArray *ptr, const mwSize *dims, mwSize ndims);
+
+/* Data extractors.  */
+extern OCTINTERP_API double *mxGetPi (const mxArray *ptr);
+extern OCTINTERP_API double *mxGetPr (const mxArray *ptr);
+extern OCTINTERP_API double mxGetScalar (const mxArray *ptr);
+extern OCTINTERP_API mxChar *mxGetChars (const mxArray *ptr);
+extern OCTINTERP_API mxLogical *mxGetLogicals (const mxArray *ptr);
+extern OCTINTERP_API void *mxGetData (const mxArray *ptr);
+extern OCTINTERP_API void *mxGetImagData (const mxArray *ptr);
+
+/* Data setters.  */
+extern OCTINTERP_API void mxSetPr (mxArray *ptr, double *pr);
+extern OCTINTERP_API void mxSetPi (mxArray *ptr, double *pi);
+extern OCTINTERP_API void mxSetData (mxArray *ptr, void *data);
+extern OCTINTERP_API void mxSetImagData (mxArray *ptr, void *pi);
+
+/* Classes.  */
+extern OCTINTERP_API mxClassID mxGetClassID (const mxArray *ptr);
+extern OCTINTERP_API const char *mxGetClassName (const mxArray *ptr);
+
+extern OCTINTERP_API void mxSetClassName (mxArray *ptr, const char *name);
+
+/* Cell support.  */
+extern OCTINTERP_API mxArray *mxGetCell (const mxArray *ptr, mwIndex idx);
+
+extern OCTINTERP_API void mxSetCell (mxArray *ptr, mwIndex idx, mxArray *val);
+
+/* Sparse support.  */
+extern OCTINTERP_API mwIndex *mxGetIr (const mxArray *ptr);
+extern OCTINTERP_API mwIndex *mxGetJc (const mxArray *ptr);
+extern OCTINTERP_API mwSize mxGetNzmax (const mxArray *ptr);
+
+extern OCTINTERP_API void mxSetIr (mxArray *ptr, mwIndex *ir);
+extern OCTINTERP_API void mxSetJc (mxArray *ptr, mwIndex *jc);
+extern OCTINTERP_API void mxSetNzmax (mxArray *ptr, mwSize nzmax);
+
+/* Structure support.  */
+extern OCTINTERP_API int mxAddField (mxArray *ptr, const char *key);
+
+extern OCTINTERP_API void mxRemoveField (mxArray *ptr, int key_num);
+
+extern OCTINTERP_API mxArray *mxGetField (const mxArray *ptr, mwIndex index, const char *key);
+extern OCTINTERP_API mxArray *mxGetFieldByNumber (const mxArray *ptr, mwIndex index, int key_num);
+
+extern OCTINTERP_API void mxSetField (mxArray *ptr, mwIndex index, const char *key, mxArray *val);
+extern OCTINTERP_API void mxSetFieldByNumber (mxArray *ptr, mwIndex index, int key_num, mxArray *val);
+
+extern OCTINTERP_API int mxGetNumberOfFields (const mxArray *ptr);
+
+extern OCTINTERP_API const char *mxGetFieldNameByNumber (const mxArray *ptr, int key_num);
+extern OCTINTERP_API int mxGetFieldNumber (const mxArray *ptr, const char *key);
+
+extern OCTINTERP_API int mxGetString (const mxArray *ptr, char *buf, mwSize buflen);
+extern OCTINTERP_API char *mxArrayToString (const mxArray *ptr);
+
+/* Miscellaneous.  */
+#ifdef NDEBUG
+#define mxAssert(expr, msg) \
+  do \
+    { \
+      if (! expr) \
+        { \
+          mexPrintf ("Assertion failed: %s, at line %d of file \"%s\".\n%s\n", \
+                     #expr, __LINE__, __FILE__, msg); \
+        } \
+    } \
+  while (0)
+
+#define mxAssertS(expr, msg) \
+  do \
+    { \
+      if (! expr) \
+        { \
+          mexPrintf ("Assertion failed at line %d of file \"%s\".\n%s\n", \
+                     __LINE__, __FILE__, msg); \
+          abort (); \
+        } \
+    } \
+  while (0)
+#else
+#define mxAssert(expr, msg)
+#define mxAssertS(expr, msg)
+#endif
+
+extern OCTINTERP_API mwIndex mxCalcSingleSubscript (const mxArray *ptr, mwSize nsubs, mwIndex *subs);
+
+extern OCTINTERP_API size_t mxGetElementSize (const mxArray *ptr);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/module.mk	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,138 @@
+EXTRA_DIST += \
+  interp-core/module.mk \
+  interp-core/gl2ps.c \
+  interp-core/mxarray.in.h \
+  interp-core/oct-errno.in.cc
+
+JIT_INCLUDES = \
+  interp-core/jit-util.h \
+  interp-core/jit-typeinfo.h \
+  interp-core/jit-ir.h \
+  interp-core/pt-jit.h
+
+INTERP_CORE_INCLUDES = \
+  interp-core/Cell.h \
+  interp-core/c-file-ptr-stream.h \
+  interp-core/comment-list.h \
+  interp-core/cutils.h \
+  interp-core/defun-dld.h \
+  interp-core/defun-int.h \
+  interp-core/display.h \
+  interp-core/dynamic-ld.h \
+  interp-core/gl-render.h \
+  interp-core/gl2ps-renderer.h \
+  interp-core/gl2ps.h \
+  interp-core/gripes.h \
+  interp-core/jit-ir.h \
+  interp-core/jit-typeinfo.h \
+  interp-core/jit-util.h \
+  interp-core/ls-ascii-helper.h \
+  interp-core/ls-hdf5.h \
+  interp-core/ls-mat-ascii.h \
+  interp-core/ls-mat4.h \
+  interp-core/ls-mat5.h \
+  interp-core/ls-oct-binary.h \
+  interp-core/ls-utils.h \
+  interp-core/mex.h \
+  interp-core/mexproto.h \
+  interp-core/mxarray.in.h \
+  interp-core/oct-errno.h \
+  interp-core/oct-fstrm.h \
+  interp-core/oct-hdf5.h \
+  interp-core/oct-iostrm.h \
+  interp-core/oct-lvalue.h \
+  interp-core/oct-map.h \
+  interp-core/oct-obj.h \
+  interp-core/oct-prcstrm.h \
+  interp-core/oct-procbuf.h \
+  interp-core/oct-stdstrm.h \
+  interp-core/oct-stream.h \
+  interp-core/oct-strstrm.h \
+  interp-core/oct.h \
+  interp-core/procstream.h \
+  interp-core/pt-jit.h \
+  interp-core/siglist.h \
+  interp-core/sparse-xdiv.h \
+  interp-core/sparse-xpow.h \
+  interp-core/txt-eng-ft.h \
+  interp-core/txt-eng.h \
+  interp-core/unwind-prot.h \
+  interp-core/xdiv.h \
+  interp-core/xnorm.h \
+  interp-core/xpow.h \
+  interp-core/zfstream.h \
+	$(JIT_INCLUDES)
+
+JIT_SRC = \
+  interp-core/jit-util.cc \
+  interp-core/jit-typeinfo.cc \
+  interp-core/jit-ir.cc \
+  interp-core/pt-jit.cc
+
+C_INTERP_CORE_SRC = \
+  interp-core/cutils.c \
+  interp-core/matherr.c \
+  interp-core/siglist.c \
+  interp-core/xgl2ps.c
+
+INTERP_CORE_SRC = \
+  interp-core/Cell.cc \
+  interp-core/c-file-ptr-stream.cc \
+  interp-core/comment-list.cc \
+  interp-core/display.cc \
+  interp-core/dynamic-ld.cc \
+  interp-core/gl-render.cc \
+  interp-core/gl2ps-renderer.cc \
+  interp-core/gripes.cc \
+  interp-core/jit-ir.cc \
+  interp-core/jit-typeinfo.cc \
+  interp-core/jit-util.cc \
+  interp-core/ls-ascii-helper.cc \
+  interp-core/ls-hdf5.cc \
+  interp-core/ls-mat-ascii.cc \
+  interp-core/ls-mat4.cc \
+  interp-core/ls-mat5.cc \
+  interp-core/ls-oct-binary.cc \
+  interp-core/ls-utils.cc \
+  interp-core/mex.cc \
+  interp-core/oct-fstrm.cc \
+  interp-core/oct-iostrm.cc \
+  interp-core/oct-lvalue.cc \
+  interp-core/oct-map.cc \
+  interp-core/oct-obj.cc \
+  interp-core/oct-prcstrm.cc \
+  interp-core/oct-procbuf.cc \
+  interp-core/oct-stream.cc \
+  interp-core/oct-strstrm.cc \
+  interp-core/procstream.cc \
+  interp-core/pt-jit.cc \
+  interp-core/sparse-xdiv.cc \
+  interp-core/sparse-xpow.cc \
+  interp-core/txt-eng-ft.cc \
+  interp-core/unwind-prot.cc \
+  interp-core/xdiv.cc \
+  interp-core/xnorm.cc \
+  interp-core/xpow.cc \
+  interp-core/zfstream.cc \
+  $(JIT_SRC) \
+	$(C_INTERP_CORE_SRC)
+
+## FIXME: I don't believe this rule actually fires
+display.df display.lo: CPPFLAGS += $(X11_FLAGS)
+
+## Special rules for sources which must be built before rest of compilation.
+interp-core/oct-errno.cc: interp-core/oct-errno.in.cc Makefile
+	if test -n "$(PERL)"; then \
+	  $(srcdir)/mk-errno-list --perl "$(PERL)" < $< > $@-t; \
+	elif test -n "$(PYTHON)"; then \
+	  $(srcdir)/mk-errno-list --python "$(PYTHON)" < $< > $@-t; \
+	else \
+	  $(SED) '/@SYSDEP_ERRNO_LIST@/D' $< > $@-t; \
+	fi
+	mv $@-t $@
+
+interp-core/mxarray.h: interp-core/mxarray.in.h Makefile
+	$(SED) < $< \
+	  -e "s|%OCTAVE_IDX_TYPE%|${OCTAVE_IDX_TYPE}|" > $@-t
+	mv $@-t $@
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/mxarray.in.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,348 @@
+// DO NOT EDIT!  Generated automatically from mxarray.in.h by configure
+/*
+
+Copyright (C) 2001-2012 Paul Kienzle
+
+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/>.
+
+*/
+
+/*
+
+Part of this code was originally distributed as part of Octave Forge under
+the following terms:
+
+Author: Paul Kienzle
+I grant this code to the public domain.
+2001-03-22
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+*/
+
+#if ! defined (MXARRAY_H)
+#define MXARRAY_H
+
+typedef enum
+  {
+    mxREAL = 0,
+    mxCOMPLEX = 1
+  }
+  mxComplexity;
+
+typedef enum
+  {
+    mxUNKNOWN_CLASS = 0,
+    mxCELL_CLASS,
+    mxSTRUCT_CLASS,
+    mxLOGICAL_CLASS,
+    mxCHAR_CLASS,
+    mxUNUSED_CLASS,
+    mxDOUBLE_CLASS,
+    mxSINGLE_CLASS,
+    mxINT8_CLASS,
+    mxUINT8_CLASS,
+    mxINT16_CLASS,
+    mxUINT16_CLASS,
+    mxINT32_CLASS,
+    mxUINT32_CLASS,
+    mxINT64_CLASS,
+    mxUINT64_CLASS,
+    mxFUNCTION_CLASS
+  }
+  mxClassID;
+
+typedef unsigned char mxLogical;
+
+/* typedef Uint16 mxChar; */
+typedef char mxChar;
+
+/*
+ * FIXME? Mathworks says these should be size_t on 64-bit system and when
+ * mex is used with the -largearraydims flag, but why do that? Its better
+ * to conform to the same indexing as the rest of Octave
+ */
+typedef %OCTAVE_IDX_TYPE% mwSize;
+typedef %OCTAVE_IDX_TYPE% mwIndex;
+
+#if ! defined (MXARRAY_TYPEDEFS_ONLY)
+
+#include <cstring>
+
+class octave_value;
+
+#define DO_MUTABLE_METHOD(RET_T, METHOD_CALL) \
+  RET_T retval = rep->METHOD_CALL; \
+ \
+  if (rep->mutation_needed ()) \
+    { \
+      maybe_mutate (); \
+      retval = rep->METHOD_CALL; \
+    } \
+ \
+  return retval
+
+#define DO_VOID_MUTABLE_METHOD(METHOD_CALL) \
+  rep->METHOD_CALL; \
+ \
+  if (rep->mutation_needed ()) \
+    { \
+      maybe_mutate (); \
+      rep->METHOD_CALL; \
+    }
+
+// This just provides a way to avoid infinite recursion when building
+// mxArray objects.
+
+struct
+xmxArray
+{
+  xmxArray (void) { }
+};
+
+// The main interface class.  The representation can be based on an
+// octave_value object or a separate object that tries to reproduce
+// the semantics of mxArray objects in Matlab more directly.
+
+class mxArray
+{
+public:
+
+  mxArray (const octave_value& ov);
+
+  mxArray (mxClassID id, mwSize ndims, const mwSize *dims,
+           mxComplexity flag = mxREAL);
+
+  mxArray (mxClassID id, const dim_vector& dv, mxComplexity flag = mxREAL);
+
+  mxArray (mxClassID id, mwSize m, mwSize n, mxComplexity flag = mxREAL);
+
+  mxArray (mxClassID id, double val);
+
+  mxArray (mxClassID id, mxLogical val);
+
+  mxArray (const char *str);
+
+  mxArray (mwSize m, const char **str);
+
+  mxArray (mxClassID id, mwSize m, mwSize n, mwSize nzmax,
+           mxComplexity flag = mxREAL);
+
+  mxArray (mwSize ndims, const mwSize *dims, int num_keys, const char **keys);
+
+  mxArray (const dim_vector& dv, int num_keys, const char **keys);
+
+  mxArray (mwSize m, mwSize n, int num_keys, const char **keys);
+
+  mxArray (mwSize ndims, const mwSize *dims);
+
+  mxArray (const dim_vector& dv);
+
+  mxArray (mwSize m, mwSize n);
+
+  virtual mxArray *dup (void) const
+  {
+    mxArray *new_rep = rep->dup ();
+
+    return new mxArray (new_rep, name);
+  }
+
+  virtual ~mxArray (void);
+
+  virtual bool is_octave_value (void) const { return rep->is_octave_value (); }
+
+  virtual int is_cell (void) const { return rep->is_cell (); }
+
+  virtual int is_char (void) const { return rep->is_char (); }
+
+  virtual int is_class (const char *name_arg) const { return rep->is_class (name_arg); }
+
+  virtual int is_complex (void) const { return rep->is_complex (); }
+
+  virtual int is_double (void) const { return rep->is_double (); }
+
+  virtual int is_function_handle (void) const { return rep->is_function_handle (); }
+
+  virtual int is_int16 (void) const { return rep->is_int16 (); }
+
+  virtual int is_int32 (void) const { return rep->is_int32 (); }
+
+  virtual int is_int64 (void) const { return rep->is_int64 (); }
+
+  virtual int is_int8 (void) const { return rep->is_int8 (); }
+
+  virtual int is_logical (void) const { return rep->is_logical (); }
+
+  virtual int is_numeric (void) const { return rep->is_numeric (); }
+
+  virtual int is_single (void) const { return rep->is_single (); }
+
+  virtual int is_sparse (void) const { return rep->is_sparse (); }
+
+  virtual int is_struct (void) const { return rep->is_struct (); }
+
+  virtual int is_uint16 (void) const { return rep->is_uint16 (); }
+
+  virtual int is_uint32 (void) const { return rep->is_uint32 (); }
+
+  virtual int is_uint64 (void) const { return rep->is_uint64 (); }
+
+  virtual int is_uint8 (void) const { return rep->is_uint8 (); }
+
+  virtual int is_logical_scalar (void) const { return rep->is_logical_scalar (); }
+
+  virtual int is_logical_scalar_true (void) const { return rep->is_logical_scalar_true (); }
+
+  virtual mwSize get_m (void) const { return rep->get_m (); }
+
+  virtual mwSize get_n (void) const { return rep->get_n (); }
+
+  virtual mwSize *get_dimensions (void) const { return rep->get_dimensions (); }
+
+  virtual mwSize get_number_of_dimensions (void) const { return rep->get_number_of_dimensions (); }
+
+  virtual void set_m (mwSize m) { DO_VOID_MUTABLE_METHOD (set_m (m)); }
+
+  virtual void set_n (mwSize n) { DO_VOID_MUTABLE_METHOD (set_n (n)); }
+
+  virtual void set_dimensions (mwSize *dims_arg, mwSize ndims_arg) { DO_VOID_MUTABLE_METHOD (set_dimensions (dims_arg, ndims_arg)); }
+
+  virtual mwSize get_number_of_elements (void) const { return rep->get_number_of_elements (); }
+
+  virtual int is_empty (void) const { return get_number_of_elements () == 0; }
+
+  const char *get_name (void) const { return name; }
+
+  void set_name (const char *name_arg);
+
+  virtual mxClassID get_class_id (void) const { return rep->get_class_id (); }
+
+  virtual const char *get_class_name (void) const { return rep->get_class_name (); }
+
+  virtual void set_class_name (const char *name_arg) { DO_VOID_MUTABLE_METHOD (set_class_name (name_arg)); }
+
+  virtual mxArray *get_cell (mwIndex idx) const { DO_MUTABLE_METHOD (mxArray *, get_cell (idx)); }
+
+  virtual void set_cell (mwIndex idx, mxArray *val) { DO_VOID_MUTABLE_METHOD (set_cell (idx, val)); }
+
+  virtual double get_scalar (void) const { return rep->get_scalar (); }
+
+  virtual void *get_data (void) const { DO_MUTABLE_METHOD (void *, get_data ()); }
+
+  virtual void *get_imag_data (void) const { DO_MUTABLE_METHOD (void *, get_imag_data ()); }
+
+  virtual void set_data (void *pr) { DO_VOID_MUTABLE_METHOD (set_data (pr)); }
+
+  virtual void set_imag_data (void *pi) { DO_VOID_MUTABLE_METHOD (set_imag_data (pi)); }
+
+  virtual mwIndex *get_ir (void) const { DO_MUTABLE_METHOD (mwIndex *, get_ir ()); }
+
+  virtual mwIndex *get_jc (void) const { DO_MUTABLE_METHOD (mwIndex *, get_jc ()); }
+
+  virtual mwSize get_nzmax (void) const { return rep->get_nzmax (); }
+
+  virtual void set_ir (mwIndex *ir) { DO_VOID_MUTABLE_METHOD (set_ir (ir)); }
+
+  virtual void set_jc (mwIndex *jc) { DO_VOID_MUTABLE_METHOD (set_jc (jc)); }
+
+  virtual void set_nzmax (mwSize nzmax) { DO_VOID_MUTABLE_METHOD (set_nzmax (nzmax)); }
+
+  virtual int add_field (const char *key) { DO_MUTABLE_METHOD (int, add_field (key)); }
+
+  virtual void remove_field (int key_num) { DO_VOID_MUTABLE_METHOD (remove_field (key_num)); }
+
+  virtual mxArray *get_field_by_number (mwIndex index, int key_num) const { DO_MUTABLE_METHOD (mxArray *, get_field_by_number (index, key_num)); }
+
+  virtual void set_field_by_number (mwIndex index, int key_num, mxArray *val) { DO_VOID_MUTABLE_METHOD (set_field_by_number (index, key_num, val)); }
+
+  virtual int get_number_of_fields (void) const { return rep->get_number_of_fields (); }
+
+  virtual const char *get_field_name_by_number (int key_num) const { DO_MUTABLE_METHOD (const char*, get_field_name_by_number (key_num)); }
+
+  virtual int get_field_number (const char *key) const { DO_MUTABLE_METHOD (int, get_field_number (key)); }
+
+  virtual int get_string (char *buf, mwSize buflen) const { return rep->get_string (buf, buflen); }
+
+  virtual char *array_to_string (void) const { return rep->array_to_string (); }
+
+  virtual mwIndex calc_single_subscript (mwSize nsubs, mwIndex *subs) const { return rep->calc_single_subscript (nsubs, subs); }
+
+  virtual size_t get_element_size (void) const { return rep->get_element_size (); }
+
+  virtual bool mutation_needed (void) const { return rep->mutation_needed (); }
+
+  virtual mxArray *mutate (void) const { return rep->mutate (); }
+
+  static void *malloc (size_t n);
+
+  static void *calloc (size_t n, size_t t);
+
+  static char *strsave (const char *str)
+  {
+    char *retval = 0;
+
+    if (str)
+      {
+        mwSize sz =  sizeof (mxChar) * (strlen (str) + 1);
+        retval = static_cast<char *> (mxArray::malloc (sz));
+        strcpy (retval, str);
+      }
+
+    return retval;
+  }
+
+  static octave_value as_octave_value (mxArray *ptr);
+
+protected:
+
+  virtual octave_value as_octave_value (void) const;
+
+  mxArray (const xmxArray&) : rep (0), name (0) { }
+
+private:
+
+  mutable mxArray *rep;
+
+  char *name;
+
+  mxArray (mxArray *r, const char *n)
+    : rep (r), name (strsave (n)) { }
+
+  void maybe_mutate (void) const;
+
+  // No copying!
+
+  mxArray (const mxArray&);
+
+  mxArray& operator = (const mxArray&);
+};
+
+#undef DO_MUTABLE_METHOD
+#undef DO_VOID_MUTABLE_METHOD
+
+#endif
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/oct-errno.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,72 @@
+// oct-errno.h.in
+/*
+
+Copyright (C) 2005-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if !defined (octave_errno_h)
+#define octave_errno_h 1
+
+#include <cerrno>
+#include <map>
+#include <string>
+
+#include "oct-map.h"
+
+class
+octave_errno
+{
+protected:
+
+  octave_errno (void);
+
+public:
+
+  ~octave_errno (void) { }
+
+  static bool instance_ok (void);
+
+  static void cleanup_instance (void) { delete instance; instance = 0; }
+
+  static int lookup (const std::string& name);
+
+  static octave_scalar_map list (void);
+
+  static int get (void) { return errno; }
+
+  static int set (int val)
+  {
+    int retval = errno;
+    errno = val;
+    return retval;
+  }
+
+private:
+
+  std::map<std::string, int> errno_tbl;
+
+  static octave_errno *instance;
+
+  int do_lookup (const std::string& name);
+
+  octave_scalar_map do_list (void);
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/oct-errno.in.cc	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,345 @@
+// DO NOT EDIT!  Generated automatically from oct-errno.in.cc by configure
+/*
+
+Copyright (C) 2005-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <cerrno>
+
+#include "singleton-cleanup.h"
+
+#include "oct-errno.h"
+#include "oct-map.h"
+#include "error.h"
+
+octave_errno *octave_errno::instance = 0;
+
+octave_errno::octave_errno (void)
+{
+  struct errno_struct
+  {
+    const char *name;
+    int value;
+  };
+
+  static errno_struct errno_codes[] =
+  {
+    // POSIX.
+
+#if defined (E2BIG)
+    { "E2BIG", E2BIG, },
+#endif
+#if defined (EACCES)
+    { "EACCES", EACCES, },
+#endif
+#if defined (EADDRINUSE)
+    { "EADDRINUSE", EADDRINUSE, },
+#endif
+#if defined (EADDRNOTAVAIL)
+    { "EADDRNOTAVAIL", EADDRNOTAVAIL, },
+#endif
+#if defined (EAFNOSUPPORT)
+    { "EAFNOSUPPORT", EAFNOSUPPORT, },
+#endif
+#if defined (EAGAIN)
+    { "EAGAIN", EAGAIN, },
+#endif
+#if defined (EALREADY)
+    { "EALREADY", EALREADY, },
+#endif
+#if defined (EBADF)
+    { "EBADF", EBADF, },
+#endif
+#if defined (EBUSY)
+    { "EBUSY", EBUSY, },
+#endif
+#if defined (ECHILD)
+    { "ECHILD", ECHILD, },
+#endif
+#if defined (ECONNABORTED)
+    { "ECONNABORTED", ECONNABORTED, },
+#endif
+#if defined (ECONNREFUSED)
+    { "ECONNREFUSED", ECONNREFUSED, },
+#endif
+#if defined (ECONNRESET)
+    { "ECONNRESET", ECONNRESET, },
+#endif
+#if defined (EDEADLK)
+    { "EDEADLK", EDEADLK, },
+#endif
+#if defined (EDESTADDRREQ)
+    { "EDESTADDRREQ", EDESTADDRREQ, },
+#endif
+#if defined (EDOM)
+    { "EDOM", EDOM, },
+#endif
+#if defined (EDQUOT)
+    { "EDQUOT", EDQUOT, },
+#endif
+#if defined (EEXIST)
+    { "EEXIST", EEXIST, },
+#endif
+#if defined (EFAULT)
+    { "EFAULT", EFAULT, },
+#endif
+#if defined (EFBIG)
+    { "EFBIG", EFBIG, },
+#endif
+#if defined (EHOSTDOWN)
+    { "EHOSTDOWN", EHOSTDOWN, },
+#endif
+#if defined (EHOSTUNREACH)
+    { "EHOSTUNREACH", EHOSTUNREACH, },
+#endif
+#if defined (EINPROGRESS)
+    { "EINPROGRESS", EINPROGRESS, },
+#endif
+#if defined (EINTR)
+    { "EINTR", EINTR, },
+#endif
+#if defined (EINVAL)
+    { "EINVAL", EINVAL, },
+#endif
+#if defined (EIO)
+    { "EIO", EIO, },
+#endif
+#if defined (EISCONN)
+    { "EISCONN", EISCONN, },
+#endif
+#if defined (EISDIR)
+    { "EISDIR", EISDIR, },
+#endif
+#if defined (ELOOP)
+    { "ELOOP", ELOOP, },
+#endif
+#if defined (EMFILE)
+    { "EMFILE", EMFILE, },
+#endif
+#if defined (EMLINK)
+    { "EMLINK", EMLINK, },
+#endif
+#if defined (EMSGSIZE)
+    { "EMSGSIZE", EMSGSIZE, },
+#endif
+#if defined (ENAMETOOLONG)
+    { "ENAMETOOLONG", ENAMETOOLONG, },
+#endif
+#if defined (ENETDOWN)
+    { "ENETDOWN", ENETDOWN, },
+#endif
+#if defined (ENETRESET)
+    { "ENETRESET", ENETRESET, },
+#endif
+#if defined (ENETUNREACH)
+    { "ENETUNREACH", ENETUNREACH, },
+#endif
+#if defined (ENFILE)
+    { "ENFILE", ENFILE, },
+#endif
+#if defined (ENOBUFS)
+    { "ENOBUFS", ENOBUFS, },
+#endif
+#if defined (ENODEV)
+    { "ENODEV", ENODEV, },
+#endif
+#if defined (ENOENT)
+    { "ENOENT", ENOENT, },
+#endif
+#if defined (ENOEXEC)
+    { "ENOEXEC", ENOEXEC, },
+#endif
+#if defined (ENOLCK)
+    { "ENOLCK", ENOLCK, },
+#endif
+#if defined (ENOMEM)
+    { "ENOMEM", ENOMEM, },
+#endif
+#if defined (ENOPROTOOPT)
+    { "ENOPROTOOPT", ENOPROTOOPT, },
+#endif
+#if defined (ENOSPC)
+    { "ENOSPC", ENOSPC, },
+#endif
+#if defined (ENOSYS)
+    { "ENOSYS", ENOSYS, },
+#endif
+#if defined (ENOTBLK)
+    { "ENOTBLK", ENOTBLK, },
+#endif
+#if defined (ENOTCONN)
+    { "ENOTCONN", ENOTCONN, },
+#endif
+#if defined (ENOTDIR)
+    { "ENOTDIR", ENOTDIR, },
+#endif
+#if defined (ENOTEMPTY)
+    { "ENOTEMPTY", ENOTEMPTY, },
+#endif
+#if defined (ENOTSOCK)
+    { "ENOTSOCK", ENOTSOCK, },
+#endif
+#if defined (ENOTTY)
+    { "ENOTTY", ENOTTY, },
+#endif
+#if defined (ENXIO)
+    { "ENXIO", ENXIO, },
+#endif
+#if defined (EOPNOTSUPP)
+    { "EOPNOTSUPP", EOPNOTSUPP, },
+#endif
+#if defined (EPERM)
+    { "EPERM", EPERM, },
+#endif
+#if defined (EPFNOSUPPORT)
+    { "EPFNOSUPPORT", EPFNOSUPPORT, },
+#endif
+#if defined (EPIPE)
+    { "EPIPE", EPIPE, },
+#endif
+#if defined (EPROTONOSUPPORT)
+    { "EPROTONOSUPPORT", EPROTONOSUPPORT, },
+#endif
+#if defined (EPROTOTYPE)
+    { "EPROTOTYPE", EPROTOTYPE, },
+#endif
+#if defined (ERANGE)
+    { "ERANGE", ERANGE, },
+#endif
+#if defined (EREMOTE)
+    { "EREMOTE", EREMOTE, },
+#endif
+#if defined (ERESTART)
+    { "ERESTART", ERESTART, },
+#endif
+#if defined (EROFS)
+    { "EROFS", EROFS, },
+#endif
+#if defined (ESHUTDOWN)
+    { "ESHUTDOWN", ESHUTDOWN, },
+#endif
+#if defined (ESOCKTNOSUPPORT)
+    { "ESOCKTNOSUPPORT", ESOCKTNOSUPPORT, },
+#endif
+#if defined (ESPIPE)
+    { "ESPIPE", ESPIPE, },
+#endif
+#if defined (ESRCH)
+    { "ESRCH", ESRCH, },
+#endif
+#if defined (ESTALE)
+    { "ESTALE", ESTALE, },
+#endif
+#if defined (ETIMEDOUT)
+    { "ETIMEDOUT", ETIMEDOUT, },
+#endif
+#if defined (ETOOMANYREFS)
+    { "ETOOMANYREFS", ETOOMANYREFS, },
+#endif
+#if defined (ETXTBSY)
+    { "ETXTBSY", ETXTBSY, },
+#endif
+#if defined (EUSERS)
+    { "EUSERS", EUSERS, },
+#endif
+#if defined (EWOULDBLOCK)
+    { "EWOULDBLOCK", EWOULDBLOCK, },
+#endif
+#if defined (EXDEV)
+    { "EXDEV", EXDEV, },
+#endif
+
+    // Others (duplicates are OK).
+
+@SYSDEP_ERRNO_LIST@
+
+    { 0, 0, },
+  };
+
+  // Stuff them all in a map for fast access.
+
+  errno_struct *ptr = errno_codes;
+
+  while (ptr->name)
+    {
+      errno_tbl[ptr->name] = ptr->value;
+      ptr++;
+    }
+}
+
+bool
+octave_errno::instance_ok (void)
+{
+  bool retval = true;
+
+  if (! instance)
+    {
+      instance = new octave_errno ();
+
+      if (instance)
+        singleton_cleanup_list::add (cleanup_instance);
+    }
+
+  if (! instance)
+    {
+      ::error ("unable to create errno object!");
+
+      retval = false;
+    }
+
+  return retval;
+}
+
+int
+octave_errno::lookup (const std::string& name)
+{
+  return (instance_ok ()) ? instance->do_lookup (name) : -1;
+}
+
+octave_scalar_map
+octave_errno::list (void)
+{
+  return (instance_ok ()) ? instance->do_list () : octave_scalar_map ();
+}
+
+int
+octave_errno::do_lookup (const std::string& name)
+{
+  return (errno_tbl.find (name) != errno_tbl.end ()) ? errno_tbl[name] : -1;
+}
+
+octave_scalar_map
+octave_errno::do_list (void)
+{
+  octave_scalar_map retval;
+
+  for (std::map<std::string, int>::const_iterator p = errno_tbl.begin ();
+       p != errno_tbl.end ();
+       p++)
+    {
+      retval.assign (p->first, p->second);
+    }
+
+  return retval;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/oct-fstrm.cc	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,114 @@
+/*
+
+Copyright (C) 1996-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <cerrno>
+#include <cstring>
+
+#include "error.h"
+#include "oct-fstrm.h"
+
+octave_stream
+octave_fstream::create (const std::string& nm_arg, std::ios::openmode arg_md,
+                        oct_mach_info::float_format ff)
+{
+  return octave_stream (new octave_fstream (nm_arg, arg_md, ff));
+}
+
+octave_fstream::octave_fstream (const std::string& nm_arg,
+                                std::ios::openmode arg_md,
+                                oct_mach_info::float_format ff)
+  : octave_base_stream (arg_md, ff), nm (nm_arg)
+{
+
+#if CXX_ISO_COMPLIANT_LIBRARY
+
+  fs.open (nm.c_str (), arg_md);
+
+#else
+  // Override default protection of 0664 so that umask will appear to
+  // do the right thing.
+
+  fs.open (nm.c_str (), arg_md, 0666);
+
+#endif
+
+  if (! fs)
+    error (gnulib::strerror (errno));
+}
+
+// Position a stream at OFFSET relative to ORIGIN.
+
+int
+octave_fstream::seek (long, int)
+{
+  error ("fseek: invalid_operation");
+  return -1;
+}
+
+// Return current stream position.
+
+long
+octave_fstream::tell (void)
+{
+  error ("ftell: invalid_operation");
+  return -1;
+}
+
+// Return non-zero if EOF has been reached on this stream.
+
+bool
+octave_fstream::eof (void) const
+{
+  return fs.eof ();
+}
+
+void
+octave_fstream::do_close (void)
+{
+  fs.close ();
+}
+
+std::istream *
+octave_fstream::input_stream (void)
+{
+  std::istream *retval = 0;
+
+  if (mode () & std::ios::in)
+    retval = &fs;
+
+  return retval;
+}
+
+std::ostream *
+octave_fstream::output_stream (void)
+{
+  std::ostream *retval = 0;
+
+  if (mode () & std::ios::out)
+    retval = &fs;
+
+  return retval;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/oct-fstrm.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,86 @@
+/*
+
+Copyright (C) 1996-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if !defined (octave_octave_fstream_h)
+#define octave_octave_fstream_h 1
+
+#include <fstream>
+#include <string>
+
+#include "oct-stream.h"
+
+class
+octave_fstream : public octave_base_stream
+{
+public:
+
+  octave_fstream (const std::string& nm_arg,
+                  std::ios::openmode arg_md = std::ios::in|std::ios::out,
+                  oct_mach_info::float_format flt_fmt
+                    = oct_mach_info::native_float_format ());
+
+  static octave_stream
+  create (const std::string& nm_arg,
+          std::ios::openmode arg_md = std::ios::in|std::ios::out,
+          oct_mach_info::float_format flt_fmt
+            = oct_mach_info::native_float_format ());
+
+  // Position a stream at OFFSET relative to ORIGIN.
+
+  int seek (long offset, int origin);
+
+  // Return current stream position.
+
+  long tell (void);
+
+  // Return non-zero if EOF has been reached on this stream.
+
+  bool eof (void) const;
+
+  void do_close (void);
+
+  // The name of the file.
+
+  std::string name (void) const { return nm; }
+
+  std::istream *input_stream (void);
+
+  std::ostream *output_stream (void);
+
+protected:
+
+  ~octave_fstream (void) { }
+
+private:
+
+  std::string nm;
+
+  std::fstream fs;
+
+  // No copying!
+
+  octave_fstream (const octave_fstream&);
+
+  octave_fstream& operator = (const octave_fstream&);
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/oct-hdf5.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,30 @@
+/*
+
+Copyright (C) 2009-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if !defined (octave__hdf5_h)
+#define octave_hdf5_h 1
+
+#if defined (HAVE_HDF5)
+#include <hdf5.h>
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/oct-iostrm.cc	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,89 @@
+/*
+
+Copyright (C) 1996-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "error.h"
+#include "oct-iostrm.h"
+
+// Position a stream at OFFSET relative to ORIGIN.
+
+int
+octave_base_iostream::seek (long, int)
+{
+  invalid_operation ();
+  return -1;
+}
+
+// Return current stream position.
+
+long
+octave_base_iostream::tell (void)
+{
+  invalid_operation ();
+  return -1;
+}
+
+// Return non-zero if EOF has been reached on this stream.
+
+bool
+octave_base_iostream::eof (void) const
+{
+  invalid_operation ();
+  return false;
+}
+
+void
+octave_base_iostream::invalid_operation (void) const
+{
+  ::error ("%s: invalid operation", stream_type ());
+}
+
+// Return non-zero if EOF has been reached on this stream.
+
+bool
+octave_istream::eof (void) const
+{
+  return is && is->eof ();
+}
+
+octave_stream
+octave_istream::create (std::istream *arg, const std::string& n)
+{
+  return octave_stream (new octave_istream (arg, n));
+}
+
+// Return non-zero if EOF has been reached on this stream.
+
+bool
+octave_ostream::eof (void) const
+{
+  return os && os->eof ();
+}
+
+octave_stream
+octave_ostream::create (std::ostream *arg, const std::string& n)
+{
+  return octave_stream (new octave_ostream (arg, n));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/oct-iostrm.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,154 @@
+/*
+
+Copyright (C) 1996-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if !defined (octave_octave_iostream_h)
+#define octave_octave_iostream_h 1
+
+#include <iosfwd>
+
+#include "oct-stream.h"
+
+class
+octave_base_iostream : public octave_base_stream
+{
+public:
+
+  octave_base_iostream (const std::string& n = std::string (),
+                        std::ios::openmode m = std::ios::in|std::ios::out,
+                        oct_mach_info::float_format ff
+                          = oct_mach_info::native_float_format ())
+    : octave_base_stream (m, ff), nm (n) { }
+
+  // Position a stream at OFFSET relative to ORIGIN.
+
+  int seek (long offset, int origin);
+
+  // Return current stream position.
+
+  long tell (void);
+
+  // Return non-zero if EOF has been reached on this stream.
+
+  bool eof (void) const;
+
+  // The name of the file.
+
+  std::string name (void) const { return nm; }
+
+protected:
+
+  ~octave_base_iostream (void) { }
+
+  void invalid_operation (void) const;
+
+private:
+
+  std::string nm;
+
+  virtual const char *stream_type (void) const = 0;
+
+  // No copying!
+
+  octave_base_iostream (const octave_base_iostream&);
+
+  octave_base_iostream& operator = (const octave_base_iostream&);
+};
+
+class
+octave_istream : public octave_base_iostream
+{
+public:
+
+  octave_istream (std::istream *arg = 0, const std::string& n = std::string ())
+    : octave_base_iostream (n, std::ios::in,
+                            oct_mach_info::native_float_format ()),
+      is (arg)
+  { }
+
+  static octave_stream
+  create (std::istream *arg = 0, const std::string& n = std::string ());
+
+  // Return non-zero if EOF has been reached on this stream.
+
+  bool eof (void) const;
+
+  std::istream *input_stream (void) { return is; }
+
+  std::ostream *output_stream (void) { return 0; }
+
+protected:
+
+  ~octave_istream (void) { }
+
+private:
+
+  std::istream *is;
+
+  const char *stream_type (void) const { return "octave_istream"; }
+
+  // No copying!
+
+  octave_istream (const octave_istream&);
+
+  octave_istream& operator = (const octave_istream&);
+};
+
+class
+octave_ostream : public octave_base_iostream
+{
+public:
+
+  octave_ostream (std::ostream *arg, const std::string& n = std::string ())
+    : octave_base_iostream (n, std::ios::out,
+                            oct_mach_info::native_float_format ()),
+      os (arg)
+  { }
+
+  static octave_stream
+  create (std::ostream *arg, const std::string& n = std::string ());
+
+  // Return non-zero if EOF has been reached on this stream.
+
+  bool eof (void) const;
+
+  std::istream *input_stream (void) { return 0; }
+
+  std::ostream *output_stream (void) { return os; }
+
+protected:
+
+  ~octave_ostream (void) { }
+
+private:
+
+  std::ostream *os;
+
+  const char *stream_type (void) const { return "octave_ostream"; }
+
+  // No copying!
+
+  octave_ostream (const octave_ostream&);
+
+  octave_ostream& operator = (const octave_ostream&);
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/oct-lvalue.cc	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,94 @@
+/*
+
+Copyright (C) 1996-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "error.h"
+#include "oct-obj.h"
+#include "oct-lvalue.h"
+#include "ov.h"
+
+void
+octave_lvalue::assign (octave_value::assign_op op, const octave_value& rhs)
+{
+  if (val)
+    {
+      if (idx.empty ())
+        val->assign (op, rhs);
+      else
+        val->assign (op, type, idx, rhs);
+    }
+}
+
+void
+octave_lvalue::set_index (const std::string& t,
+                          const std::list<octave_value_list>& i)
+{
+  if (idx.empty ())
+    {
+      type = t;
+      idx = i;
+    }
+  else
+    error ("invalid index expression in assignment");
+}
+
+void
+octave_lvalue::do_unary_op (octave_value::unary_op op)
+{
+  if (val)
+    {
+      if (idx.empty ())
+        val->do_non_const_unary_op (op);
+      else
+        val->do_non_const_unary_op (op, type, idx);
+    }
+  else
+    error ("internal: invalid operation on ~");
+}
+
+octave_value
+octave_lvalue::value (void)
+{
+  octave_value retval;
+
+  if (val)
+    {
+      if (idx.empty ())
+        retval = *val;
+      else
+        {
+          if (val->is_constant ())
+            retval = val->subsref (type, idx);
+          else
+            {
+              octave_value_list t = val->subsref (type, idx, 1);
+              if (t.length () > 0)
+                retval = t(0);
+            }
+        }
+    }
+
+  return retval;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/oct-lvalue.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,104 @@
+/*
+
+Copyright (C) 1996-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if !defined (octave_lvalue_h)
+#define octave_lvalue_h 1
+
+class octave_value;
+class octave_value_list;
+
+#include <string>
+
+#include "oct-obj.h"
+#include "pt-idx.h"
+
+class
+octave_lvalue
+{
+public:
+
+  octave_lvalue (octave_value *v = 0)
+    : val (v), type (), idx (), nel (1)
+    { }
+
+  octave_lvalue (const octave_lvalue& vr)
+    : val (vr.val), type (vr.type), idx (vr.idx), nel (vr.nel)
+    {
+    }
+
+  octave_lvalue& operator = (const octave_lvalue& vr)
+    {
+      if (this != &vr)
+        {
+          val = vr.val;
+          type = vr.type;
+          idx = vr.idx;
+          nel = vr.nel;
+        }
+
+      return *this;
+    }
+
+  ~octave_lvalue (void) { }
+
+  bool is_black_hole (void) const { return val == 0; }
+
+  bool is_defined (void) const { return val && val->is_defined (); }
+
+  bool is_undefined (void) const { return ! val || val->is_undefined (); }
+
+  bool is_map (void) const { return val && val->is_map (); }
+
+  void define (const octave_value& v)
+    {
+      if (val)
+        *val = v;
+    }
+
+  void assign (octave_value::assign_op, const octave_value&);
+
+  void numel (octave_idx_type n) { nel = n; }
+
+  octave_idx_type numel (void) const { return nel; }
+
+  void set_index (const std::string& t, const std::list<octave_value_list>& i);
+
+  void clear_index (void) { type = std::string (); idx.clear (); }
+
+  void do_unary_op (octave_value::unary_op op);
+
+  octave_value value (void);
+
+  const octave_value *object (void) const { return val; }
+
+private:
+
+  octave_value *val;
+
+  std::string type;
+
+  std::list<octave_value_list> idx;
+
+  octave_idx_type nel;
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/oct-map.cc	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,1779 @@
+/*
+
+Copyright (C) 1995-2012 John W. Eaton
+Copyright (C) 2010 VZLU Prague
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "error.h"
+#include "str-vec.h"
+
+#include "oct-map.h"
+#include "utils.h"
+
+octave_fields::octave_fields (const string_vector& fields)
+  : rep (new fields_rep)
+{
+  octave_idx_type n = fields.numel ();
+  for (octave_idx_type i = 0; i < n; i++)
+    (*rep)[fields(i)] = i;
+}
+
+octave_fields::octave_fields (const char * const *fields)
+  : rep (new fields_rep)
+{
+  octave_idx_type n = 0;
+  while (*fields)
+    (*rep)[std::string (*fields++)] = n++;
+}
+
+bool
+octave_fields::isfield (const std::string& field) const
+{
+  return rep->find (field) != rep->end ();
+}
+
+octave_idx_type
+octave_fields::getfield (const std::string& field) const
+{
+  fields_rep::iterator p = rep->find (field);
+  return (p != rep->end ()) ? p->second : -1;
+}
+
+octave_idx_type
+octave_fields::getfield (const std::string& field)
+{
+  fields_rep::iterator p = rep->find (field);
+  if (p != rep->end ())
+    return p->second;
+  else
+    {
+      make_unique ();
+      octave_idx_type n = rep->size ();
+      return (*rep)[field] = n;
+    }
+}
+
+octave_idx_type
+octave_fields::rmfield (const std::string& field)
+{
+  fields_rep::iterator p = rep->find (field);
+  if (p == rep->end ())
+    return -1;
+  else
+    {
+      octave_idx_type n = p->second;
+      make_unique ();
+      rep->erase (field);
+      for (fields_rep::iterator q = rep->begin (); q != rep->end (); q++)
+        {
+          if (q->second >= n)
+            q->second--;
+        }
+
+      return n;
+    }
+}
+
+void
+octave_fields::orderfields (Array<octave_idx_type>& perm)
+{
+  octave_idx_type n = rep->size ();
+  perm.clear (n, 1);
+
+  make_unique ();
+  octave_idx_type i = 0;
+  for (fields_rep::iterator q = rep->begin (); q != rep->end (); q++)
+    {
+      octave_idx_type j = q->second;
+      q->second = i;
+      perm(i++) = j;
+    }
+}
+
+bool
+octave_fields::equal_up_to_order (const octave_fields& other,
+                                  octave_idx_type* perm) const
+{
+  bool retval = true;
+
+  iterator p = begin (), q = other.begin ();
+  for (; p != end () && q != other.end (); p++, q++)
+    {
+      if (p->first == q->first)
+        perm[p->second] = q->second;
+      else
+        {
+          retval = false;
+          break;
+        }
+    }
+
+  retval = (p == end () && q == other.end ());
+
+  return retval;
+}
+
+bool
+octave_fields::equal_up_to_order (const octave_fields& other,
+                                  Array<octave_idx_type>& perm) const
+{
+  octave_idx_type n = nfields ();
+  if (perm.length () != n)
+    perm.clear (1, n);
+
+  return equal_up_to_order (other, perm.fortran_vec ());
+}
+
+string_vector
+octave_fields::fieldnames (void) const
+{
+  octave_idx_type n = nfields ();
+  string_vector retval(n);
+
+  for (iterator p = begin (); p != end (); p++)
+    retval.xelem (p->second) = p->first;
+
+  return retval;
+}
+
+octave_value
+octave_scalar_map::getfield (const std::string& k) const
+{
+  octave_idx_type idx = xkeys.getfield (k);
+  return (idx >= 0) ? xvals[idx] : octave_value ();
+}
+
+void
+octave_scalar_map::setfield (const std::string& k, const octave_value& val)
+{
+  octave_idx_type idx = xkeys.getfield (k);
+  if (idx < static_cast<octave_idx_type> (xvals.size ()))
+    xvals[idx] = val;
+  else
+    xvals.push_back (val);
+}
+
+void
+octave_scalar_map::rmfield (const std::string& k)
+{
+  octave_idx_type idx = xkeys.rmfield (k);
+  if (idx >= 0)
+    xvals.erase (xvals.begin () + idx);
+}
+
+octave_scalar_map
+octave_scalar_map::orderfields (void) const
+{
+  Array<octave_idx_type> perm;
+  return orderfields (perm);
+}
+
+octave_scalar_map
+octave_scalar_map::orderfields (Array<octave_idx_type>& perm) const
+{
+  octave_scalar_map retval (xkeys);
+  retval.xkeys.orderfields (perm);
+
+  octave_idx_type nf = nfields ();
+  for (octave_idx_type i = 0; i < nf; i++)
+    retval.xvals[i] = xvals[perm.xelem (i)];
+
+  return retval;
+}
+
+octave_scalar_map
+octave_scalar_map::orderfields (const octave_scalar_map& other,
+                                Array<octave_idx_type>& perm) const
+{
+  if (xkeys.is_same (other.xkeys))
+    return *this;
+  else
+    {
+      octave_scalar_map retval (other.xkeys);
+      if (other.xkeys.equal_up_to_order (xkeys, perm))
+        {
+          octave_idx_type nf = nfields ();
+          for (octave_idx_type i = 0; i < nf; i++)
+            retval.xvals[i] = xvals[perm.xelem (i)];
+        }
+      else
+        error ("orderfields: structs must have same fields up to order");
+
+      return retval;
+    }
+}
+
+octave_value
+octave_scalar_map::contents (const std::string& k) const
+{
+  return getfield (k);
+}
+
+octave_value&
+octave_scalar_map::contents (const std::string& k)
+{
+  octave_idx_type idx = xkeys.getfield (k);
+  if (idx >= static_cast<octave_idx_type> (xvals.size ()))
+    xvals.resize (idx+1);
+  return xvals[idx];
+}
+
+octave_map::octave_map (const octave_scalar_map& m)
+  : xkeys (m.xkeys), xvals (), dimensions (1, 1)
+{
+  octave_idx_type nf = m.nfields ();
+  xvals.reserve (nf);
+  for (octave_idx_type i = 0; i < nf; i++)
+    {
+      xvals.push_back (Cell (dimensions));
+      xvals[i].xelem (0) = m.xvals[i];
+    }
+}
+
+octave_map::octave_map (const Octave_map& m)
+  : xkeys (m.keys ()), xvals (m.nfields ()), dimensions (m.dims ())
+{
+  for (iterator p = begin (); p != end (); p++)
+    contents(p) = m.contents (key (p));
+
+  optimize_dimensions ();
+}
+
+Cell
+octave_map::getfield (const std::string& k) const
+{
+  octave_idx_type idx = xkeys.getfield (k);
+  return (idx >= 0) ? xvals[idx] : Cell ();
+}
+
+void
+octave_map::setfield (const std::string& k, const Cell& val)
+{
+  if (nfields () == 0)
+    dimensions = val.dims ();
+
+  if (val.dims () == dimensions)
+    {
+      octave_idx_type idx = xkeys.getfield (k);
+      if (idx < static_cast<octave_idx_type> (xvals.size ()))
+        xvals[idx] = val;
+      else
+        xvals.push_back (val);
+    }
+  else
+    error ("octave_map::setfield: internal error");
+}
+
+void
+octave_map::rmfield (const std::string& k)
+{
+  octave_idx_type idx = xkeys.rmfield (k);
+  if (idx >= 0)
+    xvals.erase (xvals.begin () + idx);
+}
+
+octave_map
+octave_map::orderfields (void) const
+{
+  Array<octave_idx_type> perm;
+  return orderfields (perm);
+}
+
+octave_map
+octave_map::orderfields (Array<octave_idx_type>& perm) const
+{
+  octave_map retval (xkeys);
+  retval.xkeys.orderfields (perm);
+
+  octave_idx_type nf = nfields ();
+  for (octave_idx_type i = 0; i < nf; i++)
+    retval.xvals[i] = xvals[perm.xelem (i)];
+
+  return retval;
+}
+
+octave_map
+octave_map::orderfields (const octave_map& other,
+                         Array<octave_idx_type>& perm) const
+{
+  if (xkeys.is_same (other.xkeys))
+    return *this;
+  else
+    {
+      octave_map retval (other.xkeys);
+      if (other.xkeys.equal_up_to_order (xkeys, perm))
+        {
+          octave_idx_type nf = nfields ();
+          for (octave_idx_type i = 0; i < nf; i++)
+            retval.xvals[i] = xvals[perm.xelem (i)];
+        }
+      else
+        error ("orderfields: structs must have same fields up to order");
+
+      return retval;
+    }
+}
+
+Cell
+octave_map::contents (const std::string& k) const
+{
+  return getfield (k);
+}
+
+Cell&
+octave_map::contents (const std::string& k)
+{
+  octave_idx_type idx = xkeys.getfield (k);
+  if (idx >= static_cast<octave_idx_type> (xvals.size ()))
+    xvals.push_back (Cell (dimensions)); // auto-set correct dims.
+  return xvals[idx];
+}
+
+void
+octave_map::extract_scalar (octave_scalar_map& dest,
+                            octave_idx_type idx) const
+{
+  octave_idx_type nf = nfields ();
+  for (octave_idx_type i = 0; i < nf; i++)
+    dest.xvals[i] = xvals[i](idx);
+}
+
+octave_scalar_map
+octave_map::checkelem (octave_idx_type n) const
+{
+  octave_scalar_map retval (xkeys);
+
+  // Optimize this so that there is just one check.
+  extract_scalar (retval, compute_index (n, dimensions));
+
+  return retval;
+}
+
+octave_scalar_map
+octave_map::checkelem (octave_idx_type i, octave_idx_type j) const
+{
+  octave_scalar_map retval (xkeys);
+
+  // Optimize this so that there is just one check.
+  extract_scalar (retval, compute_index (i, j, dimensions));
+
+  return retval;
+}
+
+octave_scalar_map
+octave_map::checkelem (const Array<octave_idx_type>& ra_idx) const
+{
+  octave_scalar_map retval (xkeys);
+
+  // Optimize this so that there is just one check.
+  extract_scalar (retval, compute_index (ra_idx, dimensions));
+
+  return retval;
+}
+
+octave_scalar_map
+octave_map::fast_elem_extract (octave_idx_type n) const
+{
+  octave_scalar_map retval (xkeys);
+
+  extract_scalar (retval, n);
+
+  return retval;
+}
+
+bool
+octave_map::fast_elem_insert (octave_idx_type n,
+                              const octave_scalar_map& rhs)
+{
+  bool retval = false;
+
+  octave_idx_type nf = nfields ();
+  if (rhs.xkeys.is_same (xkeys))
+    {
+      for (octave_idx_type i = 0; i < nf; i++)
+        xvals[i](n) = rhs.xvals[i];
+
+      retval = true;
+    }
+  else
+    {
+      OCTAVE_LOCAL_BUFFER (octave_idx_type, perm, nf);
+      if (xkeys.equal_up_to_order (rhs.xkeys, perm))
+        {
+          for (octave_idx_type i = 0; i < nf; i++)
+            xvals[i](n) = rhs.xvals[perm[i]];
+
+          retval = true;
+        }
+    }
+
+  return retval;
+}
+
+octave_map
+octave_map::squeeze (void) const
+{
+  octave_map retval (*this);
+  octave_idx_type nf = nfields ();
+
+  retval.dimensions = dimensions.squeeze ();
+
+  for (octave_idx_type i = 0; i < nf; i++)
+    retval.xvals[i] = xvals[i].squeeze ();
+
+  retval.optimize_dimensions ();
+
+  return retval;
+}
+
+/*
+## test preservation of xkeys by squeeze
+%!test
+%! x(1,1,1,1).d = 10;  x(3,5,1,7).a = "b";  x(2,4,1,7).f = 27;
+%! assert (fieldnames (squeeze (x)), {"d"; "a"; "f"});
+*/
+
+octave_map
+octave_map::permute (const Array<int>& vec, bool inv) const
+{
+  octave_map retval (xkeys);
+  octave_idx_type nf = nfields ();
+
+  for (octave_idx_type i = 0; i < nf; i++)
+    retval.xvals[i] = xvals[i].permute (vec, inv);
+
+  // FIXME:
+  // There is no dim_vector::permute for technical reasons.
+  // We pick the dim vector from results if possible, otherwise use a dummy
+  // array to get it. Need (?) a better solution to this problem.
+  if (nf > 0)
+    retval.dimensions = retval.xvals[0].dims ();
+  else
+    {
+      Array<char> dummy (dimensions);
+      dummy = dummy.permute (vec, inv);
+      retval.dimensions = dummy.dims ();
+    }
+
+  retval.optimize_dimensions ();
+
+  return retval;
+}
+
+/*
+## test preservation of key order by permute
+%!test
+%! x(1,1,1,1).d = 10;  x(3,5,1,7).a = "b";  x(2,4,1,7).f = 27;
+%! assert (fieldnames (permute (x, [3, 4, 1, 2])), {"d"; "a"; "f"});
+*/
+
+octave_map
+octave_map::transpose (void) const
+{
+  assert (ndims () == 2);
+
+  octave_map retval (xkeys);
+
+  retval.dimensions = dim_vector (dimensions (1), dimensions (0));
+
+  octave_idx_type nf = nfields ();
+  for (octave_idx_type i = 0; i < nf; i++)
+    retval.xvals[i] = xvals[i].transpose ();
+
+  retval.optimize_dimensions ();
+
+  return retval;
+}
+
+/*
+## test preservation of key order by transpose
+%!test
+%! x(1,1).d = 10;  x(3,5).a = "b";  x(2,4).f = 27;
+%! assert (fieldnames (transpose (x)), {"d"; "a"; "f"});
+%! assert (fieldnames (x'), {"d"; "a"; "f"});
+%! assert (fieldnames (x.'), {"d"; "a"; "f"});
+*/
+
+octave_map
+octave_map::reshape (const dim_vector& dv) const
+{
+  octave_map retval (xkeys);
+  retval.dimensions = dv;
+
+  octave_idx_type nf = nfields ();
+  if (nf > 0)
+    {
+      retval.xvals.reserve (nf);
+      for (octave_idx_type i = 0; i < nf; i++)
+        retval.xvals[i] = xvals[i].reshape (dv);
+    }
+  else
+    {
+      // FIXME: Do it with a dummy array, to reuse error message.
+      // Need (?) a better solution.
+      Array<char> dummy (dimensions);
+      dummy.reshape (dv);
+    }
+
+  retval.optimize_dimensions ();
+
+  return retval;
+}
+
+/*
+## test preservation of key order by reshape
+%!test
+%! x(1,1).d = 10;  x(4,6).a = "b";  x(2,4).f = 27;
+%! assert (fieldnames (reshape (x, 3, 8)), {"d"; "a"; "f"});
+*/
+
+void
+octave_map::resize (const dim_vector& dv, bool fill)
+{
+  octave_idx_type nf = nfields ();
+  if (nf > 0)
+    {
+      for (octave_idx_type i = 0; i < nf; i++)
+        {
+          if (fill)
+            xvals[i].resize (dv, Matrix ());
+          else
+            xvals[i].resize (dv);
+        }
+    }
+  else
+    {
+      // FIXME: Do it with a dummy array, to reuse error message.
+      // Need (?) a better solution.
+      Array<char> dummy (dimensions);
+      dummy.resize (dv);
+    }
+
+  dimensions = dv;
+  optimize_dimensions ();
+}
+
+void
+octave_map::do_cat (int dim, octave_idx_type n, const octave_scalar_map *map_list,
+                    octave_map& retval)
+{
+  octave_idx_type nf = retval.nfields ();
+  retval.xvals.reserve (nf);
+
+  dim_vector& rd = retval.dimensions;
+  rd.resize (dim+1, 1);
+  rd(0) = rd(1) = 1;
+  rd(dim) = n;
+
+  for (octave_idx_type j = 0; j < nf; j++)
+    {
+      retval.xvals.push_back (Cell (rd));
+      assert (retval.xvals[j].numel () == n);
+      for (octave_idx_type i = 0; i < n; i++)
+        retval.xvals[j].xelem (i) = map_list[i].xvals[j];
+    }
+}
+
+void
+octave_map::do_cat (int dim, octave_idx_type n, const octave_map *map_list,
+                    octave_map& retval)
+{
+  octave_idx_type nf = retval.nfields ();
+  retval.xvals.reserve (nf);
+
+  OCTAVE_LOCAL_BUFFER (Array<octave_value>, field_list, n);
+
+  for (octave_idx_type j = 0; j < nf; j++)
+    {
+      for (octave_idx_type i = 0; i < n; i++)
+        field_list[i] = map_list[i].xvals[j];
+
+      retval.xvals.push_back (Array<octave_value>::cat (dim, n, field_list));
+      if (j == 0)
+        retval.dimensions = retval.xvals[j].dims ();
+    }
+}
+
+// This is just a wrapper.
+void permute_to_correct_order1 (const octave_scalar_map& ref, const octave_scalar_map& src,
+                                octave_scalar_map& dest, Array<octave_idx_type>& perm)
+{
+  dest = src.orderfields (ref, perm);
+}
+
+// In non-scalar case, we also promote empty structs without fields.
+void permute_to_correct_order1 (const octave_map& ref, const octave_map& src,
+                                octave_map& dest, Array<octave_idx_type>& perm)
+{
+  if (src.nfields () == 0 && src.is_empty ())
+     dest = octave_map (src.dims (), ref.keys ());
+  else
+     dest = src.orderfields (ref, perm);
+}
+
+template <class map>
+static void
+permute_to_correct_order (octave_idx_type n, octave_idx_type nf,
+                          octave_idx_type idx, const map *map_list,
+                          map *new_map_list)
+{
+  new_map_list[idx] = map_list[idx];
+
+  Array<octave_idx_type> perm (dim_vector (1, nf));
+
+  for (octave_idx_type i = 0; i < n; i++)
+    {
+      if (i == idx)
+         continue;
+
+      permute_to_correct_order1 (map_list[idx], map_list[i], new_map_list[i], perm);
+
+      if (error_state)
+        {
+          // Use liboctave exception to be consistent.
+          (*current_liboctave_error_handler)
+            ("cat: field names mismatch in concatenating structs");
+          break;
+        }
+    }
+}
+
+
+octave_map
+octave_map::cat (int dim, octave_idx_type n, const octave_scalar_map *map_list)
+{
+  octave_map retval;
+
+  // Allow dim = -1, -2 for compatibility, though it makes no difference here.
+  if (dim == -1 || dim == -2)
+    dim = -dim - 1;
+  else if (dim < 0)
+    (*current_liboctave_error_handler)
+      ("cat: invalid dimension");
+
+  if (n == 1)
+    retval = map_list[0];
+  else if (n > 1)
+    {
+      octave_idx_type idx, nf = 0;
+      for (idx = 0; idx < n; idx++)
+        {
+          nf = map_list[idx].nfields ();
+          if (nf > 0)
+            {
+              retval.xkeys = map_list[idx].xkeys;
+              break;
+            }
+        }
+
+      if (nf > 0)
+        {
+          // Try the fast case.
+          bool all_same = true;
+          for (octave_idx_type i = 0; i < n; i++)
+            {
+              all_same = map_list[idx].xkeys.is_same (map_list[i].xkeys);
+              if (! all_same)
+                break;
+            }
+
+          if (all_same)
+            do_cat (dim, n, map_list, retval);
+          else
+            {
+              // permute all structures to common order.
+              OCTAVE_LOCAL_BUFFER (octave_scalar_map, new_map_list, n);
+
+              permute_to_correct_order (n, nf, idx, map_list, new_map_list);
+
+              do_cat (dim, n, new_map_list, retval);
+            }
+
+        }
+      else
+        {
+          dim_vector& rd = retval.dimensions;
+          rd.resize (dim+1, 1);
+          rd(0) = rd(1) = 1;
+          rd(dim) = n;
+        }
+
+      retval.optimize_dimensions ();
+    }
+
+  return retval;
+}
+
+octave_map
+octave_map::cat (int dim, octave_idx_type n, const octave_map *map_list)
+{
+  octave_map retval;
+
+  // Allow dim = -1, -2 for compatibility, though it makes no difference here.
+  if (dim == -1 || dim == -2)
+    dim = -dim - 1;
+  else if (dim < 0)
+    (*current_liboctave_error_handler)
+      ("cat: invalid dimension");
+
+  if (n == 1)
+    retval = map_list[0];
+  else if (n > 1)
+    {
+      octave_idx_type idx, nf = 0;
+
+      for (idx = 0; idx < n; idx++)
+        {
+          nf = map_list[idx].nfields ();
+          if (nf > 0)
+            {
+              retval.xkeys = map_list[idx].xkeys;
+              break;
+            }
+        }
+
+      // Try the fast case.
+      bool all_same = true;
+
+      if (nf > 0)
+        {
+          for (octave_idx_type i = 0; i < n; i++)
+            {
+              all_same = map_list[idx].xkeys.is_same (map_list[i].xkeys);
+
+              if (! all_same)
+                break;
+            }
+        }
+
+      if (all_same && nf > 0)
+        do_cat (dim, n, map_list, retval);
+      else
+        {
+          if (nf > 0)
+            {
+              // permute all structures to correct order.
+              OCTAVE_LOCAL_BUFFER (octave_map, new_map_list, n);
+
+              permute_to_correct_order (n, nf, idx, map_list, new_map_list);
+
+              do_cat (dim, n, new_map_list, retval);
+            }
+          else
+            {
+              dim_vector dv = map_list[0].dimensions;
+
+              for (octave_idx_type i = 1; i < n; i++)
+                {
+                  if (! dv.concat (map_list[i].dimensions, dim))
+                    {
+                      error ("dimension mismatch in struct concatenation");
+                      return retval;
+                    }
+                }
+
+              retval.dimensions = dv;
+            }
+        }
+
+      retval.optimize_dimensions ();
+    }
+
+  return retval;
+}
+
+/*
+## test preservation of key order by concatenation
+%!test
+%! x(1, 1).d = 10;  x(4, 6).a = "b";  x(2, 4).f = 27;
+%! y(1, 6).f = 11;  y(1, 6).a = "c";  y(1, 6).d = 33;
+%! assert (fieldnames ([x; y]), {"d"; "a"; "f"});
+
+%!test
+%! s = struct ();
+%! sr = [s,s];
+%! sc = [s;s];
+%! sm = [s,s;s,s];
+%! assert (nfields (sr), 0);
+%! assert (nfields (sc), 0);
+%! assert (nfields (sm), 0);
+%! assert (size (sr), [1, 2]);
+%! assert (size (sc), [2, 1]);
+%! assert (size (sm), [2, 2]);
+*/
+
+octave_map
+octave_map::index (const idx_vector& i, bool resize_ok) const
+{
+  octave_map retval (xkeys);
+  octave_idx_type nf = nfields ();
+
+  for (octave_idx_type k = 0; k < nf; k++)
+    retval.xvals[k] = xvals[k].index (i, resize_ok);
+
+  if (nf > 0)
+    retval.dimensions = retval.xvals[0].dims ();
+  else
+    {
+      // Use dummy array. FIXME: Need(?) a better solution.
+      Array<char> dummy (dimensions);
+      dummy = dummy.index (i, resize_ok);
+      retval.dimensions = dummy.dims ();
+    }
+
+  retval.optimize_dimensions ();
+
+  return retval;
+}
+
+octave_map
+octave_map::index (const idx_vector& i, const idx_vector& j,
+                   bool resize_ok) const
+{
+  octave_map retval (xkeys);
+  octave_idx_type nf = nfields ();
+
+  for (octave_idx_type k = 0; k < nf; k++)
+    retval.xvals[k] = xvals[k].index (i, j, resize_ok);
+
+  if (nf > 0)
+    retval.dimensions = retval.xvals[0].dims ();
+  else
+    {
+      // Use dummy array. FIXME: Need(?) a better solution.
+      Array<char> dummy (dimensions);
+      dummy = dummy.index (i, j, resize_ok);
+      retval.dimensions = dummy.dims ();
+    }
+
+  retval.optimize_dimensions ();
+
+  return retval;
+}
+
+octave_map
+octave_map::index (const Array<idx_vector>& ia, bool resize_ok) const
+{
+  octave_map retval (xkeys);
+  octave_idx_type nf = nfields ();
+
+  for (octave_idx_type k = 0; k < nf; k++)
+    retval.xvals[k] = xvals[k].index (ia, resize_ok);
+
+  if (nf > 0)
+    retval.dimensions = retval.xvals[0].dims ();
+  else
+    {
+      // Use dummy array. FIXME: Need(?) a better solution.
+      Array<char> dummy (dimensions);
+      dummy = dummy.index (ia, resize_ok);
+      retval.dimensions = dummy.dims ();
+    }
+
+  retval.optimize_dimensions ();
+
+  return retval;
+}
+
+octave_map
+octave_map::index (const octave_value_list& idx, bool resize_ok) const
+{
+  octave_idx_type n_idx = idx.length ();
+  octave_map retval;
+
+  switch (n_idx)
+    {
+    case 1:
+      {
+        idx_vector i = idx(0).index_vector ();
+
+        if (! error_state)
+          retval = index (i, resize_ok);
+      }
+      break;
+
+    case 2:
+      {
+        idx_vector i = idx(0).index_vector ();
+
+        if (! error_state)
+          {
+            idx_vector j = idx(1).index_vector ();
+
+            retval = index (i, j, resize_ok);
+          }
+      }
+      break;
+
+    default:
+      {
+        Array<idx_vector> ia (dim_vector (n_idx, 1));
+
+        for (octave_idx_type i = 0; i < n_idx; i++)
+          {
+            ia(i) = idx(i).index_vector ();
+
+            if (error_state)
+              break;
+          }
+
+        if (! error_state)
+          retval = index (ia, resize_ok);
+      }
+      break;
+    }
+
+  return retval;
+}
+
+// Perhaps one day these will be optimized. Right now, they just call index.
+octave_map
+octave_map::column (octave_idx_type k) const
+{
+  return index (idx_vector::colon, k);
+}
+
+octave_map
+octave_map::page (octave_idx_type k) const
+{
+  static Array<idx_vector> ia (dim_vector (3, 1), idx_vector::colon);
+
+  ia(2) = k;
+  return index (ia);
+}
+
+void
+octave_map::assign (const idx_vector& i, const octave_map& rhs)
+{
+  if (rhs.xkeys.is_same (xkeys))
+    {
+      octave_idx_type nf = nfields ();
+
+      for (octave_idx_type k = 0; k < nf; k++)
+        xvals[k].assign (i, rhs.xvals[k], Matrix ());
+
+      if (nf > 0)
+        dimensions = xvals[0].dims ();
+      else
+        {
+          // Use dummy array. FIXME: Need(?) a better solution.
+          Array<char> dummy (dimensions), rhs_dummy (rhs.dimensions);
+          dummy.assign (i, rhs_dummy);;
+          dimensions = dummy.dims ();
+        }
+
+      optimize_dimensions ();
+    }
+  else if (nfields () == 0)
+    {
+      octave_map tmp (dimensions, rhs.xkeys);
+      tmp.assign (i, rhs);
+      *this = tmp;
+    }
+  else
+    {
+      Array<octave_idx_type> perm;
+      octave_map rhs1 = rhs.orderfields (*this, perm);
+      if (! error_state)
+        {
+          assert (rhs1.xkeys.is_same (xkeys));
+          assign (i, rhs1);
+        }
+      else
+        error ("incompatible fields in struct assignment");
+    }
+}
+
+void
+octave_map::assign (const idx_vector& i, const idx_vector& j,
+                    const octave_map& rhs)
+{
+  if (rhs.xkeys.is_same (xkeys))
+    {
+      octave_idx_type nf = nfields ();
+
+      for (octave_idx_type k = 0; k < nf; k++)
+        xvals[k].assign (i, j, rhs.xvals[k], Matrix ());
+
+      if (nf > 0)
+        dimensions = xvals[0].dims ();
+      else
+        {
+          // Use dummy array. FIXME: Need(?) a better solution.
+          Array<char> dummy (dimensions), rhs_dummy (rhs.dimensions);
+          dummy.assign (i, j, rhs_dummy);;
+          dimensions = dummy.dims ();
+        }
+
+      optimize_dimensions ();
+    }
+  else if (nfields () == 0)
+    {
+      octave_map tmp (dimensions, rhs.xkeys);
+      tmp.assign (i, j, rhs);
+      *this = tmp;
+    }
+  else
+    {
+      Array<octave_idx_type> perm;
+      octave_map rhs1 = rhs.orderfields (*this, perm);
+      if (! error_state)
+        {
+          assert (rhs1.xkeys.is_same (xkeys));
+          assign (i, j, rhs1);
+        }
+      else
+        error ("incompatible fields in struct assignment");
+    }
+}
+
+void
+octave_map::assign (const Array<idx_vector>& ia,
+                    const octave_map& rhs)
+{
+  if (rhs.xkeys.is_same (xkeys))
+    {
+      octave_idx_type nf = nfields ();
+
+      for (octave_idx_type k = 0; k < nf; k++)
+        xvals[k].assign (ia, rhs.xvals[k], Matrix ());
+
+      if (nf > 0)
+        dimensions = xvals[0].dims ();
+      else
+        {
+          // Use dummy array. FIXME: Need(?) a better solution.
+          Array<char> dummy (dimensions), rhs_dummy (rhs.dimensions);
+          dummy.assign (ia, rhs_dummy);;
+          dimensions = dummy.dims ();
+        }
+
+      optimize_dimensions ();
+    }
+  else if (nfields () == 0)
+    {
+      octave_map tmp (dimensions, rhs.xkeys);
+      tmp.assign (ia, rhs);
+      *this = tmp;
+    }
+  else
+    {
+      Array<octave_idx_type> perm;
+      octave_map rhs1 = rhs.orderfields (*this, perm);
+      if (! error_state)
+        {
+          assert (rhs1.xkeys.is_same (xkeys));
+          assign (ia, rhs1);
+        }
+      else
+        error ("incompatible fields in struct assignment");
+    }
+}
+
+void
+octave_map::assign (const octave_value_list& idx, const octave_map& rhs)
+{
+  octave_idx_type n_idx = idx.length ();
+
+  switch (n_idx)
+    {
+    case 1:
+      {
+        idx_vector i = idx(0).index_vector ();
+
+        if (! error_state)
+          assign (i, rhs);
+      }
+      break;
+
+    case 2:
+      {
+        idx_vector i = idx(0).index_vector ();
+
+        if (! error_state)
+          {
+            idx_vector j = idx(1).index_vector ();
+
+            assign (i, j, rhs);
+          }
+      }
+      break;
+
+    default:
+      {
+        Array<idx_vector> ia (dim_vector (n_idx, 1));
+
+        for (octave_idx_type i = 0; i < n_idx; i++)
+          {
+            ia(i) = idx(i).index_vector ();
+
+            if (error_state)
+              break;
+          }
+
+        if (! error_state)
+          assign (ia, rhs);
+      }
+      break;
+    }
+}
+
+void
+octave_map::assign (const octave_value_list& idx, const std::string& k,
+                    const Cell& rhs)
+{
+  Cell tmp;
+  iterator p = seek (k);
+  Cell& ref = p != end () ? contents (p) : tmp;
+
+  if (&ref == &tmp)
+    ref = Cell (dimensions);
+
+  ref.assign (idx, rhs);
+
+  if (! error_state && ref.dims () != dimensions)
+    {
+      dimensions = ref.dims ();
+
+      octave_idx_type nf = nfields ();
+      for (octave_idx_type i = 0; i < nf; i++)
+        {
+          if (&xvals[i] != &ref)
+            xvals[i].resize (dimensions, Matrix ());
+        }
+
+      optimize_dimensions ();
+    }
+
+  if (! error_state && &ref == &tmp)
+    setfield (k, tmp);
+}
+
+/*
+%!test
+%! rhs.b = 1;
+%! a(3) = rhs;
+%! assert ({a.b}, {[], [], 1})
+*/
+
+void
+octave_map::delete_elements (const idx_vector& i)
+{
+  octave_idx_type nf = nfields ();
+  for (octave_idx_type k = 0; k < nf; k++)
+    xvals[k].delete_elements (i);
+
+  if (nf > 0)
+    dimensions = xvals[0].dims ();
+  else
+    {
+      // Use dummy array. FIXME: Need(?) a better solution.
+      Array<char> dummy (dimensions);
+      dummy.delete_elements (i);
+      dimensions = dummy.dims ();
+    }
+
+  optimize_dimensions ();
+}
+
+void
+octave_map::delete_elements (int dim, const idx_vector& i)
+{
+  octave_idx_type nf = nfields ();
+  for (octave_idx_type k = 0; k < nf; k++)
+    xvals[k].delete_elements (dim, i);
+
+  if (nf > 0)
+    dimensions = xvals[0].dims ();
+  else
+    {
+      // Use dummy array. FIXME: Need(?) a better solution.
+      Array<char> dummy (dimensions);
+      dummy.delete_elements (dim, i);
+      dimensions = dummy.dims ();
+    }
+
+  optimize_dimensions ();
+}
+
+void
+octave_map::delete_elements (const Array<idx_vector>& ia)
+{
+  octave_idx_type nf = nfields ();
+  for (octave_idx_type k = 0; k < nf; k++)
+    xvals[k].delete_elements (ia);
+
+  if (nf > 0)
+    dimensions = xvals[0].dims ();
+  else
+    {
+      // Use dummy array. FIXME: Need(?) a better solution.
+      Array<char> dummy (dimensions);
+      dummy.delete_elements (ia);
+      dimensions = dummy.dims ();
+    }
+
+  optimize_dimensions ();
+}
+
+void
+octave_map::delete_elements (const octave_value_list& idx)
+{
+  octave_idx_type n_idx = idx.length ();
+
+  Array<idx_vector> ia (dim_vector (n_idx, 1));
+
+  for (octave_idx_type i = 0; i < n_idx; i++)
+    {
+      ia(i) = idx(i).index_vector ();
+
+      if (error_state)
+        break;
+    }
+
+  if (! error_state)
+    delete_elements (ia);
+}
+
+/*
+## test preservation of key order by indexing
+%!test
+%! x(1, 1).d = 10;  x(4, 6).a = "b";  x(2, 4).f = 27;
+%! assert (fieldnames (x([1, 2], [2:5])), {"d"; "a"; "f"});
+*/
+
+octave_map
+octave_map::concat (const octave_map& rb, const Array<octave_idx_type>& ra_idx)
+{
+  if (nfields () == rb.nfields ())
+    {
+      for (const_iterator pa = begin (); pa != end (); pa++)
+        {
+          const_iterator pb = rb.seek (key(pa));
+
+          if (pb == rb.end ())
+            {
+              error ("field name mismatch in structure concatenation");
+              break;
+            }
+
+          contents(pa).insert (rb.contents (pb), ra_idx);
+        }
+    }
+  else
+    {
+      dim_vector dv = dims ();
+
+      if (dv.all_zero ())
+        *this = rb;
+      else if (! rb.dims ().all_zero ())
+        error ("invalid structure concatenation");
+    }
+
+  return *this;
+}
+
+void
+octave_map::optimize_dimensions (void)
+{
+  octave_idx_type nf = nfields ();
+
+  for (octave_idx_type i = 0; i < nf; i++)
+    {
+      if (! xvals[i].optimize_dimensions (dimensions))
+        {
+          error ("internal error: dimension mismatch across fields in struct");
+          break;
+        }
+    }
+
+}
+
+Octave_map::Octave_map (const dim_vector& dv, const Cell& key_vals)
+  : map (), key_list (), dimensions (dv)
+{
+  Cell c (dv);
+
+  if (key_vals.is_cellstr ())
+    {
+      for (octave_idx_type i = 0; i < key_vals.numel (); i++)
+        {
+          std::string k = key_vals(i).string_value ();
+          map[k] = c;
+          key_list.push_back (k);
+        }
+    }
+  else
+    error ("Octave_map: expecting keys to be cellstr");
+}
+
+Octave_map::Octave_map (const octave_map& m)
+  : map (), key_list (), dimensions (m.dims ())
+{
+  for (octave_map::const_iterator p = m.begin (); p != m.end (); p++)
+    map[m.key (p)] = m.contents (p);
+  const string_vector mkeys = m.fieldnames ();
+  for (octave_idx_type i = 0; i < mkeys.numel (); i++)
+    key_list.push_back (mkeys(i));
+}
+
+Octave_map
+Octave_map::squeeze (void) const
+{
+  Octave_map retval (dims ().squeeze ());
+
+  for (const_iterator pa = begin (); pa != end (); pa++)
+    {
+      Cell tmp = contents (pa).squeeze ();
+
+      if (error_state)
+        break;
+
+      retval.assign (key (pa), tmp);
+    }
+
+  // Preserve order of keys.
+  retval.key_list = key_list;
+
+  return retval;
+}
+
+Octave_map
+Octave_map::permute (const Array<int>& vec, bool inv) const
+{
+  Octave_map retval (dims ());
+
+  for (const_iterator pa = begin (); pa != end (); pa++)
+    {
+      Cell tmp = contents (pa).permute (vec, inv);
+
+      if (error_state)
+        break;
+
+      retval.assign (key (pa), tmp);
+    }
+
+  // Preserve order of keys.
+  retval.key_list = key_list;
+
+  return retval;
+}
+
+Cell&
+Octave_map::contents (const std::string& k)
+{
+  maybe_add_to_key_list (k);
+
+  return map[k];
+}
+
+Cell
+Octave_map::contents (const std::string& k) const
+{
+  const_iterator p = seek (k);
+
+  return p != end () ? p->second : Cell ();
+}
+
+int
+Octave_map::intfield (const std::string& k, int def_val) const
+{
+  int retval = def_val;
+
+  Cell c = contents (k);
+
+  if (! c.is_empty ())
+    retval = c(0).int_value ();
+
+  return retval;
+}
+
+std::string
+Octave_map::stringfield (const std::string& k,
+                         const std::string& def_val) const
+{
+  std::string retval = def_val;
+
+  Cell c = contents (k);
+
+  if (! c.is_empty ())
+    retval = c(0).string_value ();
+
+  return retval;
+}
+
+string_vector
+Octave_map::keys (void) const
+{
+  assert (static_cast<size_t>(nfields ()) == key_list.size ());
+
+  return string_vector (key_list);
+}
+
+Octave_map
+Octave_map::transpose (void) const
+{
+  assert (ndims () == 2);
+
+  dim_vector dv = dims ();
+
+  octave_idx_type nr = dv(0);
+  octave_idx_type nc = dv(1);
+
+  dim_vector new_dims (nc, nr);
+
+  Octave_map retval (new_dims);
+
+  for (const_iterator p = begin (); p != end (); p++)
+    retval.assign (key(p), Cell (contents(p).transpose ()));
+
+  // Preserve order of keys.
+  retval.key_list = key_list;
+
+  return retval;
+}
+
+Octave_map
+Octave_map::reshape (const dim_vector& new_dims) const
+{
+  Octave_map retval;
+
+  if (new_dims != dims ())
+    {
+      for (const_iterator p = begin (); p != end (); p++)
+        retval.assign (key(p), contents(p).reshape (new_dims));
+
+      retval.dimensions = new_dims;
+
+      // Preserve order of keys.
+      retval.key_list = key_list;
+    }
+  else
+    retval = *this;
+
+  return retval;
+}
+
+void
+Octave_map::resize (const dim_vector& dv, bool fill)
+{
+  if (dv != dims ())
+    {
+      if (nfields () == 0)
+        dimensions = dv;
+      else
+        {
+          for (const_iterator p = begin (); p != end (); p++)
+            {
+              Cell tmp = contents(p);
+
+              if (fill)
+                tmp.resize (dv, Matrix ());
+              else
+                tmp.resize (dv);
+
+              dimensions = dv;
+
+              assign (key(p), tmp);
+            }
+        }
+    }
+}
+
+Octave_map
+Octave_map::concat (const Octave_map& rb, const Array<octave_idx_type>& ra_idx)
+{
+  Octave_map retval;
+
+  if (nfields () == rb.nfields ())
+    {
+      for (const_iterator pa = begin (); pa != end (); pa++)
+        {
+          const_iterator pb = rb.seek (key(pa));
+
+          if (pb == rb.end ())
+            {
+              error ("field name mismatch in structure concatenation");
+              break;
+            }
+
+          retval.assign (key(pa),
+                         contents(pa).insert (rb.contents(pb), ra_idx));
+        }
+
+      // Preserve order of keys.
+      retval.key_list = key_list;
+    }
+  else
+    {
+      dim_vector dv = dims ();
+
+      if (dv.all_zero ())
+        retval = rb;
+      else
+        {
+          dv = rb.dims ();
+
+          if (dv.all_zero ())
+            retval = *this;
+          else
+            error ("invalid structure concatenation");
+        }
+    }
+
+  return retval;
+}
+
+static bool
+keys_ok (const Octave_map& a, const Octave_map& b, string_vector& keys)
+{
+  bool retval = false;
+
+  keys = string_vector ();
+
+  if (a.nfields () == 0)
+    {
+      keys = b.keys ();
+      retval = true;
+    }
+  else
+    {
+      string_vector a_keys = a.keys ().sort ();
+      string_vector b_keys = b.keys ().sort ();
+
+      octave_idx_type a_len = a_keys.length ();
+      octave_idx_type b_len = b_keys.length ();
+
+      if (a_len == b_len)
+        {
+          for (octave_idx_type i = 0; i < a_len; i++)
+            {
+              if (a_keys[i] != b_keys[i])
+                goto done;
+            }
+
+          keys = a_keys;
+          retval = true;
+        }
+    }
+
+ done:
+  return retval;
+}
+
+Octave_map&
+Octave_map::maybe_delete_elements (const octave_value_list& idx)
+{
+  string_vector t_keys = keys ();
+  octave_idx_type len = t_keys.length ();
+
+  if (len > 0)
+    {
+      for (octave_idx_type i = 0; i < len; i++)
+        {
+          std::string k = t_keys[i];
+
+          contents(k).delete_elements (idx);
+
+          if (error_state)
+            break;
+        }
+
+      if (!error_state)
+        dimensions = contents(t_keys[0]).dims ();
+    }
+
+  return *this;
+}
+
+Octave_map&
+Octave_map::assign (const octave_value_list& idx, const Octave_map& rhs)
+{
+  string_vector t_keys;
+
+  if (keys_ok (*this, rhs, t_keys))
+    {
+      octave_idx_type len = t_keys.length ();
+
+      if (len == 0)
+        {
+          Cell tmp_lhs (dims ());
+          Cell tmp_rhs (rhs.dims ());
+
+          tmp_lhs.assign (idx, tmp_rhs, Matrix ());
+
+          if (! error_state)
+            resize (tmp_lhs.dims ());
+          else
+            error ("size mismatch in structure assignment");
+        }
+      else
+        {
+          for (octave_idx_type i = 0; i < len; i++)
+            {
+              std::string k = t_keys[i];
+
+              Cell t_rhs = rhs.contents (k);
+
+              assign (idx, k, t_rhs);
+
+              if (error_state)
+                break;
+            }
+        }
+    }
+  else
+    error ("field name mismatch in structure assignment");
+
+  return *this;
+}
+
+Octave_map&
+Octave_map::assign (const octave_value_list& idx, const std::string& k,
+                    const Cell& rhs)
+{
+  Cell tmp;
+
+  if (contains (k))
+    tmp = map[k];
+  else
+    tmp = Cell (dimensions);
+
+  tmp.assign (idx, rhs);
+
+  if (! error_state)
+    {
+      dim_vector tmp_dims = tmp.dims ();
+
+      if (tmp_dims != dimensions)
+        {
+          for (iterator p = begin (); p != end (); p++)
+            contents(p).resize (tmp_dims, Matrix ());
+
+          dimensions = tmp_dims;
+        }
+
+      maybe_add_to_key_list (k);
+
+      map[k] = tmp;
+    }
+
+  return *this;
+}
+
+Octave_map&
+Octave_map::assign (const std::string& k, const octave_value& rhs)
+{
+  if (nfields () == 0)
+    {
+      maybe_add_to_key_list (k);
+
+      map[k] = Cell (rhs);
+
+      dimensions = dim_vector (1, 1);
+    }
+  else
+    {
+      dim_vector dv = dims ();
+
+      if (dv.all_ones ())
+        {
+          maybe_add_to_key_list (k);
+
+          map[k] = Cell (rhs);
+        }
+      else
+        error ("invalid structure assignment");
+    }
+
+  return *this;
+}
+
+Octave_map&
+Octave_map::assign (const std::string& k, const Cell& rhs)
+{
+  if (nfields () == 0)
+    {
+      maybe_add_to_key_list (k);
+
+      map[k] = rhs;
+
+      dimensions = rhs.dims ();
+    }
+  else
+    {
+      if (dims () == rhs.dims ())
+        {
+          maybe_add_to_key_list (k);
+
+          map[k] = rhs;
+        }
+      else
+        error ("invalid structure assignment");
+    }
+
+  return *this;
+}
+
+Octave_map
+Octave_map::index (const octave_value_list& idx, bool resize_ok) const
+{
+  Octave_map retval;
+
+  octave_idx_type n_idx = idx.length ();
+
+  if (n_idx > 0)
+    {
+      Array<idx_vector> ra_idx (dim_vector (n_idx, 1));
+
+      for (octave_idx_type i = 0; i < n_idx; i++)
+        {
+          ra_idx(i) = idx(i).index_vector ();
+          if (error_state)
+            break;
+        }
+
+      if (! error_state)
+        {
+          for (const_iterator p = begin (); p != end (); p++)
+            {
+              Cell tmp = contents (p);
+
+              tmp = tmp.Array<octave_value>::index (ra_idx, resize_ok);
+
+              if (error_state)
+                break;
+
+              retval.assign (key(p), tmp);
+            }
+
+          // Preserve order of keys.
+          retval.key_list = key_list;
+        }
+    }
+  else
+    retval = *this;
+
+  return retval;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/oct-map.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,659 @@
+/*
+
+Copyright (C) 1994-2012 John W. Eaton
+Copyright (C) 2010 VZLU Prague
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if !defined (octave_oct_map_h)
+#define octave_oct_map_h 1
+
+#include <algorithm>
+#include <map>
+
+#include "Cell.h"
+#include "oct-obj.h"
+
+class string_vector;
+
+// A class holding a map field->index. Supports reference-counting.
+class OCTINTERP_API
+octave_fields
+{
+  class fields_rep : public std::map<std::string, octave_idx_type>
+  {
+  public:
+    fields_rep (void) : std::map<std::string, octave_idx_type> (), count (1) { }
+    fields_rep (const fields_rep& other)
+      : std::map<std::string, octave_idx_type> (other), count (1) { }
+
+    octave_refcount<int> count;
+
+  private:
+    fields_rep& operator = (const fields_rep&); // no assignment!
+  };
+
+  fields_rep *rep;
+
+  static fields_rep *nil_rep (void)
+    {
+      static fields_rep nr;
+      return &nr;
+    }
+
+public:
+
+  octave_fields (void) : rep (nil_rep ()) { rep->count++; }
+  octave_fields (const string_vector&);
+  octave_fields (const char * const *);
+
+  ~octave_fields (void)
+    {
+      if (--rep->count == 0)
+        delete rep;
+    }
+
+  void make_unique (void)
+    {
+      if (rep->count > 1)
+        {
+          fields_rep *r = new fields_rep (*rep);
+
+          if (--rep->count == 0)
+            delete rep;
+
+          rep = r;
+        }
+    }
+
+  octave_fields (const octave_fields& o) : rep (o.rep) { rep->count++; }
+
+  octave_fields&
+  operator = (const octave_fields& o)
+    {
+      o.rep->count++;
+      if (--rep->count == 0)
+        delete rep;
+      rep = o.rep;
+
+      return *this;
+    }
+
+  // constant iteration support. non-const iteration intentionally unsupported.
+
+  typedef std::map<std::string, octave_idx_type>::const_iterator const_iterator;
+  typedef const_iterator iterator;
+
+  const_iterator begin (void) const { return rep->begin (); }
+  const_iterator end (void) const { return rep->end (); }
+
+  std::string key (const_iterator p) const { return p->first; }
+  octave_idx_type index (const_iterator p) const { return p->second; }
+
+  const_iterator seek (const std::string& k) const
+    { return rep->find (k); }
+
+  // high-level methods.
+
+  // number of fields.
+  octave_idx_type nfields (void) const { return rep->size (); }
+
+  // check whether a field exists.
+  bool isfield (const std::string& name) const;
+
+  // get index of field. return -1 if not exist
+  octave_idx_type getfield (const std::string& name) const;
+  // get index of field. add if not exist
+  octave_idx_type getfield (const std::string& name);
+  // remove field and return the index. -1 if didn't exist.
+  octave_idx_type rmfield (const std::string& name);
+
+  // order the fields of this map. creates a permutation
+  // used to order the fields.
+  void orderfields (Array<octave_idx_type>& perm);
+
+  // compares two instances for equality up to order of fields.
+  // returns a permutation needed to bring the fields of *other*
+  // into the order of *this*.
+  bool equal_up_to_order (const octave_fields& other,
+                          octave_idx_type* perm) const;
+
+  bool equal_up_to_order (const octave_fields& other,
+                          Array<octave_idx_type>& perm) const;
+
+  bool is_same (const octave_fields& other) const
+    { return rep == other.rep; }
+
+  // Returns the fields as a vector of strings.
+  string_vector fieldnames (void) const;
+
+  void clear (void)
+    {
+      *this = octave_fields ();
+    }
+};
+
+
+class OCTINTERP_API
+octave_scalar_map
+{
+public:
+
+  octave_scalar_map (const octave_fields& k)
+    : xkeys (k), xvals (k.nfields ()) { }
+
+  octave_scalar_map (void) : xkeys (), xvals () { }
+
+  octave_scalar_map (const string_vector& k)
+    : xkeys (k), xvals (k.length ()) { }
+
+  octave_scalar_map (const octave_scalar_map& m)
+    : xkeys (m.xkeys), xvals(m.xvals) { }
+
+  octave_scalar_map& operator = (const octave_scalar_map& m)
+    {
+      xkeys = m.xkeys;
+      xvals = m.xvals;
+
+      return *this;
+    }
+
+  // iteration support. note that both const and non-const iterators are the
+  // same. The const/non-const distinction is made by the key & contents method.
+  typedef octave_fields::const_iterator const_iterator;
+  typedef const_iterator iterator;
+
+  const_iterator begin (void) const { return xkeys.begin (); }
+  const_iterator end (void) const { return xkeys.end (); }
+
+  const_iterator seek (const std::string& k) const { return xkeys.seek (k); }
+
+  std::string key (const_iterator p) const
+    { return xkeys.key (p); }
+  octave_idx_type index (const_iterator p) const
+    { return xkeys.index (p); }
+
+  const octave_value& contents (const_iterator p) const
+    { return xvals[xkeys.index (p)]; }
+
+  octave_value& contents (iterator p)
+    { return xvals[xkeys.index (p)]; }
+
+  const octave_value& contents (octave_idx_type i) const
+    { return xvals[i]; }
+
+  octave_value& contents (octave_idx_type i)
+    { return xvals[i]; }
+
+  // number of fields.
+  octave_idx_type nfields (void) const { return xkeys.nfields (); }
+
+  // check whether a field exists.
+  bool isfield (const std::string& name) const
+    { return xkeys.isfield (name); }
+
+  bool contains (const std::string& name) const
+    { return isfield (name); }
+
+  string_vector fieldnames (void) const
+    { return xkeys.fieldnames (); }
+
+  string_vector keys (void) const
+    { return fieldnames (); }
+
+  // get contents of a given field. empty value if not exist.
+  octave_value getfield (const std::string& key) const;
+
+  // set contents of a given field. add if not exist.
+  void setfield (const std::string& key, const octave_value& val);
+  void assign (const std::string& k, const octave_value& val)
+    { setfield (k, val); }
+
+  // remove a given field. do nothing if not exist.
+  void rmfield (const std::string& key);
+  void del (const std::string& k) { rmfield (k); }
+
+  // return a copy with fields ordered, optionally along with permutation.
+  octave_scalar_map orderfields (void) const;
+  octave_scalar_map orderfields (Array<octave_idx_type>& perm) const;
+  octave_scalar_map orderfields (const octave_scalar_map& other,
+                                 Array<octave_idx_type>& perm) const;
+
+  // aka getfield/setfield, but the latter returns a reference.
+  octave_value contents (const std::string& k) const;
+  octave_value& contents (const std::string& k);
+
+  void clear (void)
+    {
+      xkeys.clear ();
+      xvals.clear ();
+    }
+
+  friend class octave_map;
+
+private:
+
+  octave_fields xkeys;
+  std::vector<octave_value> xvals;
+
+};
+
+template<>
+inline octave_scalar_map octave_value_extract<octave_scalar_map> (const octave_value& v)
+  { return v.scalar_map_value (); }
+
+class OCTINTERP_API
+octave_map
+{
+public:
+
+  octave_map (const octave_fields& k)
+    : xkeys (k), xvals (k.nfields ()), dimensions () { }
+
+  octave_map (const dim_vector& dv, const octave_fields& k)
+    : xkeys (k), xvals (k.nfields (), Cell (dv)), dimensions (dv) { }
+
+  typedef octave_scalar_map element_type;
+
+  octave_map (void) : xkeys (), xvals (), dimensions () { }
+
+  octave_map (const dim_vector& dv) : xkeys (), xvals (), dimensions (dv) { }
+
+  octave_map (const string_vector& k)
+    : xkeys (k), xvals (k.length (), Cell (1, 1)), dimensions (1, 1) { }
+
+  octave_map (const dim_vector& dv, const string_vector& k)
+    : xkeys (k), xvals (k.length (), Cell (dv)), dimensions (dv) { }
+
+  octave_map (const octave_map& m)
+    : xkeys (m.xkeys), xvals (m.xvals), dimensions (m.dimensions) { }
+
+  octave_map (const octave_scalar_map& m);
+
+  octave_map (const Octave_map& m);
+
+  octave_map& operator = (const octave_map& m)
+    {
+      xkeys = m.xkeys;
+      xvals = m.xvals;
+      dimensions = m.dimensions;
+
+      return *this;
+    }
+
+  // iteration support. note that both const and non-const iterators are the
+  // same. The const/non-const distinction is made by the key & contents method.
+  typedef octave_fields::const_iterator const_iterator;
+  typedef const_iterator iterator;
+
+  const_iterator begin (void) const { return xkeys.begin (); }
+  const_iterator end (void) const { return xkeys.end (); }
+
+  const_iterator seek (const std::string& k) const { return xkeys.seek (k); }
+
+  std::string key (const_iterator p) const
+    { return xkeys.key (p); }
+  octave_idx_type index (const_iterator p) const
+    { return xkeys.index (p); }
+
+  const Cell& contents (const_iterator p) const
+    { return xvals[xkeys.index (p)]; }
+
+  Cell& contents (iterator p)
+    { return xvals[xkeys.index (p)]; }
+
+  const Cell& contents (octave_idx_type i) const
+    { return xvals[i]; }
+
+  Cell& contents (octave_idx_type i)
+    { return xvals[i]; }
+
+  // number of fields.
+  octave_idx_type nfields (void) const { return xkeys.nfields (); }
+
+  // check whether a field exists.
+  bool isfield (const std::string& name) const
+    { return xkeys.isfield (name); }
+
+  bool contains (const std::string& name) const
+    { return isfield (name); }
+
+  string_vector fieldnames (void) const
+    { return xkeys.fieldnames (); }
+
+  string_vector keys (void) const
+    { return fieldnames (); }
+
+  // get contents of a given field. empty value if not exist.
+  Cell getfield (const std::string& key) const;
+
+  // set contents of a given field. add if not exist. checks for
+  // correct dimensions.
+  void setfield (const std::string& key, const Cell& val);
+  void assign (const std::string& k, const Cell& val)
+    { setfield (k, val); }
+
+  // remove a given field. do nothing if not exist.
+  void rmfield (const std::string& key);
+  void del (const std::string& k) { rmfield (k); }
+
+  // return a copy with fields ordered, optionally along with permutation.
+  octave_map orderfields (void) const;
+  octave_map orderfields (Array<octave_idx_type>& perm) const;
+  octave_map orderfields (const octave_map& other,
+                          Array<octave_idx_type>& perm) const;
+
+  // aka getfield/setfield, but the latter returns a reference.
+  Cell contents (const std::string& k) const;
+  Cell& contents (const std::string& k);
+
+  void clear (void)
+    {
+      xkeys.clear ();
+      xvals.clear ();
+    }
+
+  // The Array-like methods.
+  octave_idx_type numel (void) const { return dimensions.numel (); }
+  octave_idx_type length (void) const { return numel (); }
+  bool is_empty (void) const { return dimensions.any_zero (); }
+
+  octave_idx_type rows (void) const { return dimensions(0); }
+  octave_idx_type cols (void) const { return dimensions(1); }
+  octave_idx_type columns (void) const { return dimensions(1); }
+
+  // Extract a scalar substructure.
+  octave_scalar_map checkelem (octave_idx_type n) const;
+  octave_scalar_map checkelem (octave_idx_type i, octave_idx_type j) const;
+
+  octave_scalar_map
+  checkelem (const Array<octave_idx_type>& ra_idx) const;
+
+  octave_scalar_map operator () (octave_idx_type n) const
+    { return checkelem (n); }
+  octave_scalar_map operator () (octave_idx_type i, octave_idx_type j) const
+    { return checkelem (i, j); }
+
+  octave_scalar_map
+  operator () (const Array<octave_idx_type>& ra_idx) const
+    { return checkelem (ra_idx); }
+
+  octave_map squeeze (void) const;
+
+  octave_map permute (const Array<int>& vec, bool inv = false) const;
+
+  dim_vector dims (void) const { return dimensions; }
+
+  int ndims (void) const { return dimensions.length (); }
+
+  octave_map transpose (void) const;
+
+  octave_map reshape (const dim_vector& dv) const;
+
+  void resize (const dim_vector& dv, bool fill = false);
+
+  static octave_map
+  cat (int dim, octave_idx_type n, const octave_scalar_map *map_list);
+
+  static octave_map
+  cat (int dim, octave_idx_type n, const octave_map *map_list);
+
+  octave_map index (const idx_vector& i, bool resize_ok = false) const;
+
+  octave_map index (const idx_vector& i, const idx_vector& j,
+                    bool resize_ok = false) const;
+
+  octave_map index (const Array<idx_vector>& ia,
+                    bool resize_ok = false) const;
+
+  octave_map index (const octave_value_list&, bool resize_ok = false) const;
+
+  octave_map column (octave_idx_type k) const;
+  octave_map page (octave_idx_type k) const;
+
+  void assign (const idx_vector& i, const octave_map& rhs);
+
+  void assign (const idx_vector& i, const idx_vector& j, const octave_map& rhs);
+
+  void assign (const Array<idx_vector>& ia, const octave_map& rhs);
+
+  void assign (const octave_value_list&, const octave_map& rhs);
+
+  void assign (const octave_value_list& idx, const std::string& k,
+               const Cell& rhs);
+
+  void delete_elements (const idx_vector& i);
+
+  void delete_elements (int dim, const idx_vector& i);
+
+  void delete_elements (const Array<idx_vector>& ia);
+
+  void delete_elements (const octave_value_list&);
+
+  octave_map concat (const octave_map& rb, const Array<octave_idx_type>& ra_idx);
+
+  // like checkelem, but no check.
+  octave_scalar_map fast_elem_extract (octave_idx_type n) const;
+
+  // element assignment, no bounds check
+  bool fast_elem_insert (octave_idx_type n, const octave_scalar_map& rhs);
+
+private:
+
+  octave_fields xkeys;
+  std::vector<Cell> xvals;
+  dim_vector dimensions;
+
+  void optimize_dimensions (void);
+  void extract_scalar (octave_scalar_map& dest,
+                       octave_idx_type index) const;
+  static void do_cat (int dim, octave_idx_type n,
+                      const octave_scalar_map *map_list, octave_map& retval);
+  static void do_cat (int dim, octave_idx_type n,
+                      const octave_map *map_list, octave_map& retval);
+};
+
+template<>
+inline octave_map octave_value_extract<octave_map> (const octave_value& v)
+  { return v.map_value (); }
+
+// The original Octave_map object. Octave_map and octave_map are convertible to
+// each other.
+
+class
+OCTINTERP_API
+Octave_map
+{
+ public:
+
+  typedef std::map<std::string, Cell>::iterator iterator;
+  typedef std::map<std::string, Cell>::const_iterator const_iterator;
+
+  typedef std::list<std::string>::iterator key_list_iterator;
+  typedef std::list<std::string>::const_iterator const_key_list_iterator;
+
+  // Warning!  You should always use at least two dimensions.
+
+  Octave_map (const dim_vector& dv = dim_vector (0, 0),
+              const Cell& key_vals = Cell ());
+
+  Octave_map (const std::string& k, const octave_value& value)
+    : map (), key_list (), dimensions (1, 1)
+  {
+    map[k] = value;
+    key_list.push_back (k);
+  }
+
+  Octave_map (const string_vector& sv,
+              const dim_vector& dv = dim_vector (0, 0))
+    : map (), key_list (), dimensions (dv)
+  {
+    for (octave_idx_type i = 0; i < sv.length (); i++)
+      {
+        std::string k = sv[i];
+        map[k] = Cell (dv);
+        key_list.push_back (k);
+      }
+  }
+
+  Octave_map (const std::string& k, const Cell& vals)
+    : map (), key_list (), dimensions (vals.dims ())
+  {
+    map[k] = vals;
+    key_list.push_back (k);
+  }
+
+  Octave_map (const std::string& k, const octave_value_list& val_list)
+    : map (), key_list (), dimensions (1, val_list.length ())
+  {
+    map[k] = val_list;
+    key_list.push_back (k);
+  }
+
+  Octave_map (const Octave_map& m)
+    : map (m.map), key_list (m.key_list), dimensions (m.dimensions) { }
+
+  Octave_map (const octave_map& m);
+
+  Octave_map& operator = (const Octave_map& m)
+    {
+      if (this != &m)
+        {
+          map = m.map;
+          key_list = m.key_list;
+          dimensions = m.dimensions;
+        }
+
+      return *this;
+    }
+
+  ~Octave_map (void) { }
+
+  Octave_map squeeze (void) const;
+
+  Octave_map permute (const Array<int>& vec, bool inv = false) const;
+
+  // This is the number of keys.
+  octave_idx_type nfields (void) const { return map.size (); }
+
+  void del (const std::string& k)
+    {
+      iterator p = map.find (k);
+
+      if (p != map.end ())
+        {
+          map.erase (p);
+
+          key_list_iterator q
+            = std::find (key_list.begin (), key_list.end (), k);
+
+          assert (q != key_list.end ());
+
+          key_list.erase (q);
+        }
+    }
+
+  iterator begin (void) { return iterator (map.begin ()); }
+  const_iterator begin (void) const { return const_iterator (map.begin ()); }
+
+  iterator end (void) { return iterator (map.end ()); }
+  const_iterator end (void) const { return const_iterator (map.end ()); }
+
+  std::string key (const_iterator p) const { return p->first; }
+
+  Cell& contents (const std::string& k);
+  Cell contents (const std::string& k) const;
+
+  Cell& contents (iterator p)
+    { return p->second; }
+
+  Cell contents (const_iterator p) const
+    { return p->second; }
+
+  int intfield (const std::string& k, int def_val = 0) const;
+
+  std::string stringfield (const std::string& k,
+                           const std::string& def_val = std::string ()) const;
+
+  iterator seek (const std::string& k) { return map.find (k); }
+  const_iterator seek (const std::string& k) const { return map.find (k); }
+
+  bool contains (const std::string& k) const
+    { return (seek (k) != map.end ()); }
+
+  void clear (void)
+    {
+      map.clear ();
+      key_list.clear ();
+    }
+
+  string_vector keys (void) const;
+
+  octave_idx_type rows (void) const { return dimensions(0); }
+
+  octave_idx_type columns (void) const { return dimensions(1); }
+
+  dim_vector dims (void) const { return dimensions; }
+
+  int ndims (void) const { return dimensions.length (); }
+
+  Octave_map transpose (void) const;
+
+  Octave_map reshape (const dim_vector& new_dims) const;
+
+  void resize (const dim_vector& dv, bool fill = false);
+
+  octave_idx_type numel (void) const { return dimensions.numel (); }
+
+  Octave_map concat (const Octave_map& rb, const Array<octave_idx_type>& ra_idx);
+
+  Octave_map& maybe_delete_elements (const octave_value_list& idx);
+
+  Octave_map& assign (const octave_value_list& idx, const Octave_map& rhs);
+
+  Octave_map& assign (const octave_value_list& idx, const std::string& k,
+                      const Cell& rhs);
+
+  Octave_map& assign (const std::string& k, const octave_value& rhs);
+
+  Octave_map& assign (const std::string& k, const Cell& rhs);
+
+  Octave_map index (const octave_value_list& idx,
+                    bool resize_ok = false) const;
+
+private:
+
+  // The map of names to values.
+  std::map<std::string, Cell> map;
+
+  // An extra list of keys, so we can keep track of the order the keys
+  // are added for compatibility with you know what.
+  std::list<std::string> key_list;
+
+  // The current size.
+  mutable dim_vector dimensions;
+
+  void maybe_add_to_key_list (const std::string& k)
+    {
+      if (! contains (k))
+        key_list.push_back (k);
+    }
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/oct-obj.cc	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,284 @@
+/*
+
+Copyright (C) 1994-2012 John W. Eaton
+Copyright (C) 2009 VZLU Prague
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "error.h"
+#include "oct-obj.h"
+#include "Cell.h"
+
+// We are likely to have a lot of octave_value_list objects to allocate,
+// so make the grow_size large.
+DEFINE_OCTAVE_ALLOCATOR2(octave_value_list, 1024);
+
+octave_value_list::octave_value_list (const std::list<octave_value_list>& lst)
+{
+  octave_idx_type n = 0, nel = 0;
+
+  // Determine number.
+  for (std::list<octave_value_list>::const_iterator p = lst.begin ();
+       p != lst.end (); p++)
+    {
+      n++;
+      nel += p->length ();
+    }
+
+  // Optimize single-element case
+  if (n == 1)
+    data = lst.front ().data;
+  else if (nel > 0)
+    {
+      data.resize (dim_vector (1, nel));
+      octave_idx_type k = 0;
+      for (std::list<octave_value_list>::const_iterator p = lst.begin ();
+           p != lst.end (); p++)
+        {
+          data.assign (idx_vector (k, k + p->length ()), p->data);
+          k += p->length ();
+        }
+      assert (k == nel);
+    }
+
+}
+
+octave_value_list&
+octave_value_list::prepend (const octave_value& val)
+{
+  octave_idx_type n = length ();
+
+  resize (n + 1);
+
+  while (n > 0)
+    {
+      elem (n) = elem (n - 1);
+      n--;
+    }
+
+  elem (0) = val;
+
+  return *this;
+}
+
+octave_value_list&
+octave_value_list::append (const octave_value& val)
+{
+  octave_idx_type n = length ();
+
+  resize (n + 1);
+
+  elem (n) = val;
+
+  return *this;
+}
+
+octave_value_list&
+octave_value_list::append (const octave_value_list& lst)
+{
+  octave_idx_type len = length ();
+  octave_idx_type lst_len = lst.length ();
+
+  resize (len + lst_len);
+
+  for (octave_idx_type i = 0; i < lst_len; i++)
+    elem (len + i) = lst (i);
+
+  return *this;
+}
+
+octave_value_list&
+octave_value_list::reverse (void)
+{
+  octave_idx_type n = length ();
+
+  for (octave_idx_type i = 0; i < n / 2; i++)
+    {
+      octave_value tmp = elem (i);
+      elem (i) = elem (n - i - 1);
+      elem (n - i - 1) = tmp;
+    }
+
+  return *this;
+}
+
+octave_value_list
+octave_value_list::splice (octave_idx_type offset, octave_idx_type rep_length,
+                           const octave_value_list& lst) const
+{
+  octave_value_list retval;
+
+  octave_idx_type len = length ();
+
+  if (offset < 0 || offset >= len)
+    {
+      if (! (rep_length == 0 && offset == len))
+        {
+          error ("octave_value_list::splice: invalid OFFSET");
+          return retval;
+        }
+    }
+
+  if (rep_length < 0 || rep_length + offset > len)
+    {
+      error ("octave_value_list::splice: invalid LENGTH");
+      return retval;
+    }
+
+  octave_idx_type lst_len = lst.length ();
+
+  octave_idx_type new_len = len - rep_length + lst_len;
+
+  retval.resize (new_len);
+
+  octave_idx_type k = 0;
+
+  for (octave_idx_type i = 0; i < offset; i++)
+    retval(k++) = elem (i);
+
+  for (octave_idx_type i = 0; i < lst_len; i++)
+    retval(k++) = lst (i);
+
+  for (octave_idx_type i = offset + rep_length; i < len; i++)
+    retval(k++) = elem (i);
+
+  return retval;
+}
+
+bool
+octave_value_list::all_strings_p (void) const
+{
+  octave_idx_type n = length ();
+
+  for (octave_idx_type i = 0; i < n; i++)
+    if (! elem(i).is_string ())
+      return false;
+
+  return true;
+}
+
+bool
+octave_value_list::all_scalars (void) const
+{
+  octave_idx_type n = length ();
+
+  for (octave_idx_type i = 0; i < n; i++)
+    {
+      dim_vector dv = elem(i).dims ();
+      if (! dv.all_ones ())
+        return false;
+    }
+
+  return true;
+}
+
+bool
+octave_value_list::any_cell (void) const
+{
+  octave_idx_type n = length ();
+
+  for (octave_idx_type i = 0; i < n; i++)
+    if (elem (i).is_cell ())
+      return true;
+
+  return false;
+}
+
+bool
+octave_value_list::has_magic_colon (void) const
+{
+  octave_idx_type n = length ();
+
+  for (octave_idx_type i = 0; i < n; i++)
+    if (elem(i).is_magic_colon ())
+      return true;
+
+  return false;
+}
+
+string_vector
+octave_value_list::make_argv (const std::string& fcn_name) const
+{
+  string_vector argv;
+
+  if (all_strings_p ())
+    {
+      octave_idx_type len = length ();
+
+      octave_idx_type total_nr = 0;
+
+      for (octave_idx_type i = 0; i < len; i++)
+        {
+          // An empty std::string ("") has zero columns and zero rows (a
+          // change that was made for Matlab contemptibility.
+
+          octave_idx_type n = elem(i).rows ();
+
+          total_nr += n ? n : 1;
+        }
+
+      octave_idx_type k = 0;
+      if (! fcn_name.empty ())
+        {
+          argv.resize (total_nr+1);
+          argv[0] = fcn_name;
+          k = 1;
+        }
+      else
+        argv.resize (total_nr);
+
+      for (octave_idx_type i = 0; i < len; i++)
+        {
+          octave_idx_type nr = elem(i).rows ();
+
+          if (nr < 2)
+            argv[k++] = elem(i).string_value ();
+          else
+            {
+              string_vector tmp = elem(i).all_strings ();
+
+              for (octave_idx_type j = 0; j < nr; j++)
+                argv[k++] = tmp[j];
+            }
+        }
+    }
+  else
+    error ("%s: expecting all arguments to be strings", fcn_name.c_str ());
+
+  return argv;
+}
+
+void
+octave_value_list::make_storable_values (void)
+{
+  octave_idx_type len = length ();
+  const Array<octave_value>& cdata = data;
+
+  for (octave_idx_type i = 0; i < len; i++)
+    {
+      // This is optimized so that we don't force a copy unless necessary.
+      octave_value tmp = cdata(i).storable_value ();
+      if (! tmp.is_copy_of (cdata (i)))
+        data(i) = tmp;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/oct-obj.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,169 @@
+/*
+
+Copyright (C) 1994-2012 John W. Eaton
+Copyright (C) 2009 VZLU Prague
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if !defined (octave_oct_obj_h)
+#define octave_oct_obj_h 1
+
+#include <string>
+#include <vector>
+
+#include "oct-alloc.h"
+#include "str-vec.h"
+#include "Array.h"
+
+#include "ov.h"
+#include "Cell.h"
+
+class
+OCTINTERP_API
+octave_value_list
+{
+public:
+
+  octave_value_list (void)
+    : data (), names () { }
+
+  explicit octave_value_list (octave_idx_type n)
+    : data (dim_vector (1, n)), names () { }
+
+  octave_value_list (octave_idx_type n, const octave_value& val)
+    : data (dim_vector (1, n), val), names () { }
+
+  octave_value_list (const octave_value& tc)
+    : data (dim_vector (1, 1), tc), names () { }
+
+  octave_value_list (const Array<octave_value>& d)
+    : data (d.as_row ()), names () { }
+
+  octave_value_list (const Cell& tc)
+    : data (tc.as_row ()), names () { }
+
+  octave_value_list (const octave_value_list& obj)
+    : data (obj.data), names (obj.names) { }
+
+  // Concatenation constructor.
+  octave_value_list (const std::list<octave_value_list>&);
+
+  ~octave_value_list (void) { }
+
+  octave_value_list& operator = (const octave_value_list& obj)
+    {
+      if (this != &obj)
+        {
+          data = obj.data;
+          names = obj.names;
+        }
+
+      return *this;
+    }
+
+  Array<octave_value> array_value (void) const { return data; }
+
+  Cell cell_value (void) const { return array_value (); }
+
+  // Assignment will resize on range errors.
+
+  octave_value& operator () (octave_idx_type n) { return elem (n); }
+
+  const octave_value& operator () (octave_idx_type n) const { return elem (n); }
+
+  octave_idx_type length (void) const { return data.length (); }
+
+  bool empty (void) const { return length () == 0; }
+
+  void resize (octave_idx_type n, const octave_value& rfv = octave_value ())
+  {
+    data.resize (dim_vector (1, n), rfv);
+  }
+
+  octave_value_list& prepend (const octave_value& val);
+
+  octave_value_list& append (const octave_value& val);
+
+  octave_value_list& append (const octave_value_list& lst);
+
+  octave_value_list& reverse (void);
+
+  octave_value_list
+  slice (octave_idx_type offset, octave_idx_type len, bool tags = false) const
+    {
+      octave_value_list retval (data.linear_slice (offset, offset + len));
+      if (tags && len > 0 && names.length () > 0)
+        retval.names = names.linear_slice (offset, std::min (len, names.length ()));
+
+      return retval;
+    }
+
+  octave_value_list
+  splice (octave_idx_type offset, octave_idx_type len,
+          const octave_value_list& lst = octave_value_list ()) const;
+
+  bool all_strings_p (void) const;
+
+  bool all_scalars (void) const;
+
+  bool any_cell (void) const;
+
+  bool has_magic_colon (void) const;
+
+  string_vector make_argv (const std::string& = std::string ()) const;
+
+  void stash_name_tags (const string_vector& nm) { names = nm; }
+
+  string_vector name_tags (void) const { return names; }
+
+  void make_storable_values (void);
+
+  octave_value& xelem (octave_idx_type i)
+    {
+      return data.xelem (i);
+    }
+
+  void clear (void)
+    {
+      data.clear ();
+    }
+
+private:
+
+  Array<octave_value> data;
+
+  // This list of strings can be used to tag each element of data with
+  // a name.  By default, it is empty.
+  string_vector names;
+
+  octave_value& elem (octave_idx_type n)
+    {
+      if (n >= length ())
+        resize (n + 1);
+
+      return data(n);
+    }
+
+  const octave_value& elem (octave_idx_type n) const
+    { return data(n); }
+
+  DECLARE_OCTAVE_ALLOCATOR
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/oct-prcstrm.cc	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,70 @@
+/*
+
+Copyright (C) 1996-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <cstdio>
+
+#include "oct-prcstrm.h"
+#include "sysdep.h"
+
+octave_stream
+octave_iprocstream::create (const std::string& n, std::ios::openmode arg_md,
+                            oct_mach_info::float_format ff)
+{
+  return octave_stream (new octave_iprocstream (n, arg_md, ff));
+}
+
+octave_iprocstream::octave_iprocstream (const std::string& n,
+                                        std::ios::openmode arg_md,
+                                        oct_mach_info::float_format ff)
+  : octave_stdiostream (n, octave_popen (n.c_str (), "r"),
+                        arg_md, ff, octave_pclose)
+{
+}
+
+octave_iprocstream::~octave_iprocstream (void)
+{
+  do_close ();
+}
+
+octave_stream
+octave_oprocstream::create (const std::string& n, std::ios::openmode arg_md,
+                            oct_mach_info::float_format ff)
+{
+  return octave_stream (new octave_oprocstream (n, arg_md, ff));
+}
+
+octave_oprocstream::octave_oprocstream (const std::string& n,
+                                        std::ios::openmode arg_md,
+                                        oct_mach_info::float_format ff)
+  : octave_stdiostream (n, octave_popen (n.c_str (), "w"),
+                        arg_md, ff, octave_pclose)
+{
+}
+
+octave_oprocstream::~octave_oprocstream (void)
+{
+  do_close ();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/oct-prcstrm.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,87 @@
+/*
+
+Copyright (C) 1996-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if !defined (octave_octave_procstream_h)
+#define octave_octave_procstream_h 1
+
+#include "oct-stdstrm.h"
+
+// FIXME -- why don't these classes use iprocstream and
+// oprocstream, which in turn use the octave_procbuf class?
+
+class
+octave_iprocstream : public octave_stdiostream
+{
+public:
+
+  octave_iprocstream (const std::string& n,
+                      std::ios::openmode arg_md = std::ios::in,
+                      oct_mach_info::float_format flt_fmt
+                        = oct_mach_info::native_float_format ());
+
+  static octave_stream
+  create (const std::string& n, std::ios::openmode arg_md = std::ios::in,
+          oct_mach_info::float_format flt_fmt
+            = oct_mach_info::native_float_format ());
+
+protected:
+
+  ~octave_iprocstream (void);
+
+private:
+
+  // No copying!
+
+  octave_iprocstream (const octave_iprocstream&);
+
+  octave_iprocstream& operator = (const octave_iprocstream&);
+};
+
+class
+octave_oprocstream : public octave_stdiostream
+{
+public:
+
+  octave_oprocstream (const std::string& n,
+                      std::ios::openmode arg_md = std::ios::out,
+                      oct_mach_info::float_format flt_fmt
+                        = oct_mach_info::native_float_format ());
+
+  static octave_stream
+  create (const std::string& n, std::ios::openmode arg_md = std::ios::out,
+          oct_mach_info::float_format flt_fmt
+            = oct_mach_info::native_float_format ());
+
+protected:
+
+  ~octave_oprocstream (void);
+
+private:
+
+  // No copying!
+
+  octave_oprocstream (const octave_oprocstream&);
+
+  octave_oprocstream& operator = (const octave_oprocstream&);
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/oct-procbuf.cc	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,218 @@
+/*
+
+Copyright (C) 1996-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <cerrno>
+
+#include <iostream>
+
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "lo-mappers.h"
+#include "lo-utils.h"
+#include "oct-procbuf.h"
+#include "oct-syscalls.h"
+#include "sysdep.h"
+#include "variables.h"
+
+#include "defun.h"
+#include "gripes.h"
+#include "utils.h"
+
+// This class is based on the procbuf class from libg++, written by
+// Per Bothner, Copyright (C) 1993 Free Software Foundation.
+
+static octave_procbuf *octave_procbuf_list = 0;
+
+#ifndef BUFSIZ
+#define BUFSIZ 1024
+#endif
+
+octave_procbuf *
+octave_procbuf::open (const char *command, int mode)
+{
+#if defined (__CYGWIN__) || defined (__MINGW32__) || defined (_MSC_VER)
+
+  if (is_open ())
+    return 0;
+
+  f = octave_popen (command, (mode & std::ios::in) ? "r" : "w");
+
+  if (! f)
+    return 0;
+
+  // Oops... popen doesn't return the associated pid, so fake it for now
+
+  proc_pid = 1;
+
+  open_p = true;
+
+  if (mode & std::ios::out)
+    ::setvbuf (f, 0, _IOLBF, BUFSIZ);
+
+  return this;
+
+#elif defined (HAVE_SYS_WAIT_H)
+
+  int pipe_fds[2];
+
+  volatile int child_std_end = (mode & std::ios::in) ? 1 : 0;
+
+  volatile int parent_end, child_end;
+
+  if (is_open ())
+    return 0;
+
+  if (pipe (pipe_fds) < 0)
+    return 0;
+
+  if (mode & std::ios::in)
+    {
+      parent_end = pipe_fds[0];
+      child_end = pipe_fds[1];
+    }
+  else
+    {
+      parent_end = pipe_fds[1];
+      child_end = pipe_fds[0];
+    }
+
+  proc_pid = ::fork ();
+
+  if (proc_pid == 0)
+    {
+      gnulib::close (parent_end);
+
+      if (child_end != child_std_end)
+        {
+          gnulib::dup2 (child_end, child_std_end);
+          gnulib::close (child_end);
+        }
+
+      while (octave_procbuf_list)
+        {
+          FILE *fp = octave_procbuf_list->f;
+
+          if (fp)
+            {
+              gnulib::fclose (fp);
+              fp = 0;
+            }
+
+          octave_procbuf_list = octave_procbuf_list->next;
+        }
+
+      execl ("/bin/sh", "sh", "-c", command, static_cast<void *> (0));
+
+      exit (127);
+    }
+
+  gnulib::close (child_end);
+
+  if (proc_pid < 0)
+    {
+      gnulib::close (parent_end);
+      return 0;
+    }
+
+  f = ::fdopen (parent_end, (mode & std::ios::in) ? "r" : "w");
+
+  if (mode & std::ios::out)
+    ::setvbuf (f, 0, _IOLBF, BUFSIZ);
+
+  open_p = true;
+
+  next = octave_procbuf_list;
+  octave_procbuf_list = this;
+
+  return this;
+
+#else
+
+  return 0;
+
+#endif
+}
+
+octave_procbuf *
+octave_procbuf::close (void)
+{
+#if defined (__CYGWIN__) || defined (__MINGW32__) || defined (_MSC_VER)
+
+  if (f)
+    {
+      wstatus = octave_pclose (f);
+      f = 0;
+    }
+
+  open_p = false;
+
+  return this;
+
+#elif defined (HAVE_SYS_WAIT_H)
+
+  if (f)
+    {
+      pid_t wait_pid;
+
+      int status = -1;
+
+      for (octave_procbuf **ptr = &octave_procbuf_list;
+           *ptr != 0;
+           ptr = &(*ptr)->next)
+        {
+          if (*ptr == this)
+            {
+              *ptr = (*ptr)->next;
+              status = 0;
+              break;
+            }
+        }
+
+      if (status == 0 && gnulib::fclose (f) == 0)
+        {
+          using namespace std;
+
+          do
+            {
+              wait_pid = octave_syscalls::waitpid (proc_pid, &wstatus, 0);
+            }
+          while (wait_pid == -1 && errno == EINTR);
+        }
+
+      f = 0;
+    }
+
+  open_p = false;
+
+  return this;
+
+#else
+
+  return 0;
+
+#endif
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/oct-procbuf.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,79 @@
+/*
+
+Copyright (C) 1996-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+// This class is based on the procbuf class from libg++, written by
+// Per Bothner, Copyright (C) 1993 Free Software Foundation.
+
+#if !defined (octave_octave_procbuf_h)
+#define octave_octave_procbuf_h 1
+
+#include <sys/types.h>
+
+#include "c-file-ptr-stream.h"
+
+class
+octave_procbuf : public c_file_ptr_buf
+{
+public:
+
+  octave_procbuf (void)
+    : c_file_ptr_buf (0), wstatus (-1), open_p (false), proc_pid (-1),
+      next (0) { }
+
+  octave_procbuf (const char *command, int mode)
+    : c_file_ptr_buf (0), wstatus (-1), open_p (false), proc_pid (-1),
+      next (0) { open (command, mode); }
+
+  ~octave_procbuf (void) { close (); }
+
+  octave_procbuf *open (const char *command, int mode);
+
+  octave_procbuf *close (void);
+
+  int wait_status (void) const { return wstatus; }
+
+  bool is_open (void) const { return open_p; }
+
+  pid_t pid (void) const { return proc_pid; }
+
+protected:
+
+  int wstatus;
+
+  bool open_p;
+
+  pid_t proc_pid;
+
+  octave_procbuf *next;
+
+private:
+
+  // No copying!
+
+  octave_procbuf (const octave_procbuf&);
+
+  octave_procbuf& operator = (const octave_procbuf&);
+};
+
+extern void symbols_of_oct_procbuf (void);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/oct-stdstrm.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,175 @@
+/*
+
+Copyright (C) 1996-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if !defined (octave_octave_stdiostream_h)
+#define octave_octave_stdiostream_h 1
+
+#include "oct-stream.h"
+#include "c-file-ptr-stream.h"
+
+template <typename BUF_T, typename STREAM_T, typename FILE_T>
+class
+octave_tstdiostream : public octave_base_stream
+{
+public:
+
+  octave_tstdiostream (const std::string& n, FILE_T f = 0, int fid = 0,
+                       std::ios::openmode m = std::ios::in|std::ios::out,
+                       oct_mach_info::float_format ff
+                         = oct_mach_info::native_float_format (),
+                       typename BUF_T::close_fcn cf = BUF_T::file_close)
+    : octave_base_stream (m, ff), nm (n), md (m),
+      s (f ? new STREAM_T (f, cf) : 0), fnum (fid)
+  { }
+
+  // Position a stream at OFFSET relative to ORIGIN.
+
+  int seek (long offset, int origin)
+    { return s ? s->seek (offset, origin) : -1; }
+
+  // Return current stream position.
+
+  long tell (void) { return s ? s->tell () : -1; }
+
+  // Return non-zero if EOF has been reached on this stream.
+
+  bool eof (void) const { return s ? s->eof () : true; }
+
+  // The name of the file.
+
+  std::string name (void) const { return nm; }
+
+  std::istream *input_stream (void) { return (md & std::ios::in) ? s : 0; }
+
+  std::ostream *output_stream (void) { return (md & std::ios::out) ? s : 0; }
+
+  // FIXME -- should not have to cast away const here.
+  BUF_T *rdbuf (void) const
+    { return s ? (const_cast<STREAM_T *> (s))->rdbuf () : 0; }
+
+  int file_number (void) const { return fnum; }
+
+  bool bad (void) const { return s ? s->bad () : true; }
+
+  void clear (void) { if (s) s->clear (); }
+
+  void do_close (void) { if (s) s->stream_close (); }
+
+protected:
+
+  std::string nm;
+
+  std::ios::openmode md;
+
+  STREAM_T *s;
+
+  // The file number associated with this file.
+  int fnum;
+
+  ~octave_tstdiostream (void) { delete s; }
+
+private:
+
+  // No copying!
+
+  octave_tstdiostream (const octave_tstdiostream&);
+
+  octave_tstdiostream& operator = (const octave_tstdiostream&);
+};
+
+class
+octave_stdiostream
+  : public octave_tstdiostream<c_file_ptr_buf, io_c_file_ptr_stream, FILE *>
+{
+public:
+
+  octave_stdiostream (const std::string& n, FILE *f = 0,
+                      std::ios::openmode m = std::ios::in|std::ios::out,
+                      oct_mach_info::float_format ff
+                        = oct_mach_info::native_float_format (),
+                      c_file_ptr_buf::close_fcn cf = c_file_ptr_buf::file_close)
+    : octave_tstdiostream<c_file_ptr_buf, io_c_file_ptr_stream, FILE *> (n, f, f ? fileno (f) : -1, m, ff, cf) { }
+
+  static octave_stream
+  create (const std::string& n, FILE *f = 0,
+          std::ios::openmode m = std::ios::in|std::ios::out,
+          oct_mach_info::float_format ff
+            = oct_mach_info::native_float_format (),
+          c_file_ptr_buf::close_fcn cf = c_file_ptr_buf::file_close)
+  {
+    return octave_stream (new octave_stdiostream (n, f, m, ff, cf));
+  }
+
+protected:
+
+  ~octave_stdiostream (void) { }
+
+private:
+
+  // No copying!
+
+  octave_stdiostream (const octave_stdiostream&);
+
+  octave_stdiostream& operator = (const octave_stdiostream&);
+};
+
+#ifdef HAVE_ZLIB
+
+class
+octave_zstdiostream
+  : public octave_tstdiostream<c_zfile_ptr_buf, io_c_zfile_ptr_stream, gzFile>
+{
+public:
+
+  octave_zstdiostream (const std::string& n, gzFile f = 0, int fid = 0,
+                       std::ios::openmode m = std::ios::in|std::ios::out,
+                       oct_mach_info::float_format ff
+                         = oct_mach_info::native_float_format (),
+                       c_zfile_ptr_buf::close_fcn cf = c_zfile_ptr_buf::file_close)
+    : octave_tstdiostream<c_zfile_ptr_buf, io_c_zfile_ptr_stream, gzFile> (n, f, fid, m, ff, cf) { }
+
+  static octave_stream
+  create (const std::string& n, gzFile f = 0, int fid = 0,
+          std::ios::openmode m = std::ios::in|std::ios::out,
+          oct_mach_info::float_format ff
+            = oct_mach_info::native_float_format (),
+          c_zfile_ptr_buf::close_fcn cf = c_zfile_ptr_buf::file_close)
+  {
+    return octave_stream (new octave_zstdiostream (n, f, fid, m, ff, cf));
+  }
+
+protected:
+
+  ~octave_zstdiostream (void) { }
+
+private:
+
+  // No copying!
+
+  octave_zstdiostream (const octave_zstdiostream&);
+
+  octave_zstdiostream& operator = (const octave_zstdiostream&);
+};
+
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/oct-stream.cc	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,4308 @@
+/*
+
+Copyright (C) 1996-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <cassert>
+#include <cctype>
+#include <cstring>
+
+#include <iomanip>
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <string>
+
+#include <Array.h>
+
+#include "byte-swap.h"
+#include "lo-ieee.h"
+#include "lo-mappers.h"
+#include "lo-utils.h"
+#include "quit.h"
+#include "singleton-cleanup.h"
+#include "str-vec.h"
+
+#include "error.h"
+#include "gripes.h"
+#include "input.h"
+#include "oct-stdstrm.h"
+#include "oct-stream.h"
+#include "oct-obj.h"
+#include "utils.h"
+
+// Possible values for conv_err:
+//
+//   1 : not a real scalar
+//   2 : value is NaN
+//   3 : value is not an integer
+
+static int
+convert_to_valid_int (const octave_value& tc, int& conv_err)
+{
+  int retval = 0;
+
+  conv_err = 0;
+
+  double dval = tc.double_value ();
+
+  if (! error_state)
+    {
+      if (! lo_ieee_isnan (dval))
+        {
+          int ival = NINT (dval);
+
+          if (ival == dval)
+            retval = ival;
+          else
+            conv_err = 3;
+        }
+      else
+        conv_err = 2;
+    }
+  else
+    conv_err = 1;
+
+  return retval;
+}
+
+static int
+get_size (double d, const std::string& who)
+{
+  int retval = -1;
+
+  if (! lo_ieee_isnan (d))
+    {
+      if (! xisinf (d))
+        {
+          if (d >= 0.0)
+            retval = NINT (d);
+          else
+            ::error ("%s: negative value invalid as size specification",
+                     who.c_str ());
+        }
+      else
+        retval = -1;
+    }
+  else
+    ::error ("%s: NaN is invalid as size specification", who.c_str ());
+
+  return retval;
+}
+
+static void
+get_size (const Array<double>& size, octave_idx_type& nr, octave_idx_type& nc, bool& one_elt_size_spec,
+          const std::string& who)
+{
+  nr = -1;
+  nc = -1;
+
+  one_elt_size_spec = false;
+
+  double dnr = -1.0;
+  double dnc = -1.0;
+
+  octave_idx_type sz_len = size.length ();
+
+  if (sz_len == 1)
+    {
+      one_elt_size_spec = true;
+
+      dnr = size (0);
+
+      dnc = (dnr == 0.0) ? 0.0 : 1.0;
+    }
+  else if (sz_len == 2)
+    {
+      dnr = size (0);
+
+      if (! xisinf (dnr))
+        dnc = size (1);
+      else
+        ::error ("%s: invalid size specification", who.c_str ());
+    }
+  else
+    ::error ("%s: invalid size specification", who.c_str ());
+
+  if (! error_state)
+    {
+      nr = get_size (dnr, who);
+
+      if (! error_state && dnc >= 0.0)
+        nc = get_size (dnc, who);
+    }
+}
+
+scanf_format_list::scanf_format_list (const std::string& s)
+  : nconv (0), curr_idx (0), list (dim_vector (16, 1)), buf (0)
+{
+  octave_idx_type num_elts = 0;
+
+  size_t n = s.length ();
+
+  size_t i = 0;
+
+  int width = 0;
+  bool discard = false;
+  char modifier = '\0';
+  char type = '\0';
+
+  bool have_more = true;
+
+  while (i < n)
+    {
+      have_more = true;
+
+      if (! buf)
+        buf = new std::ostringstream ();
+
+      if (s[i] == '%')
+        {
+          // Process percent-escape conversion type.
+
+          process_conversion (s, i, n, width, discard, type, modifier,
+                              num_elts);
+
+          have_more = (buf != 0);
+        }
+      else if (isspace (s[i]))
+        {
+          type = scanf_format_elt::whitespace_conversion;
+
+          width = 0;
+          discard = false;
+          modifier = '\0';
+          *buf << " ";
+
+          while (++i < n && isspace (s[i]))
+            /* skip whitespace */;
+
+          add_elt_to_list (width, discard, type, modifier, num_elts);
+
+          have_more = false;
+        }
+      else
+        {
+          type = scanf_format_elt::literal_conversion;
+
+          width = 0;
+          discard = false;
+          modifier = '\0';
+
+          while (i < n && ! isspace (s[i]) && s[i] != '%')
+            *buf << s[i++];
+
+          add_elt_to_list (width, discard, type, modifier, num_elts);
+
+          have_more = false;
+        }
+
+      if (nconv < 0)
+        {
+          have_more = false;
+          break;
+        }
+    }
+
+  if (have_more)
+    add_elt_to_list (width, discard, type, modifier, num_elts);
+
+  list.resize (dim_vector (num_elts, 1));
+
+  delete buf;
+}
+
+scanf_format_list::~scanf_format_list (void)
+{
+  octave_idx_type n = list.length ();
+
+  for (octave_idx_type i = 0; i < n; i++)
+    {
+      scanf_format_elt *elt = list(i);
+      delete elt;
+    }
+}
+
+void
+scanf_format_list::add_elt_to_list (int width, bool discard, char type,
+                                    char modifier, octave_idx_type& num_elts,
+                                    const std::string& char_class)
+{
+  if (buf)
+    {
+      std::string text = buf->str ();
+
+      if (! text.empty ())
+        {
+          scanf_format_elt *elt
+            = new scanf_format_elt (text.c_str (), width, discard, type,
+                                    modifier, char_class);
+
+          if (num_elts == list.length ())
+            list.resize (dim_vector (2 * num_elts, 1));
+
+          list(num_elts++) = elt;
+        }
+
+      delete buf;
+      buf = 0;
+    }
+}
+
+static std::string
+expand_char_class (const std::string& s)
+{
+  std::string retval;
+
+  size_t len = s.length ();
+
+  size_t i = 0;
+
+  while (i < len)
+    {
+      unsigned char c = s[i++];
+
+      if (c == '-' && i > 1 && i < len
+          && static_cast<unsigned char> (s[i-2]) <= static_cast<unsigned char> (s[i]))
+        {
+          // Add all characters from the range except the first (we
+          // already added it below).
+
+          for (c = s[i-2]+1; c < s[i]; c++)
+            retval += c;
+        }
+      else
+        {
+          // Add the character to the class.  Only add '-' if it is
+          // the last character in the class.
+
+          if (c != '-' || i == len)
+            retval += c;
+        }
+    }
+
+  return retval;
+}
+
+void
+scanf_format_list::process_conversion (const std::string& s, size_t& i,
+                                       size_t n, int& width, bool& discard,
+                                       char& type, char& modifier,
+                                       octave_idx_type& num_elts)
+{
+  width = 0;
+  discard = false;
+  modifier = '\0';
+  type = '\0';
+
+  *buf << s[i++];
+
+  bool have_width = false;
+
+  while (i < n)
+    {
+      switch (s[i])
+        {
+        case '*':
+          if (discard)
+            nconv = -1;
+          else
+            {
+              discard = true;
+              *buf << s[i++];
+            }
+          break;
+
+        case '0': case '1': case '2': case '3': case '4':
+        case '5': case '6': case '7': case '8': case '9':
+          if (have_width)
+            nconv = -1;
+          else
+            {
+              char c = s[i++];
+              width = width * 10 + c - '0';
+              have_width = true;
+              *buf << c;
+              while (i < n && isdigit (s[i]))
+                {
+                  c = s[i++];
+                  width = width * 10 + c - '0';
+                  *buf << c;
+                }
+            }
+          break;
+
+        case 'h': case 'l': case 'L':
+          if (modifier != '\0')
+            nconv = -1;
+          else
+            modifier = s[i++];
+          break;
+
+        case 'd': case 'i': case 'o': case 'u': case 'x':
+          if (modifier == 'L')
+            {
+              nconv = -1;
+              break;
+            }
+          goto fini;
+
+        case 'e': case 'f': case 'g':
+          if (modifier == 'h')
+            {
+              nconv = -1;
+              break;
+            }
+
+          // No float or long double conversions, thanks.
+          *buf << 'l';
+
+          goto fini;
+
+        case 'c': case 's': case 'p': case '%': case '[':
+          if (modifier != '\0')
+            {
+              nconv = -1;
+              break;
+            }
+          goto fini;
+
+        fini:
+          {
+            if (finish_conversion (s, i, n, width, discard, type,
+                                   modifier, num_elts) == 0)
+              return;
+          }
+          break;
+
+        default:
+          nconv = -1;
+          break;
+        }
+
+      if (nconv < 0)
+        break;
+    }
+
+  nconv = -1;
+}
+
+int
+scanf_format_list::finish_conversion (const std::string& s, size_t& i,
+                                      size_t n, int& width, bool discard,
+                                      char& type, char modifier,
+                                      octave_idx_type& num_elts)
+{
+  int retval = 0;
+
+  std::string char_class;
+
+  size_t beg_idx = std::string::npos;
+  size_t end_idx = std::string::npos;
+
+  if (s[i] == '%')
+    {
+      type = '%';
+      *buf << s[i++];
+    }
+  else
+    {
+      type = s[i];
+
+      if (s[i] == '[')
+        {
+          *buf << s[i++];
+
+          if (i < n)
+            {
+              beg_idx = i;
+
+              if (s[i] == '^')
+                {
+                  type = '^';
+                  *buf << s[i++];
+
+                  if (i < n)
+                    {
+                      beg_idx = i;
+
+                      if (s[i] == ']')
+                        *buf << s[i++];
+                    }
+                }
+              else if (s[i] == ']')
+                *buf << s[i++];
+            }
+
+          while (i < n && s[i] != ']')
+            *buf << s[i++];
+
+          if (i < n && s[i] == ']')
+            {
+              end_idx = i-1;
+              *buf << s[i++];
+            }
+
+          if (s[i-1] != ']')
+            retval = nconv = -1;
+        }
+      else
+        *buf << s[i++];
+
+      nconv++;
+    }
+
+  if (nconv >= 0)
+    {
+      if (beg_idx != std::string::npos && end_idx != std::string::npos)
+        char_class = expand_char_class (s.substr (beg_idx,
+                                                  end_idx - beg_idx + 1));
+
+      add_elt_to_list (width, discard, type, modifier, num_elts, char_class);
+    }
+
+  return retval;
+}
+
+void
+scanf_format_list::printme (void) const
+{
+  octave_idx_type n = list.length ();
+
+  for (octave_idx_type i = 0; i < n; i++)
+    {
+      scanf_format_elt *elt = list(i);
+
+      std::cerr
+        << "width:      " << elt->width << "\n"
+        << "discard:    " << elt->discard << "\n"
+        << "type:       ";
+
+      if (elt->type == scanf_format_elt::literal_conversion)
+        std::cerr << "literal text\n";
+      else if (elt->type == scanf_format_elt::whitespace_conversion)
+        std::cerr << "whitespace\n";
+      else
+        std::cerr << elt->type << "\n";
+
+      std::cerr
+        << "modifier:   " << elt->modifier << "\n"
+        << "char_class: `" << undo_string_escapes (elt->char_class) << "'\n"
+        << "text:       `" << undo_string_escapes (elt->text) << "'\n\n";
+    }
+}
+
+bool
+scanf_format_list::all_character_conversions (void)
+{
+  octave_idx_type n = list.length ();
+
+  if (n > 0)
+    {
+      for (octave_idx_type i = 0; i < n; i++)
+        {
+          scanf_format_elt *elt = list(i);
+
+          switch (elt->type)
+            {
+            case 'c': case 's': case '%': case '[': case '^':
+            case scanf_format_elt::literal_conversion:
+            case scanf_format_elt::whitespace_conversion:
+              break;
+
+            default:
+              return false;
+              break;
+            }
+        }
+
+      return true;
+    }
+  else
+    return false;
+}
+
+bool
+scanf_format_list::all_numeric_conversions (void)
+{
+  octave_idx_type n = list.length ();
+
+  if (n > 0)
+    {
+      for (octave_idx_type i = 0; i < n; i++)
+        {
+          scanf_format_elt *elt = list(i);
+
+          switch (elt->type)
+            {
+            case 'd': case 'i': case 'o': case 'u': case 'x':
+            case 'e': case 'f': case 'g':
+              break;
+
+            default:
+              return false;
+              break;
+            }
+        }
+
+      return true;
+    }
+  else
+    return false;
+}
+
+// Ugh again.
+
+printf_format_list::printf_format_list (const std::string& s)
+  : nconv (0), curr_idx (0), list (dim_vector (16, 1)), buf (0)
+{
+  octave_idx_type num_elts = 0;
+
+  size_t n = s.length ();
+
+  size_t i = 0;
+
+  int args = 0;
+  std::string flags;
+  int fw = 0;
+  int prec = 0;
+  char modifier = '\0';
+  char type = '\0';
+
+  bool have_more = true;
+  bool empty_buf = true;
+
+  if (n == 0)
+    {
+      printf_format_elt *elt
+        = new printf_format_elt ("", args, fw, prec, flags, type, modifier);
+
+      list(num_elts++) = elt;
+
+      list.resize (dim_vector (num_elts, 1));
+    }
+  else
+    {
+      while (i < n)
+        {
+          have_more = true;
+
+          if (! buf)
+            {
+              buf = new std::ostringstream ();
+              empty_buf = true;
+            }
+
+          switch (s[i])
+            {
+            case '%':
+              {
+                if (empty_buf)
+                  {
+                    process_conversion (s, i, n, args, flags, fw, prec,
+                                        type, modifier, num_elts);
+
+                    have_more = (buf != 0);
+                  }
+                else
+                  add_elt_to_list (args, flags, fw, prec, type, modifier,
+                                   num_elts);
+              }
+              break;
+
+            default:
+              {
+                args = 0;
+                flags = "";
+                fw = 0;
+                prec = 0;
+                modifier = '\0';
+                type = '\0';
+                *buf << s[i++];
+                empty_buf = false;
+              }
+              break;
+            }
+
+          if (nconv < 0)
+            {
+              have_more = false;
+              break;
+            }
+        }
+
+      if (have_more)
+        add_elt_to_list (args, flags, fw, prec, type, modifier, num_elts);
+
+      list.resize (dim_vector (num_elts, 1));
+
+      delete buf;
+    }
+}
+
+printf_format_list::~printf_format_list (void)
+{
+  octave_idx_type n = list.length ();
+
+  for (octave_idx_type i = 0; i < n; i++)
+    {
+      printf_format_elt *elt = list(i);
+      delete elt;
+    }
+}
+
+void
+printf_format_list::add_elt_to_list (int args, const std::string& flags,
+                                     int fw, int prec, char type,
+                                     char modifier, octave_idx_type& num_elts)
+{
+  if (buf)
+    {
+      std::string text = buf->str ();
+
+      if (! text.empty ())
+        {
+          printf_format_elt *elt
+            = new printf_format_elt (text.c_str (), args, fw, prec, flags,
+                                     type, modifier);
+
+          if (num_elts == list.length ())
+            list.resize (dim_vector (2 * num_elts, 1));
+
+          list(num_elts++) = elt;
+        }
+
+      delete buf;
+      buf = 0;
+    }
+}
+
+void
+printf_format_list::process_conversion
+  (const std::string& s, size_t& i, size_t n, int& args, std::string& flags,
+   int& fw, int& prec, char& modifier, char& type, octave_idx_type& num_elts)
+{
+  args = 0;
+  flags = "";
+  fw = 0;
+  prec = 0;
+  modifier = '\0';
+  type = '\0';
+
+  *buf << s[i++];
+
+  bool nxt = false;
+
+  while (i < n)
+    {
+      switch (s[i])
+        {
+        case '-': case '+': case ' ': case '0': case '#':
+          flags += s[i];
+          *buf << s[i++];
+          break;
+
+        default:
+          nxt = true;
+          break;
+        }
+
+      if (nxt)
+        break;
+    }
+
+  if (i < n)
+    {
+      if (s[i] == '*')
+        {
+          fw = -1;
+          args++;
+          *buf << s[i++];
+        }
+      else
+        {
+          if (isdigit (s[i]))
+            {
+              int nn = 0;
+              std::string tmp = s.substr (i);
+              sscanf (tmp.c_str (), "%d%n", &fw, &nn);
+            }
+
+          while (i < n && isdigit (s[i]))
+            *buf << s[i++];
+        }
+    }
+
+  if (i < n && s[i] == '.')
+    {
+      *buf << s[i++];
+
+      if (i < n)
+        {
+          if (s[i] == '*')
+            {
+              prec = -1;
+              args++;
+              *buf << s[i++];
+            }
+          else
+            {
+              if (isdigit (s[i]))
+                {
+                  int nn = 0;
+                  std::string tmp = s.substr (i);
+                  sscanf (tmp.c_str (), "%d%n", &prec, &nn);
+                }
+
+              while (i < n && isdigit (s[i]))
+                *buf << s[i++];
+            }
+        }
+    }
+
+  if (i < n)
+    {
+      switch (s[i])
+        {
+        case 'h': case 'l': case 'L':
+          modifier = s[i];
+          *buf << s[i++];
+          break;
+
+        default:
+          break;
+        }
+    }
+
+  if (i < n)
+    finish_conversion (s, i, args, flags, fw, prec, modifier, type, num_elts);
+  else
+    nconv = -1;
+}
+
+void
+printf_format_list::finish_conversion
+  (const std::string& s, size_t& i, int args, const std::string& flags,
+   int fw, int prec, char modifier, char& type, octave_idx_type& num_elts)
+
+{
+  switch (s[i])
+    {
+    case 'd': case 'i': case 'o': case 'x': case 'X':
+    case 'u': case 'c':
+      if (modifier == 'L')
+        {
+          nconv = -1;
+          break;
+        }
+      goto fini;
+
+    case 'f': case 'e': case 'E': case 'g': case 'G':
+      if (modifier == 'h' || modifier == 'l')
+        {
+          nconv = -1;
+          break;
+        }
+      goto fini;
+
+    case 's': case 'p': case '%':
+      if (modifier != '\0')
+        {
+          nconv = -1;
+          break;
+        }
+      goto fini;
+
+    fini:
+
+      type = s[i];
+
+      *buf << s[i++];
+
+      if (type != '%' || args != 0)
+        nconv++;
+
+      if (type != '%')
+        args++;
+
+      add_elt_to_list (args, flags, fw, prec, type, modifier, num_elts);
+
+      break;
+
+    default:
+      nconv = -1;
+      break;
+    }
+}
+
+void
+printf_format_list::printme (void) const
+{
+  int n = list.length ();
+
+  for (int i = 0; i < n; i++)
+    {
+      printf_format_elt *elt = list(i);
+
+      std::cerr
+        << "args:     " << elt->args << "\n"
+        << "flags:    `" << elt->flags << "'\n"
+        << "width:    " << elt->fw << "\n"
+        << "prec:     " << elt->prec << "\n"
+        << "type:     `" << elt->type << "'\n"
+        << "modifier: `" << elt->modifier << "'\n"
+        << "text:     `" << undo_string_escapes (elt->text) << "'\n\n";
+    }
+}
+
+void
+octave_base_stream::error (const std::string& msg)
+{
+  fail = true;
+  errmsg = msg;
+}
+
+void
+octave_base_stream::error (const std::string& who, const std::string& msg)
+{
+  fail = true;
+  errmsg = who + ": " + msg;
+}
+
+void
+octave_base_stream::clear (void)
+{
+  fail = false;
+  errmsg = "";
+}
+
+void
+octave_base_stream::clearerr (void)
+{
+  std::istream *is = input_stream ();
+  std::ostream *os = output_stream ();
+
+  if (is)
+    is->clear ();
+
+  if (os)
+    os->clear ();
+}
+
+// Functions that are defined for all input streams (input streams
+// are those that define is).
+
+std::string
+octave_base_stream::do_gets (octave_idx_type max_len, bool& err,
+                             bool strip_newline, const std::string& who)
+{
+  std::string retval;
+
+  if ((interactive || forced_interactive) && file_number () == 0)
+    {
+      ::error ("%s: unable to read from stdin while running interactively",
+               who.c_str ());
+
+      return retval;
+    }
+
+  err = false;
+
+  std::istream *isp = input_stream ();
+
+  if (isp)
+    {
+      std::istream& is = *isp;
+
+      std::ostringstream buf;
+
+      int c = 0;
+      int char_count = 0;
+
+      if (max_len != 0)
+        {
+          while (is && (c = is.get ()) != EOF)
+            {
+              char_count++;
+
+              // Handle CRLF, CR, or LF as line ending.
+
+              if (c == '\r')
+                {
+                  if (! strip_newline)
+                    buf << static_cast<char> (c);
+
+                  c = is.get ();
+
+                  if (c != EOF)
+                    {
+                      if (c == '\n')
+                        {
+                          char_count++;
+
+                          if (! strip_newline)
+                            buf << static_cast<char> (c);
+                        }
+                      else
+                        is.putback (c);
+                    }
+
+                  break;
+                }
+              else if (c == '\n')
+                {
+                  if (! strip_newline)
+                    buf << static_cast<char> (c);
+
+                  break;
+                }
+              else
+                buf << static_cast<char> (c);
+
+              if (max_len > 0 && char_count == max_len)
+                break;
+            }
+        }
+
+      if (! is.eof () && char_count > 0)
+        {
+          // GAGME.  Matlab seems to check for EOF even if the last
+          // character in a file is a newline character.  This is NOT
+          // what the corresponding C-library functions do.
+          int disgusting_compatibility_hack = is.get ();
+          if (! is.eof ())
+            is.putback (disgusting_compatibility_hack);
+        }
+
+      if (is.good () || (is.eof () && char_count > 0))
+        retval = buf.str ();
+      else
+        {
+          err = true;
+
+          if (is.eof () && char_count == 0)
+            error (who, "at end of file");
+          else
+            error (who, "read error");
+        }
+    }
+  else
+    {
+      err = true;
+      invalid_operation (who, "reading");
+    }
+
+  return retval;
+}
+
+std::string
+octave_base_stream::getl (octave_idx_type max_len, bool& err, const std::string& who)
+{
+  return do_gets (max_len, err, true, who);
+}
+
+std::string
+octave_base_stream::gets (octave_idx_type max_len, bool& err, const std::string& who)
+{
+  return do_gets (max_len, err, false, who);
+}
+
+long
+octave_base_stream::skipl (long num, bool& err, const std::string& who)
+{
+  long cnt = -1;
+
+  if ((interactive || forced_interactive) && file_number () == 0)
+    {
+      ::error ("%s: unable to read from stdin while running interactively",
+               who.c_str ());
+
+      return count;
+    }
+
+  err = false;
+
+  std::istream *isp = input_stream ();
+
+  if (isp)
+    {
+      std::istream& is = *isp;
+
+      int c = 0, lastc = -1;
+      cnt = 0;
+
+      while (is && (c = is.get ()) != EOF)
+        {
+          // Handle CRLF, CR, or LF as line ending.
+
+          if (c == '\r' || (c == '\n' && lastc != '\r'))
+            {
+              if (++cnt == num)
+                break;
+            }
+
+          lastc = c;
+        }
+
+      // Maybe eat the following \n if \r was just met.
+      if (c == '\r' && is.peek () == '\n')
+       is.get ();
+
+      if (is.bad ())
+        {
+          err = true;
+          error (who, "read error");
+        }
+
+      if (err)
+        cnt = -1;
+    }
+  else
+    {
+      err = true;
+      invalid_operation (who, "reading");
+    }
+
+  return cnt;
+}
+
+#define OCTAVE_SCAN(is, fmt, arg) octave_scan (is, fmt, arg)
+
+template <class T>
+std::istream&
+octave_scan_1 (std::istream& is, const scanf_format_elt& fmt, T* valptr)
+{
+  T& ref = *valptr;
+
+  switch (fmt.type)
+    {
+    case 'o':
+      is >> std::oct >> ref >> std::dec;
+      break;
+
+    case 'x':
+      is >> std::hex >> ref >> std::dec;
+      break;
+
+    case 'i':
+      {
+        int c1 = EOF;
+
+        while (is && (c1 = is.get ()) != EOF && isspace (c1))
+          /* skip whitespace */;
+
+        if (c1 != EOF)
+          {
+            if (c1 == '0')
+              {
+                int c2 = is.peek ();
+
+                if (c2 == 'x' || c2 == 'X')
+                  {
+                    is.ignore ();
+                    if (std::isxdigit (is.peek ()))
+                      is >> std::hex >> ref >> std::dec;
+                    else
+                      ref = 0;
+                  }
+                else
+                  {
+                    if (c2 == '0' || c2 == '1' || c2 == '2'
+                        || c2 == '3' || c2 == '4' || c2 == '5'
+                        || c2 == '6' || c2 == '7')
+                      is >> std::oct >> ref >> std::dec;
+                    else
+                      ref = 0;
+                  }
+              }
+            else
+              {
+                is.putback (c1);
+
+                is >> ref;
+              }
+          }
+      }
+      break;
+
+    default:
+      is >> ref;
+      break;
+    }
+
+  return is;
+}
+
+template <class T>
+std::istream&
+octave_scan (std::istream& is, const scanf_format_elt& fmt, T* valptr)
+{
+  if (fmt.width)
+    {
+      // Limit input to fmt.width characters by reading into a
+      // temporary stringstream buffer.
+
+      std::string tmp;
+
+      is.width (fmt.width);
+      is >> tmp;
+
+      std::istringstream ss (tmp);
+
+      octave_scan_1 (ss, fmt, valptr);
+    }
+  else
+    octave_scan_1 (is, fmt, valptr);
+
+  return is;
+}
+
+// Note that this specialization is only used for reading characters, not
+// character strings. See BEGIN_S_CONVERSION for details.
+
+template<>
+std::istream&
+octave_scan<> (std::istream& is, const scanf_format_elt& /* fmt */,
+               char* valptr)
+{
+  return is >> valptr;
+}
+
+template std::istream&
+octave_scan (std::istream&, const scanf_format_elt&, int*);
+
+template std::istream&
+octave_scan (std::istream&, const scanf_format_elt&, long int*);
+
+template std::istream&
+octave_scan (std::istream&, const scanf_format_elt&, short int*);
+
+template std::istream&
+octave_scan (std::istream&, const scanf_format_elt&, unsigned int*);
+
+template std::istream&
+octave_scan (std::istream&, const scanf_format_elt&, unsigned long int*);
+
+template std::istream&
+octave_scan (std::istream&, const scanf_format_elt&, unsigned short int*);
+
+#if 0
+template std::istream&
+octave_scan (std::istream&, const scanf_format_elt&, float*);
+#endif
+
+template<>
+std::istream&
+octave_scan<> (std::istream& is, const scanf_format_elt& fmt, double* valptr)
+{
+  double& ref = *valptr;
+
+  switch (fmt.type)
+    {
+    case 'e':
+    case 'f':
+    case 'g':
+      {
+        int c1 = EOF;
+
+        while (is && (c1 = is.get ()) != EOF && isspace (c1))
+          /* skip whitespace */;
+
+        if (c1 != EOF)
+          {
+            is.putback (c1);
+
+            ref = octave_read_value<double> (is);
+          }
+      }
+      break;
+
+    default:
+      panic_impossible ();
+      break;
+    }
+
+  return is;
+}
+
+template <class T>
+void
+do_scanf_conv (std::istream& is, const scanf_format_elt& fmt,
+               T valptr, Matrix& mval, double *data, octave_idx_type& idx,
+               octave_idx_type& conversion_count, octave_idx_type nr, octave_idx_type max_size,
+               bool discard)
+{
+  OCTAVE_SCAN (is, fmt, valptr);
+
+  if (is)
+    {
+      if (idx == max_size && ! discard)
+        {
+          max_size *= 2;
+
+          if (nr > 0)
+            mval.resize (nr, max_size / nr, 0.0);
+          else
+            mval.resize (max_size, 1, 0.0);
+
+          data = mval.fortran_vec ();
+        }
+
+      if (! discard)
+        {
+          conversion_count++;
+          data[idx++] = *(valptr);
+        }
+    }
+}
+
+template void
+do_scanf_conv (std::istream&, const scanf_format_elt&, int*,
+               Matrix&, double*, octave_idx_type&, octave_idx_type&, octave_idx_type, octave_idx_type, bool);
+
+template void
+do_scanf_conv (std::istream&, const scanf_format_elt&, long int*,
+               Matrix&, double*, octave_idx_type&, octave_idx_type&, octave_idx_type, octave_idx_type, bool);
+
+template void
+do_scanf_conv (std::istream&, const scanf_format_elt&, short int*,
+               Matrix&, double*, octave_idx_type&, octave_idx_type&, octave_idx_type, octave_idx_type, bool);
+
+template void
+do_scanf_conv (std::istream&, const scanf_format_elt&, unsigned int*,
+               Matrix&, double*, octave_idx_type&, octave_idx_type&, octave_idx_type, octave_idx_type, bool);
+
+template void
+do_scanf_conv (std::istream&, const scanf_format_elt&, unsigned long int*,
+               Matrix&, double*, octave_idx_type&, octave_idx_type&, octave_idx_type, octave_idx_type, bool);
+
+template void
+do_scanf_conv (std::istream&, const scanf_format_elt&, unsigned short int*,
+               Matrix&, double*, octave_idx_type&, octave_idx_type&, octave_idx_type, octave_idx_type, bool);
+
+#if 0
+template void
+do_scanf_conv (std::istream&, const scanf_format_elt&, float*,
+               Matrix&, double*, octave_idx_type&, octave_idx_type&, octave_idx_type, octave_idx_type, bool);
+#endif
+
+template void
+do_scanf_conv (std::istream&, const scanf_format_elt&, double*,
+               Matrix&, double*, octave_idx_type&, octave_idx_type&, octave_idx_type, octave_idx_type, bool);
+
+#define DO_WHITESPACE_CONVERSION() \
+  do \
+    { \
+      int c = EOF; \
+ \
+      while (is && (c = is.get ()) != EOF && isspace (c)) \
+        /* skip whitespace */; \
+ \
+      if (c != EOF) \
+        is.putback (c); \
+    } \
+  while (0)
+
+#define DO_LITERAL_CONVERSION() \
+  do \
+    { \
+      int c = EOF; \
+ \
+      int n = strlen (fmt); \
+      int i = 0; \
+ \
+      while (i < n && is && (c = is.get ()) != EOF) \
+        { \
+          if (c == static_cast<unsigned char> (fmt[i])) \
+            { \
+              i++; \
+              continue; \
+            } \
+          else \
+            { \
+              is.putback (c); \
+              break; \
+            } \
+        } \
+ \
+      if (i != n) \
+        is.setstate (std::ios::failbit); \
+    } \
+  while (0)
+
+#define DO_PCT_CONVERSION() \
+  do \
+    { \
+      int c = is.get (); \
+ \
+      if (c != EOF) \
+        { \
+          if (c != '%') \
+            { \
+              is.putback (c); \
+              is.setstate (std::ios::failbit); \
+            } \
+        } \
+      else \
+        is.setstate (std::ios::failbit); \
+    } \
+  while (0)
+
+#define BEGIN_C_CONVERSION() \
+  is.unsetf (std::ios::skipws); \
+ \
+  int width = elt->width ? elt->width : 1; \
+ \
+  std::string tmp (width, '\0'); \
+ \
+  int c = EOF; \
+  int n = 0; \
+ \
+  while (is && n < width && (c = is.get ()) != EOF) \
+    tmp[n++] = static_cast<char> (c); \
+ \
+  if (n > 0 && c == EOF) \
+    is.clear (); \
+ \
+  tmp.resize (n)
+
+// For a `%s' format, skip initial whitespace and then read until the
+// next whitespace character or until WIDTH characters have been read.
+#define BEGIN_S_CONVERSION() \
+  int width = elt->width; \
+ \
+  std::string tmp; \
+ \
+  do \
+    { \
+      if (width) \
+        { \
+          tmp = std::string (width, '\0'); \
+ \
+          int c = EOF; \
+ \
+          int n = 0; \
+ \
+          while (is && (c = is.get ()) != EOF) \
+            { \
+              if (! isspace (c)) \
+                { \
+                  tmp[n++] = static_cast<char> (c); \
+                  break; \
+                } \
+            } \
+ \
+          while (is && n < width && (c = is.get ()) != EOF) \
+            { \
+              if (isspace (c)) \
+                { \
+                  is.putback (c); \
+                  break; \
+                } \
+              else \
+                tmp[n++] = static_cast<char> (c); \
+            } \
+ \
+          if (n > 0 && c == EOF) \
+            is.clear (); \
+ \
+          tmp.resize (n); \
+        } \
+      else \
+        { \
+          is >> std::ws >> tmp; \
+        } \
+    } \
+  while (0)
+
+// This format must match a nonempty sequence of characters.
+#define BEGIN_CHAR_CLASS_CONVERSION() \
+  int width = elt->width; \
+ \
+  std::string tmp; \
+ \
+  do \
+    { \
+      if (! width) \
+        width = INT_MAX; \
+ \
+      std::ostringstream buf; \
+ \
+      std::string char_class = elt->char_class; \
+ \
+      int c = EOF; \
+ \
+      if (elt->type == '[') \
+        { \
+          int chars_read = 0; \
+          while (is && chars_read++ < width && (c = is.get ()) != EOF \
+                 && char_class.find (c) != std::string::npos) \
+            buf << static_cast<char> (c); \
+        } \
+      else \
+        { \
+          int chars_read = 0; \
+          while (is && chars_read++ < width && (c = is.get ()) != EOF \
+                 && char_class.find (c) == std::string::npos) \
+            buf << static_cast<char> (c); \
+        } \
+ \
+      if (width == INT_MAX && c != EOF) \
+        is.putback (c); \
+ \
+      tmp = buf.str (); \
+ \
+      if (tmp.empty ()) \
+        is.setstate (std::ios::failbit); \
+      else if (c == EOF) \
+        is.clear (); \
+ \
+    } \
+  while (0)
+
+#define FINISH_CHARACTER_CONVERSION() \
+  do \
+    { \
+      width = tmp.length (); \
+ \
+      if (is) \
+        { \
+          int i = 0; \
+ \
+          if (! discard) \
+            { \
+              conversion_count++; \
+ \
+              while (i < width) \
+                { \
+                  if (data_index == max_size) \
+                    { \
+                      max_size *= 2; \
+ \
+                      if (all_char_conv) \
+                        { \
+                          if (one_elt_size_spec) \
+                            mval.resize (1, max_size, 0.0); \
+                          else if (nr > 0) \
+                            mval.resize (nr, max_size / nr, 0.0); \
+                          else \
+                            panic_impossible (); \
+                        } \
+                      else if (nr > 0) \
+                        mval.resize (nr, max_size / nr, 0.0); \
+                      else \
+                        mval.resize (max_size, 1, 0.0); \
+ \
+                      data = mval.fortran_vec (); \
+                    } \
+ \
+                  data[data_index++] = tmp[i++]; \
+                } \
+            } \
+        } \
+    } \
+  while (0)
+
+octave_value
+octave_base_stream::do_scanf (scanf_format_list& fmt_list,
+                              octave_idx_type nr, octave_idx_type nc, bool one_elt_size_spec,
+                              octave_idx_type& conversion_count, const std::string& who)
+{
+  octave_value retval = Matrix ();
+
+  if ((interactive || forced_interactive) && file_number () == 0)
+    {
+      ::error ("%s: unable to read from stdin while running interactively",
+               who.c_str ());
+
+      return retval;
+    }
+
+  conversion_count = 0;
+
+  octave_idx_type nconv = fmt_list.num_conversions ();
+
+  octave_idx_type data_index = 0;
+
+  if (nr == 0 || nc == 0)
+    {
+      if (one_elt_size_spec)
+        nc = 0;
+
+      return Matrix (nr, nc, 0.0);
+    }
+
+  std::istream *isp = input_stream ();
+
+  bool all_char_conv = fmt_list.all_character_conversions ();
+
+  Matrix mval;
+  double *data = 0;
+  octave_idx_type max_size = 0;
+  octave_idx_type max_conv = 0;
+
+  octave_idx_type final_nr = 0;
+  octave_idx_type final_nc = 0;
+
+  if (all_char_conv)
+    {
+      // Any of these could be resized later (if we have %s
+      // conversions, we may read more than one element for each
+      // conversion).
+
+      if (one_elt_size_spec)
+        {
+          max_size = 512;
+          mval.resize (1, max_size, 0.0);
+
+          if (nr > 0)
+            max_conv = nr;
+        }
+      else if (nr > 0)
+        {
+          if (nc > 0)
+            {
+              mval.resize (nr, nc, 0.0);
+              max_size = max_conv = nr * nc;
+            }
+          else
+            {
+              mval.resize (nr, 32, 0.0);
+              max_size = nr * 32;
+            }
+        }
+      else
+        panic_impossible ();
+    }
+  else if (nr > 0)
+    {
+      if (nc > 0)
+        {
+          // Will not resize later.
+          mval.resize (nr, nc, 0.0);
+          max_size = nr * nc;
+          max_conv = max_size;
+        }
+      else
+        {
+          // Maybe resize later.
+          mval.resize (nr, 32, 0.0);
+          max_size = nr * 32;
+        }
+    }
+  else
+    {
+      // Maybe resize later.
+      mval.resize (32, 1, 0.0);
+      max_size = 32;
+    }
+
+  data = mval.fortran_vec ();
+
+  if (isp)
+    {
+      std::istream& is = *isp;
+
+      const scanf_format_elt *elt = fmt_list.first ();
+
+      std::ios::fmtflags flags = is.flags ();
+
+      octave_idx_type trips = 0;
+
+      octave_idx_type num_fmt_elts = fmt_list.length ();
+
+      for (;;)
+        {
+          octave_quit ();
+
+          if (elt)
+            {
+              if (! (elt->type == scanf_format_elt::whitespace_conversion
+                     || elt->type == scanf_format_elt::literal_conversion
+                     || elt->type == '%')
+                  && max_conv > 0 && conversion_count == max_conv)
+                {
+                  if (all_char_conv && one_elt_size_spec)
+                    {
+                      final_nr = 1;
+                      final_nc = data_index;
+                    }
+                  else
+                    {
+                      final_nr = nr;
+                      final_nc = (data_index - 1) / nr + 1;
+                    }
+
+                  break;
+                }
+              else if (data_index == max_size)
+                {
+                  max_size *= 2;
+
+                  if (all_char_conv)
+                    {
+                      if (one_elt_size_spec)
+                        mval.resize (1, max_size, 0.0);
+                      else if (nr > 0)
+                        mval.resize (nr, max_size / nr, 0.0);
+                      else
+                        panic_impossible ();
+                    }
+                  else if (nr > 0)
+                    mval.resize (nr, max_size / nr, 0.0);
+                  else
+                    mval.resize (max_size, 1, 0.0);
+
+                  data = mval.fortran_vec ();
+                }
+
+              const char *fmt = elt->text;
+
+              bool discard = elt->discard;
+
+              switch (elt->type)
+                {
+                case scanf_format_elt::whitespace_conversion:
+                  DO_WHITESPACE_CONVERSION ();
+                  break;
+
+                case scanf_format_elt::literal_conversion:
+                  DO_LITERAL_CONVERSION ();
+                  break;
+
+                case '%':
+                  DO_PCT_CONVERSION ();
+                  break;
+
+                case 'd': case 'i':
+                  {
+                    switch (elt->modifier)
+                      {
+                      case 'h':
+                        {
+                          short int tmp;
+                          do_scanf_conv (is, *elt, &tmp, mval, data,
+                                         data_index, conversion_count,
+                                         nr, max_size, discard);
+                        }
+                        break;
+
+                      case 'l':
+                        {
+                          long int tmp;
+                          do_scanf_conv (is, *elt, &tmp, mval, data,
+                                         data_index, conversion_count,
+                                         nr, max_size, discard);
+                        }
+                        break;
+
+                      default:
+                        {
+                          int tmp;
+                          do_scanf_conv (is, *elt, &tmp, mval, data,
+                                         data_index, conversion_count,
+                                         nr, max_size, discard);
+                        }
+                        break;
+                      }
+                  }
+                  break;
+
+                case 'o': case 'u': case 'x':
+                  {
+                    switch (elt->modifier)
+                      {
+                      case 'h':
+                        {
+                          unsigned short int tmp;
+                          do_scanf_conv (is, *elt, &tmp, mval, data,
+                                         data_index, conversion_count,
+                                         nr, max_size, discard);
+                        }
+                        break;
+
+                      case 'l':
+                        {
+                          unsigned long int tmp;
+                          do_scanf_conv (is, *elt, &tmp, mval, data,
+                                         data_index, conversion_count,
+                                         nr, max_size, discard);
+                        }
+                        break;
+
+                      default:
+                        {
+                          unsigned int tmp;
+                          do_scanf_conv (is, *elt, &tmp, mval, data,
+                                         data_index, conversion_count,
+                                         nr, max_size, discard);
+                        }
+                        break;
+                      }
+                  }
+                  break;
+
+                case 'e': case 'f': case 'g':
+                  {
+                    double tmp;
+
+                    do_scanf_conv (is, *elt, &tmp, mval, data,
+                                   data_index, conversion_count,
+                                   nr, max_size, discard);
+                  }
+                  break;
+
+                case 'c':
+                  {
+                    BEGIN_C_CONVERSION ();
+
+                    FINISH_CHARACTER_CONVERSION ();
+
+                    is.setf (flags);
+                  }
+                  break;
+
+                case 's':
+                  {
+                    BEGIN_S_CONVERSION ();
+
+                    FINISH_CHARACTER_CONVERSION ();
+                  }
+                  break;
+
+                case '[': case '^':
+                  {
+                    BEGIN_CHAR_CLASS_CONVERSION ();
+
+                    FINISH_CHARACTER_CONVERSION ();
+                  }
+                  break;
+
+                case 'p':
+                  error ("%s: unsupported format specifier", who.c_str ());
+                  break;
+
+                default:
+                  error ("%s: internal format error", who.c_str ());
+                  break;
+                }
+
+              if (! ok ())
+                {
+                  break;
+                }
+              else if (! is)
+                {
+                  if (all_char_conv)
+                    {
+                      if (one_elt_size_spec)
+                        {
+                          final_nr = 1;
+                          final_nc = data_index;
+                        }
+                      else if (data_index > nr)
+                        {
+                          final_nr = nr;
+                          final_nc = (data_index - 1) / nr + 1;
+                        }
+                      else
+                        {
+                          final_nr = data_index;
+                          final_nc = 1;
+                        }
+                    }
+                  else if (nr > 0)
+                    {
+                      if (data_index > nr)
+                        {
+                          final_nr = nr;
+                          final_nc = (data_index - 1) / nr + 1;
+                        }
+                      else
+                        {
+                          final_nr = data_index;
+                          final_nc = 1;
+                        }
+                    }
+                  else
+                    {
+                      final_nr = data_index;
+                      final_nc = 1;
+                    }
+
+                  // If it looks like we have a matching failure, then
+                  // reset the failbit in the stream state.
+
+                  if (is.rdstate () & std::ios::failbit)
+                    is.clear (is.rdstate () & (~std::ios::failbit));
+
+                  // FIXME -- is this the right thing to do?
+
+                  if (interactive && name () == "stdin")
+                    {
+                      is.clear ();
+
+                      // Skip to end of line.
+
+                      bool err;
+                      do_gets (-1, err, false, who);
+                    }
+
+                  break;
+                }
+            }
+          else
+            {
+              error ("%s: internal format error", who.c_str ());
+              break;
+            }
+
+          if (nconv == 0 && ++trips == num_fmt_elts)
+            {
+              if (all_char_conv && one_elt_size_spec)
+                {
+                  final_nr = 1;
+                  final_nc = data_index;
+                }
+              else
+                {
+                  final_nr = nr;
+                  final_nc = (data_index - 1) / nr + 1;
+                }
+
+              break;
+            }
+          else
+            elt = fmt_list.next (nconv > 0);
+        }
+    }
+
+  if (ok ())
+    {
+      mval.resize (final_nr, final_nc, 0.0);
+
+      retval = mval;
+
+      if (all_char_conv)
+        retval = retval.convert_to_str (false, true);
+    }
+
+  return retval;
+}
+
+octave_value
+octave_base_stream::scanf (const std::string& fmt, const Array<double>& size,
+                           octave_idx_type& conversion_count, const std::string& who)
+{
+  octave_value retval = Matrix ();
+
+  conversion_count = 0;
+
+  std::istream *isp = input_stream ();
+
+  if (isp)
+    {
+      scanf_format_list fmt_list (fmt);
+
+      if (fmt_list.num_conversions () == -1)
+        ::error ("%s: invalid format specified", who.c_str ());
+      else
+        {
+        octave_idx_type nr = -1;
+        octave_idx_type nc = -1;
+
+        bool one_elt_size_spec;
+
+        get_size (size, nr, nc, one_elt_size_spec, who);
+
+        if (! error_state)
+          retval = do_scanf (fmt_list, nr, nc, one_elt_size_spec,
+                             conversion_count, who);
+        }
+    }
+  else
+    invalid_operation (who, "reading");
+
+  return retval;
+}
+
+bool
+octave_base_stream::do_oscanf (const scanf_format_elt *elt,
+                               octave_value& retval, const std::string& who)
+{
+  bool quit = false;
+
+  std::istream *isp = input_stream ();
+
+  if (isp)
+    {
+      std::istream& is = *isp;
+
+      std::ios::fmtflags flags = is.flags ();
+
+      if (elt)
+        {
+          const char *fmt = elt->text;
+
+          bool discard = elt->discard;
+
+          switch (elt->type)
+            {
+            case scanf_format_elt::whitespace_conversion:
+              DO_WHITESPACE_CONVERSION ();
+              break;
+
+            case scanf_format_elt::literal_conversion:
+              DO_LITERAL_CONVERSION ();
+              break;
+
+            case '%':
+              {
+                DO_PCT_CONVERSION ();
+
+                if (! is)
+                  quit = true;
+
+              }
+              break;
+
+            case 'd': case 'i':
+              {
+                int tmp;
+
+                if (OCTAVE_SCAN (is, *elt, &tmp))
+                  {
+                    if (! discard)
+                      retval = tmp;
+                  }
+                else
+                  quit = true;
+              }
+              break;
+
+            case 'o': case 'u': case 'x':
+              {
+                long int tmp;
+
+                if (OCTAVE_SCAN (is, *elt, &tmp))
+                  {
+                    if (! discard)
+                      retval = tmp;
+                  }
+                else
+                  quit = true;
+              }
+              break;
+
+            case 'e': case 'f': case 'g':
+              {
+                double tmp;
+
+                if (OCTAVE_SCAN (is, *elt, &tmp))
+                  {
+                    if (! discard)
+                      retval = tmp;
+                  }
+                else
+                  quit = true;
+              }
+              break;
+
+            case 'c':
+              {
+                BEGIN_C_CONVERSION ();
+
+                if (! discard)
+                  retval = tmp;
+
+                if (! is)
+                  quit = true;
+
+                is.setf (flags);
+              }
+              break;
+
+            case 's':
+              {
+                BEGIN_S_CONVERSION ();
+
+                if (! discard)
+                  retval = tmp;
+
+                if (! is)
+                  quit = true;
+              }
+              break;
+
+            case '[': case '^':
+              {
+                BEGIN_CHAR_CLASS_CONVERSION ();
+
+                if (! discard)
+                  retval = tmp;
+
+                if (! is)
+                  quit = true;
+              }
+              break;
+
+            case 'p':
+              error ("%s: unsupported format specifier", who.c_str ());
+              break;
+
+            default:
+              error ("%s: internal format error", who.c_str ());
+              break;
+            }
+        }
+
+      if (ok () && is.fail ())
+        {
+          error ("%s: read error", who.c_str ());
+
+          // FIXME -- is this the right thing to do?
+
+          if (interactive && name () == "stdin")
+            {
+              // Skip to end of line.
+
+              bool err;
+              do_gets (-1, err, false, who);
+            }
+        }
+    }
+
+  return quit;
+}
+
+octave_value_list
+octave_base_stream::oscanf (const std::string& fmt, const std::string& who)
+{
+  octave_value_list retval;
+
+  std::istream *isp = input_stream ();
+
+  if (isp)
+    {
+      std::istream& is = *isp;
+
+      scanf_format_list fmt_list (fmt);
+
+      octave_idx_type nconv = fmt_list.num_conversions ();
+
+      if (nconv == -1)
+        ::error ("%s: invalid format specified", who.c_str ());
+      else
+        {
+          is.clear ();
+
+          octave_idx_type len = fmt_list.length ();
+
+          retval.resize (nconv+2, Matrix ());
+
+          const scanf_format_elt *elt = fmt_list.first ();
+
+          int num_values = 0;
+
+          bool quit = false;
+
+          for (octave_idx_type i = 0; i < len; i++)
+            {
+              octave_value tmp;
+
+              quit = do_oscanf (elt, tmp, who);
+
+              if (quit)
+                break;
+              else
+                {
+                  if (tmp.is_defined ())
+                    retval(num_values++) = tmp;
+
+                  if (! ok ())
+                    break;
+
+                  elt = fmt_list.next (nconv > 0);
+                }
+            }
+
+          retval(nconv) = num_values;
+
+          int err_num;
+          retval(nconv+1) = error (false, err_num);
+
+          if (! quit)
+            {
+              // Pick up any trailing stuff.
+              if (ok () && len > nconv)
+                {
+                  octave_value tmp;
+
+                  elt = fmt_list.next ();
+
+                  do_oscanf (elt, tmp, who);
+                }
+            }
+        }
+    }
+  else
+    invalid_operation (who, "reading");
+
+  return retval;
+}
+
+// Functions that are defined for all output streams (output streams
+// are those that define os).
+
+int
+octave_base_stream::flush (void)
+{
+  int retval = -1;
+
+  std::ostream *os = output_stream ();
+
+  if (os)
+    {
+      os->flush ();
+
+      if (os->good ())
+        retval = 0;
+    }
+  else
+    invalid_operation ("fflush", "writing");
+
+  return retval;
+}
+
+class
+printf_value_cache
+{
+public:
+
+  enum state { ok, conversion_error };
+
+  printf_value_cache (const octave_value_list& args, const std::string& who)
+    : values (args), val_idx (0), elt_idx (0),
+      n_vals (values.length ()), n_elts (0), data (0),
+      curr_state (ok)
+  {
+    for (octave_idx_type i = 0; i < values.length (); i++)
+      {
+        octave_value val = values(i);
+
+        if (val.is_map () || val.is_cell () || val.is_object ())
+          {
+            gripe_wrong_type_arg (who, val);
+            break;
+          }
+      }
+  }
+
+  ~printf_value_cache (void) { }
+
+  // Get the current value as a double and advance the internal pointer.
+  double double_value (void);
+
+  // Get the current value as an int and advance the internal pointer.
+  int int_value (void);
+
+  // Get the current value as a string and advance the internal pointer.
+  std::string string_value (void);
+
+  operator bool () const { return (curr_state == ok); }
+
+  bool exhausted (void) { return (val_idx >= n_vals); }
+
+private:
+
+  const octave_value_list values;
+  int val_idx;
+  int elt_idx;
+  int n_vals;
+  int n_elts;
+  const double *data;
+  NDArray curr_val;
+  state curr_state;
+
+  // Must create value cache with values!
+
+  printf_value_cache (void);
+
+  // No copying!
+
+  printf_value_cache (const printf_value_cache&);
+
+  printf_value_cache& operator = (const printf_value_cache&);
+};
+
+double
+printf_value_cache::double_value (void)
+{
+  double retval = 0.0;
+
+  if (exhausted ())
+    curr_state = conversion_error;
+
+  while (! exhausted ())
+    {
+      if (! data)
+        {
+          octave_value tmp_val = values (val_idx);
+
+          // Force string conversion here for compatibility.
+
+          curr_val = tmp_val.array_value (true);
+
+          if (! error_state)
+            {
+              elt_idx = 0;
+              n_elts = curr_val.length ();
+              data = curr_val.data ();
+            }
+          else
+            {
+              curr_state = conversion_error;
+              break;
+            }
+        }
+
+      if (elt_idx < n_elts)
+        {
+          retval = data[elt_idx++];
+
+          if (elt_idx >= n_elts)
+            {
+              elt_idx = 0;
+              val_idx++;
+              data = 0;
+            }
+
+          break;
+        }
+      else
+        {
+          val_idx++;
+          data = 0;
+
+          if (n_elts == 0 && exhausted ())
+            curr_state = conversion_error;
+
+          continue;
+        }
+    }
+
+  return retval;
+}
+
+int
+printf_value_cache::int_value (void)
+{
+  int retval = 0;
+
+  double dval = double_value ();
+
+  if (! error_state)
+    {
+      if (D_NINT (dval) == dval)
+        retval = NINT (dval);
+      else
+        curr_state = conversion_error;
+    }
+
+  return retval;
+}
+
+std::string
+printf_value_cache::string_value (void)
+{
+  std::string retval;
+
+  if (exhausted ())
+    curr_state = conversion_error;
+  else
+    {
+      octave_value tval = values (val_idx++);
+
+      if (tval.rows () == 1)
+        retval = tval.string_value ();
+      else
+        {
+          // In the name of Matlab compatibility.
+
+          charMatrix chm = tval.char_matrix_value ();
+
+          octave_idx_type nr = chm.rows ();
+          octave_idx_type nc = chm.columns ();
+
+          int k = 0;
+
+          retval.resize (nr * nc, '\0');
+
+          for (octave_idx_type j = 0; j < nc; j++)
+            for (octave_idx_type i = 0; i < nr; i++)
+              retval[k++] = chm(i,j);
+        }
+
+      if (error_state)
+        curr_state = conversion_error;
+    }
+
+  return retval;
+}
+
+// Ugh again and again.
+
+template <class T>
+int
+do_printf_conv (std::ostream& os, const char *fmt, int nsa, int sa_1,
+                int sa_2, T arg, const std::string& who)
+{
+  int retval = 0;
+
+  switch (nsa)
+    {
+    case 2:
+      retval = octave_format (os, fmt, sa_1, sa_2, arg);
+      break;
+
+    case 1:
+      retval = octave_format (os, fmt, sa_1, arg);
+      break;
+
+    case 0:
+      retval = octave_format (os, fmt, arg);
+      break;
+
+    default:
+      ::error ("%s: internal error handling format", who.c_str ());
+      break;
+    }
+
+  return retval;
+}
+
+template int
+do_printf_conv (std::ostream&, const char*, int, int, int, int,
+                const std::string&);
+
+template int
+do_printf_conv (std::ostream&, const char*, int, int, int, long,
+                const std::string&);
+
+template int
+do_printf_conv (std::ostream&, const char*, int, int, int, unsigned int,
+                const std::string&);
+
+template int
+do_printf_conv (std::ostream&, const char*, int, int, int, unsigned long,
+                const std::string&);
+
+template int
+do_printf_conv (std::ostream&, const char*, int, int, int, double,
+                const std::string&);
+
+template int
+do_printf_conv (std::ostream&, const char*, int, int, int, const char*,
+                const std::string&);
+
+#define DO_DOUBLE_CONV(TQUAL) \
+  do \
+    { \
+      if (val > std::numeric_limits<TQUAL long>::max () \
+          || val < std::numeric_limits<TQUAL long>::min ()) \
+        { \
+          std::string tfmt = fmt; \
+ \
+          tfmt.replace (tfmt.rfind (elt->type), 1, ".f"); \
+ \
+          if (elt->modifier == 'l') \
+            tfmt.replace (tfmt.rfind (elt->modifier), 1, ""); \
+ \
+          retval += do_printf_conv (os, tfmt.c_str (), nsa, sa_1, sa_2, \
+                                    val, who); \
+        } \
+      else \
+        retval += do_printf_conv (os, fmt, nsa, sa_1, sa_2, \
+                                  static_cast<TQUAL long> (val), who); \
+    } \
+  while (0)
+
+int
+octave_base_stream::do_printf (printf_format_list& fmt_list,
+                               const octave_value_list& args,
+                               const std::string& who)
+{
+  int retval = 0;
+
+  octave_idx_type nconv = fmt_list.num_conversions ();
+
+  std::ostream *osp = output_stream ();
+
+  if (osp)
+    {
+      std::ostream& os = *osp;
+
+      const printf_format_elt *elt = fmt_list.first ();
+
+      printf_value_cache val_cache (args, who);
+
+      if (error_state)
+        return retval;
+
+      for (;;)
+        {
+          octave_quit ();
+
+          if (elt)
+            {
+              // NSA is the number of `star' args to convert.
+
+              int nsa = (elt->fw < 0) + (elt->prec < 0);
+
+              int sa_1 = 0;
+              int sa_2 = 0;
+
+              if (nsa > 0)
+                {
+                  sa_1 = val_cache.int_value ();
+
+                  if (! val_cache)
+                    break;
+                  else
+                    {
+                      if (nsa > 1)
+                        {
+                          sa_2 = val_cache.int_value ();
+
+                          if (! val_cache)
+                            break;
+                        }
+                    }
+                }
+
+              const char *fmt = elt->text;
+
+              if (elt->type == '%')
+                {
+                  os << "%";
+                  retval++;
+                }
+              else if (elt->args == 0 && elt->text)
+                {
+                  os << elt->text;
+                  retval += strlen (elt->text);
+                }
+              else if (elt->type == 's')
+                {
+                  std::string val = val_cache.string_value ();
+
+                  if (val_cache)
+                    retval += do_printf_conv (os, fmt, nsa, sa_1,
+                                              sa_2, val.c_str (), who);
+                  else
+                    break;
+                }
+              else
+                {
+                  double val = val_cache.double_value ();
+
+                  if (val_cache)
+                    {
+                      if (lo_ieee_isnan (val) || xisinf (val))
+                        {
+                          std::string tfmt = fmt;
+                          std::string::size_type i1, i2;
+
+                          tfmt.replace ((i1 = tfmt.rfind (elt->type)),
+                                        1, 1, 's');
+
+                          if ((i2 = tfmt.rfind ('.')) != std::string::npos && i2 < i1)
+                            {
+                              tfmt.erase (i2, i1-i2);
+                              if (elt->prec < 0)
+                                nsa--;
+                            }
+
+                          const char *tval = xisinf (val)
+                            ? (val < 0 ? "-Inf" : "Inf")
+                            : (lo_ieee_is_NA (val) ? "NA" : "NaN");
+
+                          retval += do_printf_conv (os, tfmt.c_str (),
+                                                    nsa, sa_1, sa_2,
+                                                    tval, who);
+                        }
+                      else
+                        {
+                          char type = elt->type;
+
+                          switch (type)
+                            {
+                            case 'd': case 'i': case 'c':
+                              DO_DOUBLE_CONV (OCTAVE_EMPTY_CPP_ARG);
+                              break;
+
+                            case 'o': case 'x': case 'X': case 'u':
+                              DO_DOUBLE_CONV (unsigned);
+                              break;
+
+                            case 'f': case 'e': case 'E':
+                            case 'g': case 'G':
+                              retval
+                                += do_printf_conv (os, fmt, nsa, sa_1, sa_2,
+                                                   val, who);
+                              break;
+
+                            default:
+                              error ("%s: invalid format specifier",
+                                     who.c_str ());
+                              return -1;
+                              break;
+                            }
+                        }
+                    }
+                  else
+                    break;
+                }
+
+              if (! os)
+                {
+                  error ("%s: write error", who.c_str ());
+                  break;
+                }
+            }
+          else
+            {
+              ::error ("%s: internal error handling format", who.c_str ());
+              retval = -1;
+              break;
+            }
+
+          elt = fmt_list.next (nconv > 0 && ! val_cache.exhausted ());
+
+          if (! elt || (val_cache.exhausted () && elt->args > 0))
+            break;
+        }
+    }
+  else
+    invalid_operation (who, "writing");
+
+  return retval;
+}
+
+int
+octave_base_stream::printf (const std::string& fmt,
+                            const octave_value_list& args,
+                            const std::string& who)
+{
+  int retval = 0;
+
+  printf_format_list fmt_list (fmt);
+
+  if (fmt_list.num_conversions () == -1)
+    ::error ("%s: invalid format specified", who.c_str ());
+  else
+    retval = do_printf (fmt_list, args, who);
+
+  return retval;
+}
+
+int
+octave_base_stream::puts (const std::string& s, const std::string& who)
+{
+  int retval = -1;
+
+  std::ostream *osp = output_stream ();
+
+  if (osp)
+    {
+      std::ostream& os = *osp;
+
+      os << s;
+
+      if (os)
+        {
+          // FIXME -- why does this seem to be necessary?
+          // Without it, output from a loop like
+          //
+          //   for i = 1:100, fputs (stdout, "foo\n"); endfor
+          //
+          // doesn't seem to go to the pager immediately.
+
+          os.flush ();
+
+          if (os)
+            retval = 0;
+          else
+            error ("%s: write error", who.c_str ());
+        }
+      else
+        error ("%s: write error", who.c_str ());
+    }
+  else
+    invalid_operation (who, "writing");
+
+  return retval;
+}
+
+// Return current error message for this stream.
+
+std::string
+octave_base_stream::error (bool clear_err, int& err_num)
+{
+  err_num = fail ? -1 : 0;
+
+  std::string tmp = errmsg;
+
+  if (clear_err)
+    clear ();
+
+  return tmp;
+}
+
+void
+octave_base_stream::invalid_operation (const std::string& who, const char *rw)
+{
+  // Note that this is not ::error () !
+
+  error (who, std::string ("stream not open for ") + rw);
+}
+
+octave_stream::octave_stream (octave_base_stream *bs)
+  : rep (bs)
+{
+  if (rep)
+    rep->count = 1;
+}
+
+octave_stream::~octave_stream (void)
+{
+  if (rep && --rep->count == 0)
+    delete rep;
+}
+
+octave_stream::octave_stream (const octave_stream& s)
+  : rep (s.rep)
+{
+  if (rep)
+    rep->count++;
+}
+
+octave_stream&
+octave_stream::operator = (const octave_stream& s)
+{
+  if (rep != s.rep)
+    {
+      if (rep && --rep->count == 0)
+        delete rep;
+
+      rep = s.rep;
+
+      if (rep)
+        rep->count++;
+    }
+
+  return *this;
+}
+
+int
+octave_stream::flush (void)
+{
+  int retval = -1;
+
+  if (stream_ok ())
+    retval = rep->flush ();
+
+  return retval;
+}
+
+std::string
+octave_stream::getl (octave_idx_type max_len, bool& err, const std::string& who)
+{
+  std::string retval;
+
+  if (stream_ok ())
+    retval = rep->getl (max_len, err, who);
+
+  return retval;
+}
+
+std::string
+octave_stream::getl (const octave_value& tc_max_len, bool& err,
+                     const std::string& who)
+{
+  std::string retval;
+
+  err = false;
+
+  int conv_err = 0;
+
+  int max_len = -1;
+
+  if (tc_max_len.is_defined ())
+    {
+      max_len = convert_to_valid_int (tc_max_len, conv_err);
+
+      if (conv_err || max_len < 0)
+        {
+          err = true;
+          ::error ("%s: invalid maximum length specified", who.c_str ());
+        }
+    }
+
+  if (! error_state)
+    retval = getl (max_len, err, who);
+
+  return retval;
+}
+
+std::string
+octave_stream::gets (octave_idx_type max_len, bool& err, const std::string& who)
+{
+  std::string retval;
+
+  if (stream_ok ())
+    retval = rep->gets (max_len, err, who);
+
+  return retval;
+}
+
+std::string
+octave_stream::gets (const octave_value& tc_max_len, bool& err,
+                     const std::string& who)
+{
+  std::string retval;
+
+  err = false;
+
+  int conv_err = 0;
+
+  int max_len = -1;
+
+  if (tc_max_len.is_defined ())
+    {
+      max_len = convert_to_valid_int (tc_max_len, conv_err);
+
+      if (conv_err || max_len < 0)
+        {
+          err = true;
+          ::error ("%s: invalid maximum length specified", who.c_str ());
+        }
+    }
+
+  if (! error_state)
+    retval = gets (max_len, err, who);
+
+  return retval;
+}
+
+long
+octave_stream::skipl (long count, bool& err, const std::string& who)
+{
+  long retval = -1;
+
+  if (stream_ok ())
+    retval = rep->skipl (count, err, who);
+
+  return retval;
+}
+
+long
+octave_stream::skipl (const octave_value& tc_count, bool& err, const std::string& who)
+{
+  long retval = -1;
+
+  err = false;
+
+  int conv_err = 0;
+
+  int count = 1;
+
+  if (tc_count.is_defined ())
+    {
+      if (tc_count.is_scalar_type () && xisinf (tc_count.scalar_value ()))
+        count = -1;
+      else
+        {
+          count = convert_to_valid_int (tc_count, conv_err);
+
+          if (conv_err || count < 0)
+            {
+              err = true;
+              ::error ("%s: invalid number of lines specified", who.c_str ());
+            }
+        }
+    }
+
+  if (! error_state)
+    retval = skipl (count, err, who);
+
+  return retval;
+}
+
+int
+octave_stream::seek (long offset, int origin)
+{
+  int status = -1;
+
+  if (stream_ok ())
+    {
+      clearerr ();
+
+      // Find current position so we can return to it if needed.
+
+      long orig_pos = rep->tell ();
+
+      // Move to end of file.  If successful, find the offset of the end.
+
+      status = rep->seek (0, SEEK_END);
+
+      if (status == 0)
+        {
+          long eof_pos = rep->tell ();
+
+          if (origin == SEEK_CUR)
+            {
+              // Move back to original position, otherwise we will be
+              // seeking from the end of file which is probably not the
+              // original location.
+
+              rep->seek (orig_pos, SEEK_SET);
+            }
+
+          // Attempt to move to desired position; may be outside bounds
+          // of existing file.
+
+          status = rep->seek (offset, origin);
+
+          if (status == 0)
+            {
+              // Where are we after moving to desired position?
+
+              long desired_pos = rep->tell ();
+
+              // I don't think save_pos can be less than zero, but we'll
+              // check anyway...
+
+              if (desired_pos > eof_pos || desired_pos < 0)
+                {
+                  // Seek outside bounds of file.  Failure should leave
+                  // position unchanged.
+
+                  rep->seek (orig_pos, SEEK_SET);
+
+                  status = -1;
+                }
+            }
+          else
+            {
+              // Seeking to the desired position failed.  Move back to
+              // original position and return failure status.
+
+              rep->seek (orig_pos, SEEK_SET);
+
+              status = -1;
+            }
+        }
+    }
+
+  return status;
+}
+
+int
+octave_stream::seek (const octave_value& tc_offset,
+                     const octave_value& tc_origin)
+{
+  int retval = -1;
+
+  long xoffset = tc_offset.long_value (true);
+
+  if (! error_state)
+    {
+      int conv_err = 0;
+
+      int origin = SEEK_SET;
+
+      if (tc_origin.is_string ())
+        {
+          std::string xorigin = tc_origin.string_value ();
+
+          if (xorigin == "bof")
+            origin = SEEK_SET;
+          else if (xorigin == "cof")
+            origin = SEEK_CUR;
+          else if (xorigin == "eof")
+            origin = SEEK_END;
+          else
+            conv_err = -1;
+        }
+      else
+        {
+          int xorigin = convert_to_valid_int (tc_origin, conv_err);
+
+          if (! conv_err)
+            {
+              if (xorigin == -1)
+                origin = SEEK_SET;
+              else if (xorigin == 0)
+                origin = SEEK_CUR;
+              else if (xorigin == 1)
+                origin = SEEK_END;
+              else
+                conv_err = -1;
+            }
+        }
+
+      if (! conv_err)
+        {
+          retval = seek (xoffset, origin);
+
+          if (retval != 0)
+            error ("fseek: failed to seek to requested position");
+        }
+      else
+        error ("fseek: invalid value for origin");
+    }
+  else
+    error ("fseek: invalid value for offset");
+
+  return retval;
+}
+
+long
+octave_stream::tell (void)
+{
+  long retval = -1;
+
+  if (stream_ok ())
+    retval = rep->tell ();
+
+  return retval;
+}
+
+int
+octave_stream::rewind (void)
+{
+  return seek (0, SEEK_SET);
+}
+
+bool
+octave_stream::is_open (void) const
+{
+  bool retval = false;
+
+  if (stream_ok ())
+    retval = rep->is_open ();
+
+  return retval;
+}
+
+void
+octave_stream::close (void)
+{
+  if (stream_ok ())
+    rep->close ();
+}
+
+template <class RET_T, class READ_T>
+octave_value
+do_read (octave_stream& strm, octave_idx_type nr, octave_idx_type nc, octave_idx_type block_size,
+         octave_idx_type skip, bool do_float_fmt_conv, bool do_NA_conv,
+         oct_mach_info::float_format from_flt_fmt, octave_idx_type& count)
+{
+  octave_value retval;
+
+  RET_T nda;
+
+  count = 0;
+
+  typedef typename RET_T::element_type ELMT;
+  ELMT elt_zero = ELMT ();
+
+  ELMT *dat = 0;
+
+  octave_idx_type max_size = 0;
+
+  octave_idx_type final_nr = 0;
+  octave_idx_type final_nc = 1;
+
+  if (nr > 0)
+    {
+      if (nc > 0)
+        {
+          nda.resize (dim_vector (nr, nc), elt_zero);
+          dat = nda.fortran_vec ();
+          max_size = nr * nc;
+        }
+      else
+        {
+          nda.resize (dim_vector (nr, 32), elt_zero);
+          dat = nda.fortran_vec ();
+          max_size = nr * 32;
+        }
+    }
+  else
+    {
+      nda.resize (dim_vector (32, 1), elt_zero);
+      dat = nda.fortran_vec ();
+      max_size = 32;
+    }
+
+  // FIXME -- byte order for Cray?
+
+  bool swap = false;
+
+  if (oct_mach_info::words_big_endian ())
+    swap = (from_flt_fmt == oct_mach_info::flt_fmt_ieee_little_endian
+            || from_flt_fmt == oct_mach_info::flt_fmt_vax_g
+            || from_flt_fmt == oct_mach_info::flt_fmt_vax_g);
+  else
+    swap = (from_flt_fmt == oct_mach_info::flt_fmt_ieee_big_endian);
+
+  union
+  {
+    char buf[sizeof (typename strip_template_param<octave_int, READ_T>::type)];
+    typename strip_template_param<octave_int, READ_T>::type val;
+  } u;
+
+  std::istream *isp = strm.input_stream ();
+
+  if (isp)
+    {
+      std::istream& is = *isp;
+
+      octave_idx_type elts_read = 0;
+
+      for (;;)
+        {
+          // FIXME -- maybe there should be a special case for
+          // skip == 0.
+
+          if (is)
+            {
+              if (nr > 0 && nc > 0 && count == max_size)
+                {
+                  final_nr = nr;
+                  final_nc = nc;
+
+                  break;
+                }
+
+              is.read (u.buf, sizeof (typename strip_template_param<octave_int, READ_T>::type));
+
+              // We only swap bytes for integer types.  For float
+              // types, the format conversion will also handle byte
+              // swapping.
+
+              if (swap)
+                swap_bytes<sizeof (typename strip_template_param<octave_int, READ_T>::type)> (u.buf);
+              else if (do_float_fmt_conv)
+                do_float_format_conversion
+                  (u.buf,
+                   sizeof (typename strip_template_param<octave_int, READ_T>::type),
+                   1, from_flt_fmt, oct_mach_info::float_format ());
+
+              typename RET_T::element_type tmp
+                = static_cast <typename RET_T::element_type> (u.val);
+
+              if (is)
+                {
+                  if (count == max_size)
+                    {
+                      max_size *= 2;
+
+                      if (nr > 0)
+                        nda.resize (dim_vector (nr, max_size / nr),
+                                    elt_zero);
+                      else
+                        nda.resize (dim_vector (max_size, 1), elt_zero);
+
+                      dat = nda.fortran_vec ();
+                    }
+
+                  if (do_NA_conv && __lo_ieee_is_old_NA (tmp))
+                    tmp = __lo_ieee_replace_old_NA (tmp);
+
+                  dat[count++] = tmp;
+
+                  elts_read++;
+                }
+
+              int seek_status = 0;
+
+              if (skip != 0 && elts_read == block_size)
+                {
+                  seek_status = strm.seek (skip, SEEK_CUR);
+                  elts_read = 0;
+                }
+
+              if (is.eof () || seek_status < 0)
+                {
+                  if (nr > 0)
+                    {
+                      if (count > nr)
+                        {
+                          final_nr = nr;
+                          final_nc = (count - 1) / nr + 1;
+                        }
+                      else
+                        {
+                          final_nr = count;
+                          final_nc = 1;
+                        }
+                    }
+                  else
+                    {
+                      final_nr = count;
+                      final_nc = 1;
+                    }
+
+                  break;
+                }
+            }
+          else if (is.eof ())
+            break;
+        }
+    }
+
+  nda.resize (dim_vector (final_nr, final_nc), elt_zero);
+
+  retval = nda;
+
+  return retval;
+}
+
+#define DO_READ_VAL_TEMPLATE(RET_T, READ_T) \
+  template octave_value \
+  do_read<RET_T, READ_T> (octave_stream&, octave_idx_type, octave_idx_type, octave_idx_type, octave_idx_type, bool, bool, \
+                          oct_mach_info::float_format, octave_idx_type&)
+
+// FIXME -- should we only have float if it is a different
+// size from double?
+
+#define INSTANTIATE_DO_READ(VAL_T) \
+  DO_READ_VAL_TEMPLATE (VAL_T, octave_int8); \
+  DO_READ_VAL_TEMPLATE (VAL_T, octave_uint8); \
+  DO_READ_VAL_TEMPLATE (VAL_T, octave_int16); \
+  DO_READ_VAL_TEMPLATE (VAL_T, octave_uint16); \
+  DO_READ_VAL_TEMPLATE (VAL_T, octave_int32); \
+  DO_READ_VAL_TEMPLATE (VAL_T, octave_uint32); \
+  DO_READ_VAL_TEMPLATE (VAL_T, octave_int64); \
+  DO_READ_VAL_TEMPLATE (VAL_T, octave_uint64); \
+  DO_READ_VAL_TEMPLATE (VAL_T, float); \
+  DO_READ_VAL_TEMPLATE (VAL_T, double); \
+  DO_READ_VAL_TEMPLATE (VAL_T, char); \
+  DO_READ_VAL_TEMPLATE (VAL_T, signed char); \
+  DO_READ_VAL_TEMPLATE (VAL_T, unsigned char)
+
+INSTANTIATE_DO_READ (int8NDArray);
+INSTANTIATE_DO_READ (uint8NDArray);
+INSTANTIATE_DO_READ (int16NDArray);
+INSTANTIATE_DO_READ (uint16NDArray);
+INSTANTIATE_DO_READ (int32NDArray);
+INSTANTIATE_DO_READ (uint32NDArray);
+INSTANTIATE_DO_READ (int64NDArray);
+INSTANTIATE_DO_READ (uint64NDArray);
+INSTANTIATE_DO_READ (FloatNDArray);
+INSTANTIATE_DO_READ (NDArray);
+INSTANTIATE_DO_READ (charNDArray);
+INSTANTIATE_DO_READ (boolNDArray);
+
+typedef octave_value (*read_fptr) (octave_stream&, octave_idx_type, octave_idx_type, octave_idx_type, octave_idx_type, bool, bool,
+                                   oct_mach_info::float_format ffmt, octave_idx_type&);
+
+#define FILL_TABLE_ROW(R, VAL_T) \
+  read_fptr_table[R][oct_data_conv::dt_int8] = do_read<VAL_T, octave_int8>; \
+  read_fptr_table[R][oct_data_conv::dt_uint8] = do_read<VAL_T, octave_uint8>; \
+  read_fptr_table[R][oct_data_conv::dt_int16] = do_read<VAL_T, octave_int16>; \
+  read_fptr_table[R][oct_data_conv::dt_uint16] = do_read<VAL_T, octave_uint16>; \
+  read_fptr_table[R][oct_data_conv::dt_int32] = do_read<VAL_T, octave_int32>; \
+  read_fptr_table[R][oct_data_conv::dt_uint32] = do_read<VAL_T, octave_uint32>; \
+  read_fptr_table[R][oct_data_conv::dt_int64] = do_read<VAL_T, octave_int64>; \
+  read_fptr_table[R][oct_data_conv::dt_uint64] = do_read<VAL_T, octave_uint64>; \
+  read_fptr_table[R][oct_data_conv::dt_single] = do_read<VAL_T, float>; \
+  read_fptr_table[R][oct_data_conv::dt_double] = do_read<VAL_T, double>; \
+  read_fptr_table[R][oct_data_conv::dt_char] = do_read<VAL_T, char>; \
+  read_fptr_table[R][oct_data_conv::dt_schar] = do_read<VAL_T, signed char>; \
+  read_fptr_table[R][oct_data_conv::dt_uchar] = do_read<VAL_T, unsigned char>; \
+  read_fptr_table[R][oct_data_conv::dt_logical] = do_read<VAL_T, unsigned char>
+
+octave_value
+octave_stream::read (const Array<double>& size, octave_idx_type block_size,
+                     oct_data_conv::data_type input_type,
+                     oct_data_conv::data_type output_type,
+                     octave_idx_type skip, oct_mach_info::float_format ffmt,
+                     octave_idx_type& char_count)
+{
+  static bool initialized = false;
+
+  // Table function pointers for return types x read types.
+
+  static read_fptr read_fptr_table[oct_data_conv::dt_unknown][14];
+
+  if (! initialized)
+    {
+      for (int i = 0; i < oct_data_conv::dt_unknown; i++)
+        for (int j = 0; j < 14; j++)
+          read_fptr_table[i][j] = 0;
+
+      FILL_TABLE_ROW (oct_data_conv::dt_int8, int8NDArray);
+      FILL_TABLE_ROW (oct_data_conv::dt_uint8, uint8NDArray);
+      FILL_TABLE_ROW (oct_data_conv::dt_int16, int16NDArray);
+      FILL_TABLE_ROW (oct_data_conv::dt_uint16, uint16NDArray);
+      FILL_TABLE_ROW (oct_data_conv::dt_int32, int32NDArray);
+      FILL_TABLE_ROW (oct_data_conv::dt_uint32, uint32NDArray);
+      FILL_TABLE_ROW (oct_data_conv::dt_int64, int64NDArray);
+      FILL_TABLE_ROW (oct_data_conv::dt_uint64, uint64NDArray);
+      FILL_TABLE_ROW (oct_data_conv::dt_single, FloatNDArray);
+      FILL_TABLE_ROW (oct_data_conv::dt_double, NDArray);
+      FILL_TABLE_ROW (oct_data_conv::dt_char, charNDArray);
+      FILL_TABLE_ROW (oct_data_conv::dt_schar, charNDArray);
+      FILL_TABLE_ROW (oct_data_conv::dt_uchar, charNDArray);
+      FILL_TABLE_ROW (oct_data_conv::dt_logical, boolNDArray);
+
+      initialized = true;
+    }
+
+  octave_value retval;
+
+  if (stream_ok ())
+    {
+      // FIXME -- we may eventually want to make this extensible.
+
+      // FIXME -- we need a better way to ensure that this
+      // numbering stays consistent with the order of the elements in the
+      // data_type enum in the oct_data_conv class.
+
+      char_count = 0;
+
+      octave_idx_type nr = -1;
+      octave_idx_type nc = -1;
+
+      bool ignore;
+
+      get_size (size, nr, nc, ignore, "fread");
+
+      if (! error_state)
+        {
+          if (nr == 0 || nc == 0)
+            retval = Matrix (nr, nc);
+          else
+            {
+              if (ffmt == oct_mach_info::flt_fmt_unknown)
+                ffmt = float_format ();
+
+              read_fptr fcn = read_fptr_table[output_type][input_type];
+
+              bool do_float_fmt_conv = ((input_type == oct_data_conv::dt_double
+                                         || input_type == oct_data_conv::dt_single)
+                                        && ffmt != float_format ());
+
+              bool do_NA_conv = (output_type == oct_data_conv::dt_double);
+
+              if (fcn)
+                {
+                  retval = (*fcn) (*this, nr, nc, block_size, skip,
+                                   do_float_fmt_conv, do_NA_conv,
+                                   ffmt, char_count);
+
+                  // FIXME -- kluge!
+
+                  if (! error_state
+                      && (output_type == oct_data_conv::dt_char
+                          || output_type == oct_data_conv::dt_schar
+                          || output_type == oct_data_conv::dt_uchar))
+                    retval = retval.char_matrix_value ();
+                }
+              else
+                error ("fread: unable to read and convert requested types");
+            }
+        }
+      else
+        invalid_operation ("fread", "reading");
+    }
+
+  return retval;
+}
+
+octave_idx_type
+octave_stream::write (const octave_value& data, octave_idx_type block_size,
+                      oct_data_conv::data_type output_type, octave_idx_type skip,
+                      oct_mach_info::float_format flt_fmt)
+{
+  octave_idx_type retval = -1;
+
+  if (stream_ok ())
+    {
+      if (! error_state)
+        {
+          if (flt_fmt == oct_mach_info::flt_fmt_unknown)
+            flt_fmt = float_format ();
+
+          octave_idx_type status = data.write (*this, block_size, output_type,
+                                   skip, flt_fmt);
+
+          if (status < 0)
+            error ("fwrite: write error");
+          else
+            retval = status;
+        }
+      else
+        invalid_operation ("fwrite", "writing");
+    }
+
+  return retval;
+}
+
+template <class T>
+void
+write_int (std::ostream& os, bool swap, const T& val)
+{
+  typename T::val_type tmp = val.value ();
+
+  if (swap)
+    swap_bytes<sizeof (typename T::val_type)> (&tmp);
+
+  os.write (reinterpret_cast<const char *> (&tmp),
+            sizeof (typename T::val_type));
+}
+
+template void write_int (std::ostream&, bool, const octave_int8&);
+template void write_int (std::ostream&, bool, const octave_uint8&);
+template void write_int (std::ostream&, bool, const octave_int16&);
+template void write_int (std::ostream&, bool, const octave_uint16&);
+template void write_int (std::ostream&, bool, const octave_int32&);
+template void write_int (std::ostream&, bool, const octave_uint32&);
+template void write_int (std::ostream&, bool, const octave_int64&);
+template void write_int (std::ostream&, bool, const octave_uint64&);
+
+template <class T>
+static inline bool
+do_write (std::ostream& os, const T& val, oct_data_conv::data_type output_type,
+          oct_mach_info::float_format flt_fmt, bool swap,
+          bool do_float_conversion)
+{
+  bool retval = true;
+
+  // For compatibility, Octave converts to the output type, then
+  // writes.  This means that truncation happens on the conversion.
+  // For example, the following program prints 0:
+  //
+  //   x = int8 (-1)
+  //   f = fopen ("foo.dat", "w");
+  //   fwrite (f, x, "unsigned char");
+  //   fclose (f);
+  //   f = fopen ("foo.dat", "r");
+  //   y = fread (f, 1, "unsigned char");
+  //   printf ("%d\n", y);
+
+  switch (output_type)
+    {
+    case oct_data_conv::dt_char:
+    case oct_data_conv::dt_schar:
+    case oct_data_conv::dt_int8:
+      write_int (os, swap, octave_int8 (val));
+      break;
+
+    case oct_data_conv::dt_uchar:
+    case oct_data_conv::dt_uint8:
+      write_int (os, swap, octave_uint8 (val));
+      break;
+
+    case oct_data_conv::dt_int16:
+      write_int (os, swap, octave_int16 (val));
+      break;
+
+    case oct_data_conv::dt_uint16:
+      write_int (os, swap, octave_uint16 (val));
+      break;
+
+    case oct_data_conv::dt_int32:
+      write_int (os, swap, octave_int32 (val));
+      break;
+
+    case oct_data_conv::dt_uint32:
+      write_int (os, swap, octave_uint32 (val));
+      break;
+
+    case oct_data_conv::dt_int64:
+      write_int (os, swap, octave_int64 (val));
+      break;
+
+    case oct_data_conv::dt_uint64:
+      write_int (os, swap, octave_uint64 (val));
+      break;
+
+    case oct_data_conv::dt_single:
+      {
+        float f = static_cast<float> (val);
+
+        if (do_float_conversion)
+          do_float_format_conversion (&f, 1, flt_fmt);
+
+        os.write (reinterpret_cast<const char *> (&f), sizeof (float));
+      }
+      break;
+
+    case oct_data_conv::dt_double:
+      {
+        double d = static_cast<double> (val);
+        if (do_float_conversion)
+          do_double_format_conversion (&d, 1, flt_fmt);
+
+        os.write (reinterpret_cast<const char *> (&d), sizeof (double));
+      }
+      break;
+
+    default:
+      retval = false;
+      (*current_liboctave_error_handler)
+        ("write: invalid type specification");
+      break;
+    }
+
+  return retval;
+}
+
+template bool
+do_write (std::ostream&, const octave_int8&, oct_data_conv::data_type,
+          oct_mach_info::float_format, bool, bool);
+
+template bool
+do_write (std::ostream&, const octave_uint8&, oct_data_conv::data_type,
+          oct_mach_info::float_format, bool, bool);
+
+template bool
+do_write (std::ostream&, const octave_int16&, oct_data_conv::data_type,
+          oct_mach_info::float_format, bool, bool);
+
+template bool
+do_write (std::ostream&, const octave_uint16&, oct_data_conv::data_type,
+          oct_mach_info::float_format, bool, bool);
+
+template bool
+do_write (std::ostream&, const octave_int32&, oct_data_conv::data_type,
+          oct_mach_info::float_format, bool, bool);
+
+template bool
+do_write (std::ostream&, const octave_uint32&, oct_data_conv::data_type,
+          oct_mach_info::float_format, bool, bool);
+
+template bool
+do_write (std::ostream&, const octave_int64&, oct_data_conv::data_type,
+          oct_mach_info::float_format, bool, bool);
+
+template bool
+do_write (std::ostream&, const octave_uint64&, oct_data_conv::data_type,
+          oct_mach_info::float_format, bool, bool);
+
+template <class T>
+octave_idx_type
+octave_stream::write (const Array<T>& data, octave_idx_type block_size,
+                      oct_data_conv::data_type output_type,
+                      octave_idx_type skip, oct_mach_info::float_format flt_fmt)
+{
+  octave_idx_type retval = -1;
+
+  bool status = true;
+
+  octave_idx_type count = 0;
+
+  const T *d = data.data ();
+
+  octave_idx_type n = data.length ();
+
+  oct_mach_info::float_format native_flt_fmt
+    = oct_mach_info::float_format ();
+
+  bool do_float_conversion = (flt_fmt != native_flt_fmt);
+
+  // FIXME -- byte order for Cray?
+
+  bool swap = false;
+
+  if (oct_mach_info::words_big_endian ())
+    swap = (flt_fmt == oct_mach_info::flt_fmt_ieee_little_endian
+            || flt_fmt == oct_mach_info::flt_fmt_vax_g
+            || flt_fmt == oct_mach_info::flt_fmt_vax_g);
+  else
+    swap = (flt_fmt == oct_mach_info::flt_fmt_ieee_big_endian);
+
+  for (octave_idx_type i = 0; i < n; i++)
+    {
+      std::ostream *osp = output_stream ();
+
+      if (osp)
+        {
+          std::ostream& os = *osp;
+
+          if (skip != 0 && (i % block_size) == 0)
+            {
+              // Seek to skip when inside bounds of existing file.
+              // Otherwise, write NUL to skip.
+
+              long orig_pos = tell ();
+
+              seek (0, SEEK_END);
+
+              long eof_pos = tell ();
+
+              // Is it possible for this to fail to return us to the
+              // original position?
+              seek (orig_pos, SEEK_SET);
+
+              long remaining = eof_pos - orig_pos;
+
+              if (remaining < skip)
+                {
+                  seek (0, SEEK_END);
+
+                  // FIXME -- probably should try to write larger
+                  // blocks...
+
+                  unsigned char zero = 0;
+                  for (octave_idx_type j = 0; j < skip - remaining; j++)
+                    os.write (reinterpret_cast<const char *> (&zero), 1);
+                }
+              else
+                seek (skip, SEEK_CUR);
+            }
+
+          if (os)
+            {
+              status = do_write (os, d[i], output_type, flt_fmt, swap,
+                                 do_float_conversion);
+
+              if (os && status)
+                count++;
+              else
+                break;
+            }
+          else
+            {
+              status = false;
+              break;
+            }
+        }
+      else
+        {
+          status = false;
+          break;
+        }
+    }
+
+  if (status)
+    retval = count;
+
+  return retval;
+}
+
+template octave_idx_type
+octave_stream::write (const Array<char>&, octave_idx_type,
+                      oct_data_conv::data_type,
+                      octave_idx_type, oct_mach_info::float_format);
+
+template octave_idx_type
+octave_stream::write (const Array<bool>&, octave_idx_type,
+                      oct_data_conv::data_type,
+                      octave_idx_type, oct_mach_info::float_format);
+
+template octave_idx_type
+octave_stream::write (const Array<double>&, octave_idx_type,
+                      oct_data_conv::data_type,
+                      octave_idx_type, oct_mach_info::float_format);
+
+template octave_idx_type
+octave_stream::write (const Array<float>&, octave_idx_type,
+                      oct_data_conv::data_type,
+                      octave_idx_type, oct_mach_info::float_format);
+
+template octave_idx_type
+octave_stream::write (const Array<octave_int8>&, octave_idx_type,
+                      oct_data_conv::data_type,
+                      octave_idx_type, oct_mach_info::float_format);
+
+template octave_idx_type
+octave_stream::write (const Array<octave_uint8>&, octave_idx_type,
+                      oct_data_conv::data_type,
+                      octave_idx_type, oct_mach_info::float_format);
+
+template octave_idx_type
+octave_stream::write (const Array<octave_int16>&, octave_idx_type,
+                      oct_data_conv::data_type,
+                      octave_idx_type, oct_mach_info::float_format);
+
+template octave_idx_type
+octave_stream::write (const Array<octave_uint16>&, octave_idx_type,
+                      oct_data_conv::data_type,
+                      octave_idx_type, oct_mach_info::float_format);
+
+template octave_idx_type
+octave_stream::write (const Array<octave_int32>&, octave_idx_type,
+                      oct_data_conv::data_type,
+                      octave_idx_type, oct_mach_info::float_format);
+
+template octave_idx_type
+octave_stream::write (const Array<octave_uint32>&, octave_idx_type,
+                      oct_data_conv::data_type,
+                      octave_idx_type, oct_mach_info::float_format);
+
+template octave_idx_type
+octave_stream::write (const Array<octave_int64>&, octave_idx_type,
+                      oct_data_conv::data_type,
+                      octave_idx_type, oct_mach_info::float_format);
+
+template octave_idx_type
+octave_stream::write (const Array<octave_uint64>&, octave_idx_type,
+                      oct_data_conv::data_type,
+                      octave_idx_type, oct_mach_info::float_format);
+
+octave_value
+octave_stream::scanf (const std::string& fmt, const Array<double>& size,
+                      octave_idx_type& count, const std::string& who)
+{
+  octave_value retval;
+
+  if (stream_ok ())
+    retval = rep->scanf (fmt, size, count, who);
+
+  return retval;
+}
+
+octave_value
+octave_stream::scanf (const octave_value& fmt, const Array<double>& size,
+                      octave_idx_type& count, const std::string& who)
+{
+  octave_value retval = Matrix ();
+
+  if (fmt.is_string ())
+    {
+      std::string sfmt = fmt.string_value ();
+
+      if (fmt.is_sq_string ())
+        sfmt = do_string_escapes (sfmt);
+
+      retval = scanf (sfmt, size, count, who);
+    }
+  else
+    {
+      // Note that this is not ::error () !
+
+      error (who + ": format must be a string");
+    }
+
+  return retval;
+}
+
+octave_value_list
+octave_stream::oscanf (const std::string& fmt, const std::string& who)
+{
+  octave_value_list retval;
+
+  if (stream_ok ())
+    retval = rep->oscanf (fmt, who);
+
+  return retval;
+}
+
+octave_value_list
+octave_stream::oscanf (const octave_value& fmt, const std::string& who)
+{
+  octave_value_list retval;
+
+  if (fmt.is_string ())
+    {
+      std::string sfmt = fmt.string_value ();
+
+      if (fmt.is_sq_string ())
+        sfmt = do_string_escapes (sfmt);
+
+      retval = oscanf (sfmt, who);
+    }
+  else
+    {
+      // Note that this is not ::error () !
+
+      error (who + ": format must be a string");
+    }
+
+  return retval;
+}
+
+int
+octave_stream::printf (const std::string& fmt, const octave_value_list& args,
+                       const std::string& who)
+{
+  int retval = -1;
+
+  if (stream_ok ())
+    retval = rep->printf (fmt, args, who);
+
+  return retval;
+}
+
+int
+octave_stream::printf (const octave_value& fmt, const octave_value_list& args,
+                       const std::string& who)
+{
+  int retval = 0;
+
+  if (fmt.is_string ())
+    {
+      std::string sfmt = fmt.string_value ();
+
+      if (fmt.is_sq_string ())
+        sfmt = do_string_escapes (sfmt);
+
+      retval = printf (sfmt, args, who);
+    }
+  else
+    {
+      // Note that this is not ::error () !
+
+      error (who + ": format must be a string");
+    }
+
+  return retval;
+}
+
+int
+octave_stream::puts (const std::string& s, const std::string& who)
+{
+  int retval = -1;
+
+  if (stream_ok ())
+    retval = rep->puts (s, who);
+
+  return retval;
+}
+
+// FIXME -- maybe this should work for string arrays too.
+
+int
+octave_stream::puts (const octave_value& tc_s, const std::string& who)
+{
+  int retval = -1;
+
+  if (tc_s.is_string ())
+    {
+      std::string s = tc_s.string_value ();
+      retval = puts (s, who);
+    }
+  else
+    {
+      // Note that this is not ::error () !
+
+      error (who + ": argument must be a string");
+    }
+
+  return retval;
+}
+
+bool
+octave_stream::eof (void) const
+{
+  int retval = -1;
+
+  if (stream_ok ())
+    retval = rep->eof ();
+
+  return retval;
+}
+
+std::string
+octave_stream::error (bool clear, int& err_num)
+{
+  std::string retval = "invalid stream object";
+
+  if (stream_ok (false))
+    retval = rep->error (clear, err_num);
+
+  return retval;
+}
+
+std::string
+octave_stream::name (void) const
+{
+  std::string retval;
+
+  if (stream_ok ())
+    retval = rep->name ();
+
+  return retval;
+}
+
+int
+octave_stream::mode (void) const
+{
+  int retval = 0;
+
+  if (stream_ok ())
+    retval = rep->mode ();
+
+  return retval;
+}
+
+oct_mach_info::float_format
+octave_stream::float_format (void) const
+{
+  oct_mach_info::float_format retval = oct_mach_info::flt_fmt_unknown;
+
+  if (stream_ok ())
+    retval = rep->float_format ();
+
+  return retval;
+}
+
+std::string
+octave_stream::mode_as_string (int mode)
+{
+  std::string retval = "???";
+  std::ios::openmode in_mode = static_cast<std::ios::openmode> (mode);
+
+  if (in_mode == std::ios::in)
+    retval = "r";
+  else if (in_mode == std::ios::out
+           || in_mode == (std::ios::out | std::ios::trunc))
+    retval = "w";
+  else if (in_mode == (std::ios::out | std::ios::app))
+    retval = "a";
+  else if (in_mode == (std::ios::in | std::ios::out))
+    retval = "r+";
+  else if (in_mode == (std::ios::in | std::ios::out | std::ios::trunc))
+    retval = "w+";
+  else if (in_mode == (std::ios::in | std::ios::out | std::ios::ate))
+    retval = "a+";
+  else if (in_mode == (std::ios::in | std::ios::binary))
+    retval = "rb";
+  else if (in_mode == (std::ios::out | std::ios::binary)
+           || in_mode == (std::ios::out | std::ios::trunc | std::ios::binary))
+    retval = "wb";
+  else if (in_mode == (std::ios::out | std::ios::app | std::ios::binary))
+    retval = "ab";
+  else if (in_mode == (std::ios::in | std::ios::out | std::ios::binary))
+    retval = "r+b";
+  else if (in_mode == (std::ios::in | std::ios::out | std::ios::trunc
+                       | std::ios::binary))
+    retval = "w+b";
+  else if (in_mode == (std::ios::in | std::ios::out | std::ios::ate
+                       | std::ios::binary))
+    retval = "a+b";
+
+  return retval;
+}
+
+octave_stream_list *octave_stream_list::instance = 0;
+
+bool
+octave_stream_list::instance_ok (void)
+{
+  bool retval = true;
+
+  if (! instance)
+    {
+      instance = new octave_stream_list ();
+
+      if (instance)
+        singleton_cleanup_list::add (cleanup_instance);
+    }
+
+  if (! instance)
+    {
+      ::error ("unable to create stream list object!");
+
+      retval = false;
+    }
+
+  return retval;
+}
+
+int
+octave_stream_list::insert (octave_stream& os)
+{
+  return (instance_ok ()) ? instance->do_insert (os) : -1;
+}
+
+octave_stream
+octave_stream_list::lookup (int fid, const std::string& who)
+{
+  return (instance_ok ()) ? instance->do_lookup (fid, who) : octave_stream ();
+}
+
+octave_stream
+octave_stream_list::lookup (const octave_value& fid, const std::string& who)
+{
+  return (instance_ok ()) ? instance->do_lookup (fid, who) : octave_stream ();
+}
+
+int
+octave_stream_list::remove (int fid, const std::string& who)
+{
+  return (instance_ok ()) ? instance->do_remove (fid, who) : -1;
+}
+
+int
+octave_stream_list::remove (const octave_value& fid, const std::string& who)
+{
+  return (instance_ok ()) ? instance->do_remove (fid, who) : -1;
+}
+
+void
+octave_stream_list::clear (bool flush)
+{
+  if (instance)
+    instance->do_clear (flush);
+}
+
+string_vector
+octave_stream_list::get_info (int fid)
+{
+  return (instance_ok ()) ? instance->do_get_info (fid) : string_vector ();
+}
+
+string_vector
+octave_stream_list::get_info (const octave_value& fid)
+{
+  return (instance_ok ()) ? instance->do_get_info (fid) : string_vector ();
+}
+
+std::string
+octave_stream_list::list_open_files (void)
+{
+  return (instance_ok ()) ? instance->do_list_open_files () : std::string ();
+}
+
+octave_value
+octave_stream_list::open_file_numbers (void)
+{
+  return (instance_ok ())
+    ? instance->do_open_file_numbers () : octave_value ();
+}
+
+int
+octave_stream_list::get_file_number (const octave_value& fid)
+{
+  return (instance_ok ()) ? instance->do_get_file_number (fid) : -1;
+}
+
+int
+octave_stream_list::do_insert (octave_stream& os)
+{
+  // Insert item with key corresponding to file-descriptor.
+
+  int stream_number;
+
+  if ((stream_number = os.file_number ()) == -1)
+    return stream_number;
+
+  // Should we test for "(list.find (stream_number) != list.end ()) &&
+  // list[stream_number].is_open ()" and respond with "error
+  // ("internal error: ...")"? It should not happen except for some
+  // bug or if the user has opened a stream with an interpreted
+  // command, but closed it directly with a system call in an
+  // oct-file; then the kernel knows the fd is free, but Octave does
+  // not know. If it happens, it should not do harm here to simply
+  // overwrite this entry, although the wrong entry might have done
+  // harm before.
+
+  if (list.size () < list.max_size ())
+    list[stream_number] = os;
+  else
+    {
+      stream_number = -1;
+      error ("could not create file id");
+    }
+
+  return stream_number;
+
+}
+
+static void
+gripe_invalid_file_id (int fid, const std::string& who)
+{
+  if (who.empty ())
+    ::error ("invalid stream number = %d", fid);
+  else
+    ::error ("%s: invalid stream number = %d", who.c_str (), fid);
+}
+
+octave_stream
+octave_stream_list::do_lookup (int fid, const std::string& who) const
+{
+  octave_stream retval;
+
+  if (fid >= 0)
+    {
+      if (lookup_cache != list.end () && lookup_cache->first == fid)
+        retval = lookup_cache->second;
+      else
+        {
+          ostrl_map::const_iterator iter = list.find (fid);
+
+          if (iter != list.end ())
+            {
+              retval = iter->second;
+              lookup_cache = iter;
+            }
+          else
+            gripe_invalid_file_id (fid, who);
+        }
+    }
+  else
+    gripe_invalid_file_id (fid, who);
+
+  return retval;
+}
+
+octave_stream
+octave_stream_list::do_lookup (const octave_value& fid,
+                               const std::string& who) const
+{
+  octave_stream retval;
+
+  int i = get_file_number (fid);
+
+  if (! error_state)
+    retval = do_lookup (i, who);
+
+  return retval;
+}
+
+int
+octave_stream_list::do_remove (int fid, const std::string& who)
+{
+  int retval = -1;
+
+  // Can't remove stdin (std::cin), stdout (std::cout), or stderr
+  // (std::cerr).
+
+  if (fid > 2)
+    {
+      ostrl_map::iterator iter = list.find (fid);
+
+      if (iter != list.end ())
+        {
+          octave_stream os = iter->second;
+          list.erase (iter);
+          lookup_cache = list.end ();
+
+          // FIXME: is this check redundant?
+          if (os.is_valid ())
+            {
+              os.close ();
+              retval = 0;
+            }
+          else
+            gripe_invalid_file_id (fid, who);
+        }
+      else
+        gripe_invalid_file_id (fid, who);
+    }
+  else
+    gripe_invalid_file_id (fid, who);
+
+  return retval;
+}
+
+int
+octave_stream_list::do_remove (const octave_value& fid, const std::string& who)
+{
+  int retval = -1;
+
+  if (fid.is_string () && fid.string_value () == "all")
+    {
+      do_clear (false);
+
+      retval = 0;
+    }
+  else
+    {
+      int i = get_file_number (fid);
+
+      if (! error_state)
+        retval = do_remove (i, who);
+    }
+
+  return retval;
+}
+
+void
+octave_stream_list::do_clear (bool flush)
+{
+  if (flush)
+    {
+      // Do flush stdout and stderr.
+
+      list[0].flush ();
+      list[1].flush ();
+    }
+
+  octave_stream saved_os[3];
+  // But don't delete them or stdin.
+  for (ostrl_map::iterator iter = list.begin (); iter != list.end (); iter++)
+    {
+      int fid = iter->first;
+      octave_stream os = iter->second;
+      if (fid < 3)
+        saved_os[fid] = os;
+      else if (os.is_valid ())
+        os.close ();
+    }
+  list.clear ();
+  for (int fid = 0; fid < 3; fid++) list[fid] = saved_os[fid];
+  lookup_cache = list.end ();
+}
+
+string_vector
+octave_stream_list::do_get_info (int fid) const
+{
+  string_vector retval;
+
+  octave_stream os = do_lookup (fid);
+
+  if (os.is_valid ())
+    {
+      retval.resize (3);
+
+      retval(2) = oct_mach_info::float_format_as_string (os.float_format ());
+      retval(1) = octave_stream::mode_as_string (os.mode ());
+      retval(0) = os.name ();
+    }
+  else
+    ::error ("invalid file id = %d", fid);
+
+  return retval;
+}
+
+string_vector
+octave_stream_list::do_get_info (const octave_value& fid) const
+{
+  string_vector retval;
+
+  int conv_err = 0;
+
+  int int_fid = convert_to_valid_int (fid, conv_err);
+
+  if (! conv_err)
+    retval = do_get_info (int_fid);
+  else
+    ::error ("file id must be a file object or integer value");
+
+  return retval;
+}
+
+std::string
+octave_stream_list::do_list_open_files (void) const
+{
+  std::string retval;
+
+  std::ostringstream buf;
+
+  buf << "\n"
+      << "  number  mode  arch       name\n"
+      << "  ------  ----  ----       ----\n";
+
+  for (ostrl_map::const_iterator p = list.begin (); p != list.end (); p++)
+    {
+      octave_stream os = p->second;
+
+      buf << "  "
+          << std::setiosflags (std::ios::right)
+          << std::setw (4) << p->first << "     "
+          << std::setiosflags (std::ios::left)
+          << std::setw (3)
+          << octave_stream::mode_as_string (os.mode ())
+          << "  "
+          << std::setw (9)
+          << oct_mach_info::float_format_as_string (os.float_format ())
+          << "  "
+          << os.name () << "\n";
+    }
+
+  buf << "\n";
+
+  retval = buf.str ();
+
+  return retval;
+}
+
+octave_value
+octave_stream_list::do_open_file_numbers (void) const
+{
+  Matrix retval (1, list.size (), 0.0);
+
+  int num_open = 0;
+
+  for (ostrl_map::const_iterator p = list.begin (); p != list.end (); p++)
+    {
+      // Skip stdin, stdout, and stderr.
+
+      if (p->first > 2 && p->second)
+        retval(0,num_open++) = p->first;
+    }
+
+  retval.resize ((num_open > 0), num_open);
+
+  return retval;
+}
+
+int
+octave_stream_list::do_get_file_number (const octave_value& fid) const
+{
+  int retval = -1;
+
+  if (fid.is_string ())
+    {
+      std::string nm = fid.string_value ();
+
+      for (ostrl_map::const_iterator p = list.begin (); p != list.end (); p++)
+        {
+          // stdin (std::cin), stdout (std::cout), and stderr (std::cerr)
+          // are unnamed.
+
+          if (p->first > 2)
+            {
+              octave_stream os = p->second;
+
+              if (os && os.name () == nm)
+                {
+                  retval = p->first;
+                  break;
+                }
+            }
+        }
+    }
+  else
+    {
+      int conv_err = 0;
+
+      int int_fid = convert_to_valid_int (fid, conv_err);
+
+      if (conv_err)
+        ::error ("file id must be a file object, std::string, or integer value");
+      else
+        retval = int_fid;
+    }
+
+  return retval;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/oct-stream.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,738 @@
+/*
+
+Copyright (C) 1996-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if !defined (octave_octave_stream_h)
+#define octave_octave_stream_h 1
+
+class Matrix;
+class string_vector;
+class octave_value;
+class octave_value_list;
+
+#include <iosfwd>
+#include <sstream>
+#include <string>
+#include <map>
+
+#include "Array.h"
+#include "data-conv.h"
+#include "lo-utils.h"
+#include "mach-info.h"
+#include "oct-refcount.h"
+
+class
+OCTINTERP_API
+scanf_format_elt
+{
+public:
+
+  enum special_conversion
+    {
+      whitespace_conversion = 1,
+      literal_conversion = 2
+    };
+
+  scanf_format_elt (const char *txt = 0, int w = 0, bool d = false,
+                    char typ = '\0', char mod = '\0',
+                    const std::string& ch_class = std::string ())
+    : text (strsave (txt)), width (w), discard (d), type (typ),
+      modifier (mod), char_class (ch_class) { }
+
+  scanf_format_elt (const scanf_format_elt& e)
+    : text (strsave (e.text)), width (e.width), discard (e.discard),
+      type (e.type), modifier (e.modifier), char_class (e.char_class) { }
+
+  scanf_format_elt& operator = (const scanf_format_elt& e)
+    {
+      if (this != &e)
+        {
+          text = strsave (e.text);
+          width = e.width;
+          discard = e.discard;
+          type = e.type;
+          modifier = e.modifier;
+          char_class = e.char_class;
+        }
+
+      return *this;
+    }
+
+  ~scanf_format_elt (void) { delete [] text; }
+
+  // The C-style format string.
+  const char *text;
+
+  // The maximum field width.
+  int width;
+
+  // TRUE if we are not storing the result of this conversion.
+  bool discard;
+
+  // Type of conversion -- `d', `i', `o', `u', `x', `e', `f', `g',
+  // `c', `s', `p', `%', or `['.
+  char type;
+
+  // A length modifier -- `h', `l', or `L'.
+  char modifier;
+
+  // The class of characters in a `[' format.
+  std::string char_class;
+};
+
+class
+OCTINTERP_API
+scanf_format_list
+{
+public:
+
+  scanf_format_list (const std::string& fmt = std::string ());
+
+  ~scanf_format_list (void);
+
+  octave_idx_type num_conversions (void) { return nconv; }
+
+  // The length can be different than the number of conversions.
+  // For example, "x %d y %d z" has 2 conversions but the length of
+  // the list is 3 because of the characters that appear after the
+  // last conversion.
+
+  octave_idx_type length (void) { return list.length (); }
+
+  const scanf_format_elt *first (void)
+    {
+      curr_idx = 0;
+      return current ();
+    }
+
+  const scanf_format_elt *current (void) const
+    { return list.length () > 0 ? list.elem (curr_idx) : 0; }
+
+  const scanf_format_elt *next (bool cycle = true)
+    {
+      curr_idx++;
+
+      if (curr_idx >= list.length ())
+        {
+          if (cycle)
+            curr_idx = 0;
+          else
+            return 0;
+        }
+      return current ();
+    }
+
+  void printme (void) const;
+
+  bool ok (void) const { return (nconv >= 0); }
+
+  operator bool () const { return ok (); }
+
+  bool all_character_conversions (void);
+
+  bool all_numeric_conversions (void);
+
+private:
+
+  // Number of conversions specified by this format string, or -1 if
+  // invalid conversions have been found.
+  octave_idx_type nconv;
+
+  // Index to current element;
+  octave_idx_type curr_idx;
+
+  // FIXME -- maybe LIST should be a std::list object?
+  // List of format elements.
+  Array<scanf_format_elt*> list;
+
+  // Temporary buffer.
+  std::ostringstream *buf;
+
+  void add_elt_to_list (int width, bool discard, char type, char modifier,
+                        octave_idx_type& num_elts,
+                        const std::string& char_class = std::string ());
+
+  void process_conversion (const std::string& s, size_t& i, size_t n,
+                           int& width, bool& discard, char& type,
+                           char& modifier, octave_idx_type& num_elts);
+
+  int finish_conversion (const std::string& s, size_t& i, size_t n,
+                         int& width, bool discard, char& type,
+                         char modifier, octave_idx_type& num_elts);
+  // No copying!
+
+  scanf_format_list (const scanf_format_list&);
+
+  scanf_format_list& operator = (const scanf_format_list&);
+};
+
+class
+printf_format_elt
+{
+public:
+
+  printf_format_elt (const char *txt = 0, int n = 0, int w = 0,
+                     int p = 0, const std::string& f = std::string (),
+                     char typ = '\0', char mod = '\0')
+    : text (strsave (txt)), args (n), fw (w), prec (p), flags (f),
+      type (typ), modifier (mod) { }
+
+  printf_format_elt (const printf_format_elt& e)
+    : text (strsave (e.text)), args (e.args), fw (e.fw), prec (e.prec),
+      flags (e.flags), type (e.type), modifier (e.modifier) { }
+
+  printf_format_elt& operator = (const printf_format_elt& e)
+    {
+      if (this != &e)
+        {
+          text = strsave (e.text);
+          args = e.args;
+          fw = e.fw;
+          prec = e.prec;
+          flags = e.flags;
+          type = e.type;
+          modifier = e.modifier;
+        }
+
+      return *this;
+    }
+
+  ~printf_format_elt (void) { delete [] text; }
+
+  // The C-style format string.
+  const char *text;
+
+  // How many args do we expect to consume?
+  int args;
+
+  // Field width.
+  int fw;
+
+  // Precision.
+  int prec;
+
+  // Flags -- `-', `+', ` ', `0', or `#'.
+  std::string flags;
+
+  // Type of conversion -- `d', `i', `o', `x', `X', `u', `c', `s',
+  // `f', `e', `E', `g', `G', `p', or `%'
+  char type;
+
+  // A length modifier -- `h', `l', or `L'.
+  char modifier;
+};
+
+class
+OCTINTERP_API
+printf_format_list
+{
+public:
+
+  printf_format_list (const std::string& fmt = std::string ());
+
+  ~printf_format_list (void);
+
+  octave_idx_type num_conversions (void) { return nconv; }
+
+  const printf_format_elt *first (void)
+    {
+      curr_idx = 0;
+      return current ();
+    }
+
+  const printf_format_elt *current (void) const
+    { return list.length () > 0 ? list.elem (curr_idx) : 0; }
+
+  const printf_format_elt *next (bool cycle = true)
+    {
+      curr_idx++;
+
+      if (curr_idx >= list.length ())
+        {
+          if (cycle)
+            curr_idx = 0;
+          else
+            return 0;
+        }
+
+      return current ();
+    }
+
+  bool last_elt_p (void) { return (curr_idx + 1 == list.length ()); }
+
+  void printme (void) const;
+
+  bool ok (void) const { return (nconv >= 0); }
+
+  operator bool () const { return ok (); }
+
+private:
+
+  // Number of conversions specified by this format string, or -1 if
+  // invalid conversions have been found.
+  octave_idx_type nconv;
+
+  // Index to current element;
+  octave_idx_type curr_idx;
+
+  // FIXME -- maybe LIST should be a std::list object?
+  // List of format elements.
+  Array<printf_format_elt*> list;
+
+  // Temporary buffer.
+  std::ostringstream *buf;
+
+  void add_elt_to_list (int args, const std::string& flags, int fw,
+                        int prec, char type, char modifier,
+                        octave_idx_type& num_elts);
+
+  void process_conversion (const std::string& s, size_t& i, size_t n,
+                           int& args, std::string& flags, int& fw,
+                           int& prec, char& modifier, char& type,
+                           octave_idx_type& num_elts);
+
+  void finish_conversion (const std::string& s, size_t& i, int args,
+                          const std::string& flags, int fw, int prec,
+                          char modifier, char& type,
+                          octave_idx_type& num_elts);
+
+  // No copying!
+
+  printf_format_list (const printf_format_list&);
+
+  printf_format_list& operator = (const printf_format_list&);
+};
+
+// Provide an interface for Octave streams.
+
+class
+OCTINTERP_API
+octave_base_stream
+{
+friend class octave_stream;
+
+public:
+
+  octave_base_stream (std::ios::openmode arg_md = std::ios::in|std::ios::out,
+                      oct_mach_info::float_format ff
+                        = oct_mach_info::native_float_format ())
+    : count (0), md (arg_md), flt_fmt (ff), fail (false), open_state (true),
+      errmsg ()
+  { }
+
+  virtual ~octave_base_stream (void) { }
+
+  // The remaining functions are not specific to input or output only,
+  // and must be provided by the derived classes.
+
+  // Position a stream at OFFSET relative to ORIGIN.
+
+  virtual int seek (long offset, int origin) = 0;
+
+  // Return current stream position.
+
+  virtual long tell (void) = 0;
+
+  // Return TRUE if EOF has been reached on this stream.
+
+  virtual bool eof (void) const = 0;
+
+  // The name of the file.
+
+  virtual std::string name (void) const = 0;
+
+  // If the derived class provides this function and it returns a
+  // pointer to a valid istream, scanf(), read(), getl(), and gets()
+  // will automatically work for this stream.
+
+  virtual std::istream *input_stream (void) { return 0; }
+
+  // If the derived class provides this function and it returns a
+  // pointer to a valid ostream, flush(), write(), and printf() will
+  // automatically work for this stream.
+
+  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; }
+
+  virtual void do_close (void) { }
+
+  void close (void)
+    {
+      if (is_open ())
+        {
+          open_state = false;
+          do_close ();
+        }
+    }
+
+  virtual int file_number (void) const
+  {
+    // Kluge alert!
+
+    if (name () == "stdin")
+      return 0;
+    else if (name () == "stdout")
+      return 1;
+    else if (name () == "stderr")
+      return 2;
+    else
+      return -1;
+  }
+
+  bool ok (void) const { return ! fail; }
+
+  // Return current error message for this stream.
+
+  std::string error (bool clear, int& err_num);
+
+protected:
+
+  int mode (void) const { return md; }
+
+  oct_mach_info::float_format float_format (void) const { return flt_fmt; }
+
+  // Set current error state and set fail to TRUE.
+
+  void error (const std::string& msg);
+  void error (const std::string& who, const std::string& msg);
+
+  // Clear any error message and set fail to FALSE.
+
+  void clear (void);
+
+  // Clear stream state.
+
+  void clearerr (void);
+
+private:
+
+  // A reference count.
+  octave_refcount<octave_idx_type> count;
+
+  // The permission bits for the file.  Should be some combination of
+  // std::ios::open_mode bits.
+  int md;
+
+  // Data format.
+  oct_mach_info::float_format flt_fmt;
+
+  // TRUE if an error has occurred.
+  bool fail;
+
+  // TRUE if this stream is open.
+  bool open_state;
+
+  // Should contain error message if fail is TRUE.
+  std::string errmsg;
+
+  // Functions that are defined for all input streams (input streams
+  // are those that define is).
+
+  std::string do_gets (octave_idx_type max_len, bool& err, bool strip_newline,
+                       const std::string& who /* = "gets" */);
+
+  std::string getl (octave_idx_type max_len, bool& err, const std::string& who /* = "getl" */);
+  std::string gets (octave_idx_type max_len, bool& err, const std::string& who /* = "gets" */);
+  long skipl (long count, bool& err, const std::string& who /* = "skipl" */);
+
+  octave_value do_scanf (scanf_format_list& fmt_list, octave_idx_type nr, octave_idx_type nc,
+                         bool one_elt_size_spec, octave_idx_type& count,
+                         const std::string& who /* = "scanf" */);
+
+  octave_value scanf (const std::string& fmt, const Array<double>& size,
+                      octave_idx_type& count, const std::string& who /* = "scanf" */);
+
+  bool do_oscanf (const scanf_format_elt *elt, octave_value&,
+                  const std::string& who /* = "scanf" */);
+
+  octave_value_list oscanf (const std::string& fmt,
+                            const std::string& who /* = "scanf" */);
+
+  // Functions that are defined for all output streams (output streams
+  // are those that define os).
+
+  int flush (void);
+
+  int do_printf (printf_format_list& fmt_list, const octave_value_list& args,
+                 const std::string& who /* = "printf" */);
+
+  int printf (const std::string& fmt, const octave_value_list& args,
+              const std::string& who /* = "printf" */);
+
+  int puts (const std::string& s, const std::string& who /* = "puts" */);
+
+  // We can always do this in terms of seek(), so the derived class
+  // only has to provide that.
+
+  void invalid_operation (const std::string& who, const char *rw);
+
+  // No copying!
+
+  octave_base_stream (const octave_base_stream&);
+
+  octave_base_stream& operator = (const octave_base_stream&);
+};
+
+class
+OCTINTERP_API
+octave_stream
+{
+public:
+
+  octave_stream (octave_base_stream *bs = 0);
+
+  ~octave_stream (void);
+
+  octave_stream (const octave_stream&);
+
+  octave_stream& operator = (const octave_stream&);
+
+  int flush (void);
+
+  std::string getl (octave_idx_type max_len, bool& err, const std::string& who /* = "getl" */);
+  std::string getl (const octave_value& max_len, bool& err,
+                    const std::string& who /* = "getl" */);
+
+  std::string gets (octave_idx_type max_len, bool& err, const std::string& who /* = "gets" */);
+  std::string gets (const octave_value& max_len, bool& err,
+                    const std::string& who /* = "gets" */);
+
+  long skipl (long count, bool& err, const std::string& who /* = "skipl" */);
+  long skipl (const octave_value& count, bool& err, const std::string& who /* = "skipl" */);
+
+  int seek (long offset, int origin);
+  int seek (const octave_value& offset, const octave_value& origin);
+
+  long tell (void);
+
+  int rewind (void);
+
+  bool is_open (void) const;
+
+  void close (void);
+
+  octave_value read (const Array<double>& size, octave_idx_type block_size,
+                     oct_data_conv::data_type input_type,
+                     oct_data_conv::data_type output_type,
+                     octave_idx_type skip, oct_mach_info::float_format flt_fmt,
+                     octave_idx_type& count);
+
+  octave_idx_type write (const octave_value& data, octave_idx_type block_size,
+             oct_data_conv::data_type output_type,
+             octave_idx_type skip, oct_mach_info::float_format flt_fmt);
+
+  template <class T>
+  octave_idx_type write (const Array<T>&, octave_idx_type block_size,
+             oct_data_conv::data_type output_type,
+             octave_idx_type skip, oct_mach_info::float_format flt_fmt);
+
+  octave_value scanf (const std::string& fmt, const Array<double>& size,
+                      octave_idx_type& count, const std::string& who /* = "scanf" */);
+
+  octave_value scanf (const octave_value& fmt, const Array<double>& size,
+                      octave_idx_type& count, const std::string& who /* = "scanf" */);
+
+  octave_value_list oscanf (const std::string& fmt,
+                            const std::string& who /* = "scanf" */);
+
+  octave_value_list oscanf (const octave_value& fmt,
+                            const std::string& who /* = "scanf" */);
+
+  int printf (const std::string& fmt, const octave_value_list& args,
+              const std::string& who /* = "printf" */);
+
+  int printf (const octave_value& fmt, const octave_value_list& args,
+              const std::string& who /* = "printf" */);
+
+  int puts (const std::string& s, const std::string& who /* = "puts" */);
+  int puts (const octave_value& s, const std::string& who /* = "puts" */);
+
+  bool eof (void) const;
+
+  std::string error (bool clear, int& err_num);
+
+  std::string error (bool clear = false)
+    {
+      int err_num;
+      return error (clear, err_num);
+    }
+
+  // Set the error message and state.
+
+  void error (const std::string& msg)
+    {
+      if (rep)
+        rep->error (msg);
+    }
+
+  void error (const char *msg) { error (std::string (msg)); }
+
+  int file_number (void) { return rep ? rep->file_number () : -1; }
+
+  bool is_valid (void) const { return (rep != 0); }
+
+  bool ok (void) const { return rep && rep->ok (); }
+
+  operator bool () const { return ok (); }
+
+  std::string name (void) const;
+
+  int mode (void) const;
+
+  oct_mach_info::float_format float_format (void) const;
+
+  static std::string mode_as_string (int mode);
+
+  std::istream *input_stream (void)
+  {
+    return rep ? rep->input_stream () : 0;
+  }
+
+  std::ostream *output_stream (void)
+  {
+    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:
+
+  // The actual representation of this stream.
+  octave_base_stream *rep;
+
+  bool stream_ok (bool clear = true) const
+    {
+      bool retval = true;
+
+      if (rep)
+        {
+          if (clear)
+            rep->clear ();
+        }
+      else
+        retval = false;
+
+      return retval;
+    }
+
+  void invalid_operation (const std::string& who, const char *rw)
+    {
+      if (rep)
+        rep->invalid_operation (who, rw);
+    }
+};
+
+class
+OCTINTERP_API
+octave_stream_list
+{
+protected:
+
+  octave_stream_list (void) : list (), lookup_cache (list.end ()) { }
+
+public:
+
+  ~octave_stream_list (void) { }
+
+  static bool instance_ok (void);
+
+  static int insert (octave_stream& os);
+
+  static octave_stream
+  lookup (int fid, const std::string& who = std::string ());
+
+  static octave_stream
+  lookup (const octave_value& fid, const std::string& who = std::string ());
+
+  static int remove (int fid, const std::string& who = std::string ());
+  static int remove (const octave_value& fid,
+                     const std::string& who = std::string ());
+
+  static void clear (bool flush = true);
+
+  static string_vector get_info (int fid);
+  static string_vector get_info (const octave_value& fid);
+
+  static std::string list_open_files (void);
+
+  static octave_value open_file_numbers (void);
+
+  static int get_file_number (const octave_value& fid);
+
+private:
+
+  typedef std::map<int, octave_stream> ostrl_map;
+
+  ostrl_map list;
+
+  mutable ostrl_map::const_iterator lookup_cache;
+
+  static octave_stream_list *instance;
+
+  static void cleanup_instance (void) { delete instance; instance = 0; }
+
+  int do_insert (octave_stream& os);
+
+  octave_stream do_lookup (int fid, const std::string& who = std::string ()) const;
+  octave_stream do_lookup (const octave_value& fid,
+                           const std::string& who = std::string ()) const;
+
+  int do_remove (int fid, const std::string& who = std::string ());
+  int do_remove (const octave_value& fid, const std::string& who = std::string ());
+
+  void do_clear (bool flush = true);
+
+  string_vector do_get_info (int fid) const;
+  string_vector do_get_info (const octave_value& fid) const;
+
+  std::string do_list_open_files (void) const;
+
+  octave_value do_open_file_numbers (void) const;
+
+  int do_get_file_number (const octave_value& fid) const;
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/oct-strstrm.cc	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,66 @@
+/*
+
+Copyright (C) 1996-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "oct-strstrm.h"
+
+// Position a stream at OFFSET relative to ORIGIN.
+
+int
+octave_base_strstream::seek (long, int)
+{
+  error ("fseek: invalid operation");
+  return -1;
+}
+
+// Return current stream position.
+
+long
+octave_base_strstream::tell (void)
+{
+  error ("ftell: invalid operation");
+  return -1;
+}
+
+octave_stream
+octave_istrstream::create (const char *data, std::ios::openmode arg_md,
+                           oct_mach_info::float_format flt_fmt)
+{
+  return octave_stream (new octave_istrstream (data, arg_md, flt_fmt));
+}
+
+octave_stream
+octave_istrstream::create (const std::string& data, std::ios::openmode arg_md,
+                           oct_mach_info::float_format flt_fmt)
+{
+  return octave_stream (new octave_istrstream (data, arg_md, flt_fmt));
+}
+
+octave_stream
+octave_ostrstream::create (std::ios::openmode arg_md,
+                           oct_mach_info::float_format flt_fmt)
+{
+  return octave_stream (new octave_ostrstream (arg_md, flt_fmt));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/oct-strstrm.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,176 @@
+/*
+
+Copyright (C) 1996-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if !defined (octave_octave_strstream_h)
+#define octave_octave_strstream_h 1
+
+#include <string>
+#include <sstream>
+
+#include "oct-stream.h"
+
+class
+octave_base_strstream : public octave_base_stream
+{
+public:
+
+  octave_base_strstream (std::ios::openmode m = std::ios::out,
+                         oct_mach_info::float_format ff
+                           = oct_mach_info::native_float_format ())
+    : octave_base_stream (m, ff) { }
+
+  // Position a stream at OFFSET relative to ORIGIN.
+
+  int seek (long, int);
+
+  // Return current stream position.
+
+  virtual long tell (void);
+
+  // The name of the file.
+
+  std::string name (void) const { return std::string (); }
+
+  virtual std::streambuf *rdbuf (void) = 0;
+
+  virtual bool bad (void) const = 0;
+
+  virtual void clear (void) = 0;
+
+protected:
+
+  ~octave_base_strstream (void) { }
+
+private:
+
+  // No copying!
+
+  octave_base_strstream (const octave_base_strstream&);
+
+  octave_base_strstream& operator = (const octave_base_strstream&);
+};
+
+class
+octave_istrstream : public octave_base_strstream
+{
+public:
+
+  octave_istrstream (const char *data,
+                     std::ios::openmode arg_md = std::ios::out,
+                     oct_mach_info::float_format ff
+                       = oct_mach_info::native_float_format ())
+    : octave_base_strstream (arg_md, ff), is (data) { }
+
+  octave_istrstream (const std::string& data,
+                     std::ios::openmode arg_md = std::ios::out,
+                     oct_mach_info::float_format ff
+                       = oct_mach_info::native_float_format ())
+    : octave_base_strstream (arg_md, ff), is (data.c_str ()) { }
+
+  static octave_stream
+  create (const char *data, std::ios::openmode arg_md = std::ios::out,
+          oct_mach_info::float_format ff
+            = oct_mach_info::native_float_format ());
+
+  static octave_stream
+  create (const std::string& data, std::ios::openmode arg_md = std::ios::out,
+          oct_mach_info::float_format ff
+            = oct_mach_info::native_float_format ());
+
+  // Return non-zero if EOF has been reached on this stream.
+
+  bool eof (void) const { return is.eof (); }
+
+  std::istream *input_stream (void) { return &is; }
+
+  std::ostream *output_stream (void) { return 0; }
+
+  long tell (void) { return is.tellg (); }
+
+  std::streambuf *rdbuf (void) { return is ? is.rdbuf () : 0; }
+
+  bool bad (void) const { return is.bad (); }
+
+  void clear (void) { is.clear (); }
+
+protected:
+
+  ~octave_istrstream (void) { }
+
+private:
+
+  std::istringstream is;
+
+  // No copying!
+
+  octave_istrstream (const octave_istrstream&);
+
+  octave_istrstream& operator = (const octave_istrstream&);
+};
+
+class
+octave_ostrstream : public octave_base_strstream
+{
+public:
+
+  octave_ostrstream (std::ios::openmode arg_md = std::ios::out,
+                     oct_mach_info::float_format ff
+                       = oct_mach_info::native_float_format ())
+    : octave_base_strstream (arg_md, ff), os () { }
+
+  static octave_stream
+  create (std::ios::openmode arg_md = std::ios::out,
+          oct_mach_info::float_format ff
+            = oct_mach_info::native_float_format ());
+
+  // Return non-zero if EOF has been reached on this stream.
+
+  bool eof (void) const { return os.eof (); }
+
+  std::istream *input_stream (void) { return 0; }
+
+  std::ostream *output_stream (void) { return &os; }
+
+  std::string str (void) { return os.str (); }
+
+  std::streambuf *rdbuf (void) { return os ? os.rdbuf () : 0; }
+
+  bool bad (void) const { return os.bad (); }
+
+  void clear (void) { os.clear (); }
+
+protected:
+
+  ~octave_ostrstream (void) { }
+
+private:
+
+  std::ostringstream os;
+
+  // No copying!
+
+  octave_ostrstream (const octave_ostrstream&);
+
+  octave_ostrstream& operator = (const octave_ostrstream&);
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/oct.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,45 @@
+/*
+
+Copyright (C) 1996-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if !defined (octave_oct_h)
+#define octave_oct_h 1
+
+// Things that are often included to create .oct files.
+
+// config.h needs to be first because it includes #defines that can */
+// affect other header files.
+
+#include "config.h"
+
+#include "Matrix.h"
+
+#include "oct-locbuf.h"
+#include "defun-dld.h"
+#include "error.h"
+#include "gripes.h"
+#include "help.h"
+#include "oct-obj.h"
+#include "pager.h"
+#include "utils.h"
+#include "variables.h"
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/procstream.cc	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,70 @@
+/*
+
+Copyright (C) 1993-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <iostream>
+
+#include "procstream.h"
+
+procstreambase::procstreambase (const std::string& command, int mode)
+{
+  pb_init ();
+
+  if (! pb.open (command.c_str (), mode))
+    std::ios::setstate (std::ios::badbit);
+}
+
+procstreambase::procstreambase (const char *command, int mode)
+{
+  pb_init ();
+
+  if (! pb.open (command, mode))
+    std::ios::setstate (std::ios::badbit);
+}
+
+void
+procstreambase::open (const char *command, int mode)
+{
+  clear ();
+
+  if (! pb.open (command, mode))
+    std::ios::setstate (std::ios::badbit);
+}
+
+int
+procstreambase::close (void)
+{
+  int status = 0;
+
+  if (is_open ())
+    {
+      if (! pb.close ())
+        std::ios::setstate (std::ios::failbit);
+
+      status = pb.wait_status ();
+    }
+
+  return status;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/procstream.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,161 @@
+/*
+
+Copyright (C) 1993-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if !defined (octave_procstream_h)
+#define octave_procstream_h 1
+
+#include <iosfwd>
+#include <string>
+
+#include <sys/types.h>
+
+#include "oct-procbuf.h"
+
+class
+OCTINTERP_API
+procstreambase : virtual public std::ios
+{
+public:
+
+  procstreambase (void) : pb () { pb_init (); }
+
+  procstreambase (const std::string& name, int mode);
+
+  procstreambase (const char *name, int mode);
+
+  ~procstreambase (void) { close (); }
+
+  void open (const std::string& name, int mode)
+    { open (name.c_str (), mode); }
+
+  void open (const char *name, int mode);
+
+  int is_open (void) const { return pb.is_open (); }
+
+  int close (void);
+
+  pid_t pid (void) const { return pb.pid (); }
+
+  int file_number (void) const { return pb.file_number (); }
+
+private:
+
+  octave_procbuf pb;
+
+  void pb_init (void) { init (&pb); }
+
+  procstreambase (const procstreambase&);
+
+  procstreambase& operator = (const procstreambase&);
+};
+
+class
+OCTINTERP_API
+iprocstream : public std::istream, public procstreambase
+// iprocstream : public procstreambase, public std::istream
+{
+public:
+
+  iprocstream (void) : std::istream (0), procstreambase () { }
+
+  iprocstream (const std::string& name, int mode = std::ios::in)
+    : std::istream (0), procstreambase (name, mode) { }
+
+  iprocstream (const char *name, int mode = std::ios::in)
+    : std::istream (0), procstreambase (name, mode) { }
+
+  ~iprocstream (void) { }
+
+  void open (const std::string& name, int mode = std::ios::in)
+    { procstreambase::open (name, mode); }
+
+  void open (const char *name, int mode = std::ios::in)
+    { procstreambase::open (name, mode); }
+
+private:
+
+  iprocstream (const iprocstream&);
+
+  iprocstream& operator = (const iprocstream&);
+};
+
+class
+OCTINTERP_API
+oprocstream : public std::ostream, public procstreambase
+// oprocstream : public procstreambase, public std::ostream
+{
+public:
+
+  oprocstream (void) : std::ostream (0), procstreambase () { }
+
+  oprocstream (const std::string& name, int mode = std::ios::out)
+    : std::ostream (0), procstreambase (name, mode) { }
+
+  oprocstream (const char *name, int mode = std::ios::out)
+    : std::ostream (0), procstreambase (name, mode) { }
+
+  ~oprocstream (void) { }
+
+  void open (const std::string& name, int mode = std::ios::out)
+    { procstreambase::open (name, mode); }
+
+  void open (const char *name, int mode = std::ios::out)
+    { procstreambase::open (name, mode); }
+
+private:
+
+  oprocstream (const oprocstream&);
+
+  oprocstream& operator = (const oprocstream&);
+};
+
+class
+OCTINTERP_API
+procstream : public std::iostream, public procstreambase
+// procstream : public procstreambase, public std::iostream
+{
+public:
+
+  procstream (void) : std::iostream (0), procstreambase () { }
+
+  procstream (const std::string& name, int mode)
+    : std::iostream (0), procstreambase (name, mode) { }
+
+  procstream (const char *name, int mode)
+    : std::iostream (0), procstreambase (name, mode) { }
+
+  ~procstream (void) { }
+
+  void open (const std::string& name, int mode)
+    { procstreambase::open (name, mode); }
+
+  void open (const char *name, int mode)
+    { procstreambase::open (name, mode); }
+
+private:
+
+  procstream (const procstream&);
+
+  procstream& operator = (const procstream&);
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/pt-jit.cc	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,1930 @@
+/*
+
+Copyright (C) 2012 Max Brister <max@2bass.com>
+
+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/>.
+
+*/
+
+#define __STDC_LIMIT_MACROS
+#define __STDC_CONSTANT_MACROS
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_LLVM
+
+#include "pt-jit.h"
+
+#include <llvm/Analysis/CallGraph.h>
+#include <llvm/Analysis/Passes.h>
+#include <llvm/Analysis/Verifier.h>
+#include <llvm/LLVMContext.h>
+#include <llvm/ExecutionEngine/ExecutionEngine.h>
+#include <llvm/ExecutionEngine/JIT.h>
+#include <llvm/Module.h>
+#include <llvm/PassManager.h>
+#include <llvm/Support/IRBuilder.h>
+#include <llvm/Support/raw_os_ostream.h>
+#include <llvm/Support/TargetSelect.h>
+#include <llvm/Target/TargetData.h>
+#include <llvm/Transforms/IPO.h>
+#include <llvm/Transforms/Scalar.h>
+
+#ifdef OCTAVE_JIT_DEBUG
+#include <llvm/Bitcode/ReaderWriter.h>
+#endif
+
+#include "symtab.h"
+#include "pt-all.h"
+
+static llvm::IRBuilder<> builder (llvm::getGlobalContext ());
+
+static llvm::LLVMContext& context = llvm::getGlobalContext ();
+
+// -------------------- jit_convert --------------------
+jit_convert::jit_convert (llvm::Module *module, tree &tee,
+                          jit_type *for_bounds)
+  : iterator_count (0), for_bounds_count (0), short_count (0), breaking (false)
+{
+  jit_instruction::reset_ids ();
+
+  entry_block = create<jit_block> ("body");
+  final_block = create<jit_block> ("final");
+  append (entry_block);
+  entry_block->mark_alive ();
+  block = entry_block;
+
+  if (for_bounds)
+    create_variable (next_for_bounds (false), for_bounds);
+
+  visit (tee);
+
+  // FIXME: Remove if we no longer only compile loops
+  assert (! breaking);
+  assert (breaks.empty ());
+  assert (continues.empty ());
+
+  block->append (create<jit_branch> (final_block));
+  append (final_block);
+
+  for (vmap_t::iterator iter = vmap.begin (); iter != vmap.end (); ++iter)
+    {
+      jit_variable *var = iter->second;
+      const std::string& name = var->name ();
+      if (name.size () && name[0] != '#')
+        final_block->append (create<jit_store_argument> (var));
+    }
+
+  construct_ssa ();
+
+  // initialize the worklist to instructions derived from constants
+  for (std::list<jit_value *>::iterator iter = constants.begin ();
+       iter != constants.end (); ++iter)
+    append_users (*iter);
+
+  // the entry block terminator may be a regular branch statement
+  if (entry_block->terminator ())
+    push_worklist (entry_block->terminator ());
+
+  // FIXME: Describe algorithm here
+  while (worklist.size ())
+    {
+      jit_instruction *next = worklist.front ();
+      worklist.pop_front ();
+      next->stash_in_worklist (false);
+
+      if (next->infer ())
+        {
+          // terminators need to be handles specially
+          if (jit_terminator *term = dynamic_cast<jit_terminator *> (next))
+            append_users_term (term);
+          else
+            append_users (next);
+        }
+    }
+
+  remove_dead ();
+  merge_blocks ();
+  final_block->label ();
+  place_releases ();
+  simplify_phi ();
+
+#ifdef OCTAVE_JIT_DEBUG
+  final_block->label ();
+  std::cout << "-------------------- Compiling tree --------------------\n";
+  std::cout << tee.str_print_code () << std::endl;
+  print_blocks ("octave jit ir");
+#endif
+
+  // for now just init arguments from entry, later we will have to do something
+  // more interesting
+  for (jit_block::iterator iter = entry_block->begin ();
+       iter != entry_block->end (); ++iter)
+    if (jit_extract_argument *extract
+        = dynamic_cast<jit_extract_argument *> (*iter))
+      arguments.push_back (std::make_pair (extract->name (), true));
+
+  convert_llvm to_llvm (*this);
+  function = to_llvm.convert (module, arguments, blocks, constants);
+
+#ifdef OCTAVE_JIT_DEBUG
+  std::cout << "-------------------- llvm ir --------------------";
+  llvm::raw_os_ostream llvm_cout (std::cout);
+  function->print (llvm_cout);
+  std::cout << std::endl;
+  llvm::verifyFunction (*function);
+#endif
+}
+
+jit_convert::~jit_convert (void)
+{
+  for (std::list<jit_value *>::iterator iter = all_values.begin ();
+       iter != all_values.end (); ++iter)
+    delete *iter;
+}
+
+void
+jit_convert::visit_anon_fcn_handle (tree_anon_fcn_handle&)
+{
+  throw jit_fail_exception ();
+}
+
+void
+jit_convert::visit_argument_list (tree_argument_list&)
+{
+  throw jit_fail_exception ();
+}
+
+void
+jit_convert::visit_binary_expression (tree_binary_expression& be)
+{
+  if (be.op_type () >= octave_value::num_binary_ops)
+    {
+      tree_boolean_expression *boole;
+      boole = dynamic_cast<tree_boolean_expression *> (&be);
+      assert (boole);
+      bool is_and = boole->op_type () == tree_boolean_expression::bool_and;
+
+      std::string short_name = next_shortcircut_result ();
+      jit_variable *short_result = create<jit_variable> (short_name);
+      vmap[short_name] = short_result;
+
+      jit_block *done = create<jit_block> (block->name ());
+      tree_expression *lhs = be.lhs ();
+      jit_value *lhsv = visit (lhs);
+      lhsv = create_checked (&jit_typeinfo::logically_true, lhsv);
+
+      jit_block *short_early = create<jit_block> ("short_early");
+      append (short_early);
+
+      jit_block *short_cont = create<jit_block> ("short_cont");
+
+      if (is_and)
+        block->append (create<jit_cond_branch> (lhsv, short_cont, short_early));
+      else
+        block->append (create<jit_cond_branch> (lhsv, short_early, short_cont));
+
+      block = short_early;
+
+      jit_value *early_result = create<jit_const_bool> (! is_and);
+      block->append (create<jit_assign> (short_result, early_result));
+      block->append (create<jit_branch> (done));
+
+      append (short_cont);
+      block = short_cont;
+
+      tree_expression *rhs = be.rhs ();
+      jit_value *rhsv = visit (rhs);
+      rhsv = create_checked (&jit_typeinfo::logically_true, rhsv);
+      block->append (create<jit_assign> (short_result, rhsv));
+      block->append (create<jit_branch> (done));
+
+      append (done);
+      block = done;
+      result = short_result;
+    }
+  else
+    {
+      tree_expression *lhs = be.lhs ();
+      jit_value *lhsv = visit (lhs);
+
+      tree_expression *rhs = be.rhs ();
+      jit_value *rhsv = visit (rhs);
+
+      const jit_operation& fn = jit_typeinfo::binary_op (be.op_type ());
+      result = create_checked (fn, lhsv, rhsv);
+    }
+}
+
+void
+jit_convert::visit_break_command (tree_break_command&)
+{
+  breaks.push_back (block);
+  breaking = true;
+}
+
+void
+jit_convert::visit_colon_expression (tree_colon_expression& expr)
+{
+  // in the futher we need to add support for classes and deal with rvalues
+  jit_value *base = visit (expr.base ());
+  jit_value *limit = visit (expr.limit ());
+  jit_value *increment;
+  tree_expression *tinc = expr.increment ();
+
+  if (tinc)
+    increment = visit (tinc);
+  else
+    increment = create<jit_const_scalar> (1);
+
+  result = block->append (create<jit_call> (jit_typeinfo::make_range, base,
+                                            limit, increment));
+}
+
+void
+jit_convert::visit_continue_command (tree_continue_command&)
+{
+  continues.push_back (block);
+  breaking = true;
+}
+
+void
+jit_convert::visit_global_command (tree_global_command&)
+{
+  throw jit_fail_exception ();
+}
+
+void
+jit_convert::visit_persistent_command (tree_persistent_command&)
+{
+  throw jit_fail_exception ();
+}
+
+void
+jit_convert::visit_decl_elt (tree_decl_elt&)
+{
+  throw jit_fail_exception ();
+}
+
+void
+jit_convert::visit_decl_init_list (tree_decl_init_list&)
+{
+  throw jit_fail_exception ();
+}
+
+void
+jit_convert::visit_simple_for_command (tree_simple_for_command& cmd)
+{
+  // Note we do an initial check to see if the loop will run atleast once.
+  // This allows us to get better type inference bounds on variables defined
+  // and used only inside the for loop (e.g. the index variable)
+
+  // If we are a nested for loop we need to store the previous breaks
+  assert (! breaking);
+  unwind_protect prot;
+  prot.protect_var (breaks);
+  prot.protect_var (continues);
+  prot.protect_var (breaking);
+  breaks.clear ();
+  continues.clear ();
+
+  // we need a variable for our iterator, because it is used in multiple blocks
+  std::string iter_name = next_iterator ();
+  jit_variable *iterator = create<jit_variable> (iter_name);
+  create<jit_variable> (iter_name);
+  vmap[iter_name] = iterator;
+
+  jit_block *body = create<jit_block> ("for_body");
+  append (body);
+
+  jit_block *tail = create<jit_block> ("for_tail");
+
+  // do control expression, iter init, and condition check in prev_block (block)
+  // if we are the top level for loop, the bounds is an input argument.
+  jit_value *control = find_variable (next_for_bounds ());
+  if (! control)
+    control = visit (cmd.control_expr ());
+  jit_call *init_iter = create<jit_call> (jit_typeinfo::for_init, control);
+  block->append (init_iter);
+  block->append (create<jit_assign> (iterator, init_iter));
+
+  jit_value *check = block->append (create<jit_call> (jit_typeinfo::for_check,
+                                                      control, iterator));
+  block->append (create<jit_cond_branch> (check, body, tail));
+  block = body;
+
+  // compute the syntactical iterator
+  jit_call *idx_rhs = create<jit_call> (jit_typeinfo::for_index, control,
+                                        iterator);
+  block->append (idx_rhs);
+  do_assign (cmd.left_hand_side (), idx_rhs);
+
+  // do loop
+  tree_statement_list *pt_body = cmd.body ();
+  pt_body->accept (*this);
+
+  if (breaking && continues.empty ())
+    {
+      // WTF are you doing user? Every branch was a continue, why did you have
+      // a loop??? Users are silly people...
+      finish_breaks (tail, breaks);
+      append (tail);
+      block = tail;
+      return;
+    }
+
+  // check our condition, continues jump to this block
+  jit_block *check_block = create<jit_block> ("for_check");
+  append (check_block);
+
+  if (! breaking)
+    block->append (create<jit_branch> (check_block));
+  finish_breaks (check_block, continues);
+
+  block = check_block;
+  const jit_operation& add_fn = jit_typeinfo::binary_op (octave_value::op_add);
+  jit_value *one = create<jit_const_index> (1);
+  jit_call *iter_inc = create<jit_call> (add_fn, iterator, one);
+  block->append (iter_inc);
+  block->append (create<jit_assign> (iterator, iter_inc));
+  check = block->append (create<jit_call> (jit_typeinfo::for_check, control,
+                                           iterator));
+  block->append (create<jit_cond_branch> (check, body, tail));
+
+  // breaks will go to our tail
+  append (tail);
+  finish_breaks (tail, breaks);
+  block = tail;
+}
+
+void
+jit_convert::visit_complex_for_command (tree_complex_for_command&)
+{
+  throw jit_fail_exception ();
+}
+
+void
+jit_convert::visit_octave_user_script (octave_user_script&)
+{
+  throw jit_fail_exception ();
+}
+
+void
+jit_convert::visit_octave_user_function (octave_user_function&)
+{
+  throw jit_fail_exception ();
+}
+
+void
+jit_convert::visit_octave_user_function_header (octave_user_function&)
+{
+  throw jit_fail_exception ();
+}
+
+void
+jit_convert::visit_octave_user_function_trailer (octave_user_function&)
+{
+  throw jit_fail_exception ();
+}
+
+void
+jit_convert::visit_function_def (tree_function_def&)
+{
+  throw jit_fail_exception ();
+}
+
+void
+jit_convert::visit_identifier (tree_identifier& ti)
+{
+  if (ti.has_magic_end ())
+    {
+      if (!end_context.size ())
+        throw jit_fail_exception ("Illegal end");
+      result = block->append (create<jit_magic_end> (end_context));
+    }
+  else
+    result = get_variable (ti.name ());
+}
+
+void
+jit_convert::visit_if_clause (tree_if_clause&)
+{
+  throw jit_fail_exception ();
+}
+
+void
+jit_convert::visit_if_command (tree_if_command& cmd)
+{
+  tree_if_command_list *lst = cmd.cmd_list ();
+  assert (lst); // jwe: Can this be null?
+  lst->accept (*this);
+}
+
+void
+jit_convert::visit_if_command_list (tree_if_command_list& lst)
+{
+  tree_if_clause *last = lst.back ();
+  size_t last_else = static_cast<size_t> (last->is_else_clause ());
+
+  // entry_blocks represents the block you need to enter in order to execute
+  // the condition check for the ith clause. For the else, it is simple the
+  // else body. If there is no else body, then it is padded with the tail
+  std::vector<jit_block *> entry_blocks (lst.size () + 1 - last_else);
+  std::vector<jit_block *> branch_blocks (lst.size (), 0); // final blocks
+  entry_blocks[0] = block;
+
+  // we need to construct blocks first, because they have jumps to eachother
+  tree_if_command_list::iterator iter = lst.begin ();
+  ++iter;
+  for (size_t i = 1; iter != lst.end (); ++iter, ++i)
+    {
+      tree_if_clause *tic = *iter;
+      if (tic->is_else_clause ())
+        entry_blocks[i] = create<jit_block> ("else");
+      else
+        entry_blocks[i] = create<jit_block> ("ifelse_cond");
+    }
+
+  jit_block *tail = create<jit_block> ("if_tail");
+  if (! last_else)
+    entry_blocks[entry_blocks.size () - 1] = tail;
+
+  size_t num_incomming = 0; // number of incomming blocks to our tail
+  iter = lst.begin ();
+  for (size_t i = 0; iter != lst.end (); ++iter, ++i)
+    {
+      tree_if_clause *tic = *iter;
+      block = entry_blocks[i];
+      assert (block);
+
+      if (i) // the first block is prev_block, so it has already been added
+        append (entry_blocks[i]);
+
+      if (! tic->is_else_clause ())
+        {
+          tree_expression *expr = tic->condition ();
+          jit_value *cond = visit (expr);
+          jit_call *check = create_checked (&jit_typeinfo::logically_true,
+                                            cond);
+          jit_block *body = create<jit_block> (i == 0 ? "if_body"
+                                               : "ifelse_body");
+          append (body);
+
+          jit_instruction *br = create<jit_cond_branch> (check, body,
+                                                        entry_blocks[i + 1]);
+          block->append (br);
+          block = body;
+        }
+
+      tree_statement_list *stmt_lst = tic->commands ();
+      assert (stmt_lst); // jwe: Can this be null?
+      stmt_lst->accept (*this);
+
+      if (breaking)
+        breaking = false;
+      else
+        {
+          ++num_incomming;
+          block->append (create<jit_branch> (tail));
+        }
+    }
+
+  if (num_incomming || ! last_else)
+    {
+      append (tail);
+      block = tail;
+    }
+  else
+    // every branch broke, so we don't have a tail
+    breaking = true;
+}
+
+void
+jit_convert::visit_index_expression (tree_index_expression& exp)
+{
+  result = resolve (jit_typeinfo::paren_subsref (), exp);
+}
+
+void
+jit_convert::visit_matrix (tree_matrix&)
+{
+  throw jit_fail_exception ();
+}
+
+void
+jit_convert::visit_cell (tree_cell&)
+{
+  throw jit_fail_exception ();
+}
+
+void
+jit_convert::visit_multi_assignment (tree_multi_assignment&)
+{
+  throw jit_fail_exception ();
+}
+
+void
+jit_convert::visit_no_op_command (tree_no_op_command&)
+{
+  throw jit_fail_exception ();
+}
+
+void
+jit_convert::visit_constant (tree_constant& tc)
+{
+  octave_value v = tc.rvalue1 ();
+  if (v.is_real_scalar () && v.is_double_type ())
+    {
+      double dv = v.double_value ();
+      result = create<jit_const_scalar> (dv);
+    }
+  else if (v.is_range ())
+    {
+      Range rv = v.range_value ();
+      result = create<jit_const_range> (rv);
+    }
+  else if (v.is_complex_scalar ())
+    {
+      Complex cv = v.complex_value ();
+      result = create<jit_const_complex> (cv);
+    }
+  else
+    throw jit_fail_exception ("Unknown constant");
+}
+
+void
+jit_convert::visit_fcn_handle (tree_fcn_handle&)
+{
+  throw jit_fail_exception ();
+}
+
+void
+jit_convert::visit_parameter_list (tree_parameter_list&)
+{
+  throw jit_fail_exception ();
+}
+
+void
+jit_convert::visit_postfix_expression (tree_postfix_expression&)
+{
+  throw jit_fail_exception ();
+}
+
+void
+jit_convert::visit_prefix_expression (tree_prefix_expression&)
+{
+  throw jit_fail_exception ();
+}
+
+void
+jit_convert::visit_return_command (tree_return_command&)
+{
+  throw jit_fail_exception ();
+}
+
+void
+jit_convert::visit_return_list (tree_return_list&)
+{
+  throw jit_fail_exception ();
+}
+
+void
+jit_convert::visit_simple_assignment (tree_simple_assignment& tsa)
+{
+  if (tsa.op_type () != octave_value::op_asn_eq)
+    throw jit_fail_exception ("Unsupported assign");
+
+  // resolve rhs
+  tree_expression *rhs = tsa.right_hand_side ();
+  jit_value *rhsv = visit (rhs);
+
+  result = do_assign (tsa.left_hand_side (), rhsv);
+}
+
+void
+jit_convert::visit_statement (tree_statement& stmt)
+{
+  tree_command *cmd = stmt.command ();
+  tree_expression *expr = stmt.expression ();
+
+  if (cmd)
+    visit (cmd);
+  else
+    {
+      // stolen from tree_evaluator::visit_statement
+      bool do_bind_ans = false;
+
+      if (expr->is_identifier ())
+        {
+          tree_identifier *id = dynamic_cast<tree_identifier *> (expr);
+
+          do_bind_ans = (! id->is_variable ());
+        }
+      else
+        do_bind_ans = (! expr->is_assignment_expression ());
+
+      jit_value *expr_result = visit (expr);
+
+      if (do_bind_ans)
+        do_assign ("ans", expr_result, expr->print_result ());
+      else if (expr->is_identifier () && expr->print_result ())
+        {
+          // FIXME: ugly hack, we need to come up with a way to pass
+          // nargout to visit_identifier
+          const jit_operation& fn = jit_typeinfo::print_value ();
+          jit_const_string *name = create<jit_const_string> (expr->name ());
+          block->append (create<jit_call> (fn, name, expr_result));
+        }
+    }
+}
+
+void
+jit_convert::visit_statement_list (tree_statement_list& lst)
+{
+  for (tree_statement_list::iterator iter = lst.begin (); iter != lst.end();
+       ++iter)
+    {
+      tree_statement *elt = *iter;
+      // jwe: Can this ever be null?
+      assert (elt);
+      elt->accept (*this);
+
+      if (breaking)
+        break;
+    }
+}
+
+void
+jit_convert::visit_switch_case (tree_switch_case&)
+{
+  throw jit_fail_exception ();
+}
+
+void
+jit_convert::visit_switch_case_list (tree_switch_case_list&)
+{
+  throw jit_fail_exception ();
+}
+
+void
+jit_convert::visit_switch_command (tree_switch_command&)
+{
+  throw jit_fail_exception ();
+}
+
+void
+jit_convert::visit_try_catch_command (tree_try_catch_command&)
+{
+  throw jit_fail_exception ();
+}
+
+void
+jit_convert::visit_unwind_protect_command (tree_unwind_protect_command&)
+{
+  throw jit_fail_exception ();
+}
+
+void
+jit_convert::visit_while_command (tree_while_command& wc)
+{
+  assert (! breaking);
+  unwind_protect prot;
+  prot.protect_var (breaks);
+  prot.protect_var (continues);
+  prot.protect_var (breaking);
+  breaks.clear ();
+  continues.clear ();
+
+  jit_block *cond_check = create<jit_block> ("while_cond_check");
+  block->append (create<jit_branch> (cond_check));
+  append (cond_check);
+  block = cond_check;
+
+  tree_expression *expr = wc.condition ();
+  assert (expr && "While expression can not be null");
+  jit_value *check = visit (expr);
+  check = create_checked (&jit_typeinfo::logically_true, check);
+
+  jit_block *body = create<jit_block> ("while_body");
+  append (body);
+
+  jit_block *tail = create<jit_block> ("while_tail");
+  block->append (create<jit_cond_branch> (check, body, tail));
+  block = body;
+
+  tree_statement_list *loop_body = wc.body ();
+  if (loop_body)
+    loop_body->accept (*this);
+
+  finish_breaks (tail, breaks);
+  finish_breaks (cond_check, continues);
+
+  if (! breaking)
+    block->append (create<jit_branch> (cond_check));
+
+  append (tail);
+  block = tail;
+}
+
+void
+jit_convert::visit_do_until_command (tree_do_until_command&)
+{
+  throw jit_fail_exception ();
+}
+
+void
+jit_convert::append (jit_block *ablock)
+{
+  blocks.push_back (ablock);
+  ablock->stash_location (--blocks.end ());
+}
+
+void
+jit_convert::insert_before (block_iterator iter, jit_block *ablock)
+{
+  iter = blocks.insert (iter, ablock);
+  ablock->stash_location (iter);
+}
+
+void
+jit_convert::insert_after (block_iterator iter, jit_block *ablock)
+{
+  ++iter;
+  insert_before (iter, ablock);
+}
+
+jit_variable *
+jit_convert::find_variable (const std::string& vname) const
+{
+  vmap_t::const_iterator iter;
+  iter = vmap.find (vname);
+  return iter != vmap.end () ? iter->second : 0;
+}
+
+jit_variable *
+jit_convert::get_variable (const std::string& vname)
+{
+  jit_variable *ret = find_variable (vname);
+  if (ret)
+    return ret;
+
+  octave_value val = symbol_table::find (vname);
+  jit_type *type = jit_typeinfo::type_of (val);
+  return create_variable (vname, type);
+}
+
+jit_variable *
+jit_convert::create_variable (const std::string& vname, jit_type *type)
+{
+  jit_variable *var = create<jit_variable> (vname);
+  jit_extract_argument *extract;
+  extract = create<jit_extract_argument> (type, var);
+  entry_block->prepend (extract);
+  return vmap[vname] = var;
+}
+
+std::string
+jit_convert::next_name (const char *prefix, size_t& count, bool inc)
+{
+  std::stringstream ss;
+  ss << prefix << count;
+  if (inc)
+    ++count;
+  return ss.str ();
+}
+
+jit_instruction *
+jit_convert::resolve (const jit_operation& fres, tree_index_expression& exp,
+                      jit_value *extra_arg)
+{
+  std::string type = exp.type_tags ();
+  if (! (type.size () == 1 && type[0] == '('))
+    throw jit_fail_exception ("Unsupported index operation");
+
+  std::list<tree_argument_list *> args = exp.arg_lists ();
+  if (args.size () != 1)
+    throw jit_fail_exception ("Bad number of arguments in tree_index_expression");
+
+  tree_argument_list *arg_list = args.front ();
+  if (! arg_list)
+    throw jit_fail_exception ("null argument list");
+
+  if (arg_list->size () < 1)
+    throw jit_fail_exception ("Empty arg_list");
+
+  tree_expression *tree_object = exp.expression ();
+  jit_value *object = visit (tree_object);
+
+  size_t narg = arg_list->size ();
+  tree_argument_list::iterator iter = arg_list->begin ();
+  bool have_extra = extra_arg;
+  std::vector<jit_value *> call_args (narg + 1 + have_extra);
+  call_args[0] = object;
+
+  for (size_t idx = 0; iter != arg_list->end (); ++idx, ++iter)
+    {
+      unwind_protect prot;
+      prot.add_method (&end_context,
+                       &std::vector<jit_magic_end::context>::pop_back);
+      end_context.push_back (jit_magic_end::context (object, idx, narg));
+      call_args[idx + 1] = visit (*iter);
+    }
+
+  if (extra_arg)
+    call_args[call_args.size () - 1] = extra_arg;
+
+  return create_checked (fres, call_args);
+}
+
+jit_value *
+jit_convert::do_assign (tree_expression *exp, jit_value *rhs, bool artificial)
+{
+  if (! exp)
+    throw jit_fail_exception ("NULL lhs in assign");
+
+  if (isa<tree_identifier> (exp))
+    return do_assign (exp->name (), rhs, exp->print_result (), artificial);
+  else if (tree_index_expression *idx
+           = dynamic_cast<tree_index_expression *> (exp))
+    {
+      jit_value *new_object = resolve (jit_typeinfo::paren_subsasgn (), *idx,
+                                       rhs);
+      do_assign (idx->expression (), new_object, true);
+
+      // FIXME: Will not work for values that must be release/grabed
+      return rhs;
+    }
+  else
+    throw jit_fail_exception ("Unsupported assignment");
+}
+
+jit_value *
+jit_convert::do_assign (const std::string& lhs, jit_value *rhs,
+                        bool print, bool artificial)
+{
+  jit_variable *var = get_variable (lhs);
+  jit_assign *assign = block->append (create<jit_assign> (var, rhs));
+
+  if (artificial)
+    assign->mark_artificial ();
+
+  if (print)
+    {
+      const jit_operation& print_fn = jit_typeinfo::print_value ();
+      jit_const_string *name = create<jit_const_string> (lhs);
+      block->append (create<jit_call> (print_fn, name, var));
+    }
+
+  return var;
+}
+
+jit_value *
+jit_convert::visit (tree& tee)
+{
+  result = 0;
+  tee.accept (*this);
+
+  jit_value *ret = result;
+  result = 0;
+  return ret;
+}
+
+void
+jit_convert::append_users_term (jit_terminator *term)
+{
+  for (size_t i = 0; i < term->successor_count (); ++i)
+    {
+      if (term->alive (i))
+        {
+          jit_block *succ = term->successor (i);
+          for (jit_block::iterator iter = succ->begin (); iter != succ->end ()
+                 && isa<jit_phi> (*iter); ++iter)
+            push_worklist (*iter);
+
+          jit_terminator *sterm = succ->terminator ();
+          if (sterm)
+            push_worklist (sterm);
+        }
+    }
+}
+
+void
+jit_convert::merge_blocks (void)
+{
+  std::vector<jit_block *> dead;
+  for (block_list::iterator iter = blocks.begin (); iter != blocks.end ();
+       ++iter)
+    {
+      jit_block *b = *iter;
+      jit_block *merged = b->maybe_merge ();
+
+      if (merged)
+        {
+          if (merged == final_block)
+            final_block = b;
+
+          if (merged == entry_block)
+            entry_block = b;
+
+          dead.push_back (merged);
+        }
+    }
+
+  for (size_t i = 0; i < dead.size (); ++i)
+    blocks.erase (dead[i]->location ());
+}
+
+void
+jit_convert::construct_ssa (void)
+{
+  merge_blocks ();
+  final_block->label ();
+  final_block->compute_idom (entry_block);
+  entry_block->compute_df ();
+  entry_block->create_dom_tree ();
+
+  // insert phi nodes where needed, this is done on a per variable basis
+  for (vmap_t::iterator iter = vmap.begin (); iter != vmap.end (); ++iter)
+    {
+      jit_block::df_set visited, added_phi;
+      std::list<jit_block *> ssa_worklist;
+      iter->second->use_blocks (visited);
+      ssa_worklist.insert (ssa_worklist.begin (), visited.begin (),
+                           visited.end ());
+
+      while (ssa_worklist.size ())
+        {
+          jit_block *b = ssa_worklist.front ();
+          ssa_worklist.pop_front ();
+
+          for (jit_block::df_iterator diter = b->df_begin ();
+               diter != b->df_end (); ++diter)
+            {
+              jit_block *dblock = *diter;
+              if (! added_phi.count (dblock))
+                {
+                  jit_phi *phi = create<jit_phi> (iter->second,
+                                                  dblock->use_count ());
+                  dblock->prepend (phi);
+                  added_phi.insert (dblock);
+                }
+
+              if (! visited.count (dblock))
+                {
+                  ssa_worklist.push_back (dblock);
+                  visited.insert (dblock);
+                }
+            }
+        }
+    }
+
+  do_construct_ssa (*entry_block, entry_block->visit_count ());
+}
+
+void
+jit_convert::do_construct_ssa (jit_block& ablock, size_t avisit_count)
+{
+  if (ablock.visited (avisit_count))
+    return;
+
+  // replace variables with their current SSA value
+  for (jit_block::iterator iter = ablock.begin (); iter != ablock.end (); ++iter)
+    {
+      jit_instruction *instr = *iter;
+      instr->construct_ssa ();
+      instr->push_variable ();
+    }
+
+  // finish phi nodes of successors
+  for (size_t i = 0; i < ablock.successor_count (); ++i)
+    {
+      jit_block *finish = ablock.successor (i);
+
+      for (jit_block::iterator iter = finish->begin (); iter != finish->end ()
+             && isa<jit_phi> (*iter);)
+        {
+          jit_phi *phi = static_cast<jit_phi *> (*iter);
+          jit_variable *var = phi->dest ();
+          if (var->has_top ())
+            {
+              phi->add_incomming (&ablock, var->top ());
+              ++iter;
+            }
+          else
+            {
+              // temporaries may have extranious phi nodes which can be removed
+              assert (! phi->use_count ());
+              assert (var->name ().size () && var->name ()[0] == '#');
+              iter = finish->remove (iter);
+            }
+        }
+    }
+
+  for (size_t i = 0; i < ablock.dom_successor_count (); ++i)
+    do_construct_ssa (*ablock.dom_successor (i), avisit_count);
+
+  ablock.pop_all ();
+}
+
+void
+jit_convert::remove_dead ()
+{
+  block_list::iterator biter;
+  for (biter = blocks.begin (); biter != blocks.end (); ++biter)
+    {
+      jit_block *b = *biter;
+      if (b->alive ())
+        {
+          for (jit_block::iterator iter = b->begin (); iter != b->end ()
+                 && isa<jit_phi> (*iter);)
+            {
+              jit_phi *phi = static_cast<jit_phi *> (*iter);
+              if (phi->prune ())
+                iter = b->remove (iter);
+              else
+                ++iter;
+            }
+        }
+    }
+
+  for (biter = blocks.begin (); biter != blocks.end ();)
+    {
+      jit_block *b = *biter;
+      if (b->alive ())
+        {
+          // FIXME: A special case for jit_error_check, if we generalize to
+          // we will need to change!
+          jit_terminator *term = b->terminator ();
+          if (term && term->successor_count () == 2 && ! term->alive (0))
+            {
+              jit_block *succ = term->successor (1);
+              term->remove ();
+              jit_branch *abreak = b->append (create<jit_branch> (succ));
+              abreak->infer ();
+            }
+
+          ++biter;
+        }
+      else
+        {
+          jit_terminator *term = b->terminator ();
+          if (term)
+            term->remove ();
+          biter = blocks.erase (biter);
+        }
+    }
+}
+
+void
+jit_convert::place_releases (void)
+{
+  std::set<jit_value *> temporaries;
+  for (block_list::iterator iter = blocks.begin (); iter != blocks.end ();
+       ++iter)
+    {
+      jit_block& ablock = **iter;
+      if (ablock.id () != jit_block::NO_ID)
+        {
+          release_temp (ablock, temporaries);
+          release_dead_phi (ablock);
+        }
+    }
+}
+
+void
+jit_convert::release_temp (jit_block& ablock, std::set<jit_value *>& temp)
+{
+  for (jit_block::iterator iter = ablock.begin (); iter != ablock.end ();
+       ++iter)
+    {
+      jit_instruction *instr = *iter;
+
+      // check for temporaries that require release and live across
+      // multiple blocks
+      if (instr->needs_release ())
+        {
+          jit_block *fu_block = instr->first_use_block ();
+          if (fu_block && fu_block != &ablock)
+            temp.insert (instr);
+        }
+
+      if (isa<jit_call> (instr))
+        {
+          // place releases for temporary arguments
+          for (size_t i = 0; i < instr->argument_count (); ++i)
+            {
+              jit_value *arg = instr->argument (i);
+              if (arg->needs_release ())
+                {
+                  jit_call *release = create<jit_call> (&jit_typeinfo::release,
+                                                        arg);
+                  release->infer ();
+                  ablock.insert_after (iter, release);
+                  ++iter;
+                  temp.erase (arg);
+                }
+            }
+        }
+    }
+
+  if (! temp.size () || ! isa<jit_error_check> (ablock.terminator ()))
+    return;
+
+  // FIXME: If we support try/catch or unwind_protect final_block may not be the
+  // destination
+  jit_block *split = ablock.maybe_split (*this, final_block);
+  jit_terminator *term = split->terminator ();
+  for (std::set<jit_value *>::const_iterator iter = temp.begin ();
+       iter != temp.end (); ++iter)
+    {
+      jit_value *value = *iter;
+      jit_call *release = create<jit_call> (&jit_typeinfo::release, value);
+      split->insert_before (term, release);
+      release->infer ();
+    }
+}
+
+void
+jit_convert::release_dead_phi (jit_block& ablock)
+{
+  jit_block::iterator iter = ablock.begin ();
+  while (iter != ablock.end () && isa<jit_phi> (*iter))
+    {
+      jit_phi *phi = static_cast<jit_phi *> (*iter);
+      ++iter;
+
+      jit_use *use = phi->first_use ();
+      if (phi->use_count () == 1 && isa<jit_assign> (use->user ()))
+        {
+          // instead of releasing on assign, release on all incomming branches,
+          // this can get rid of casts inside loops
+          for (size_t i = 0; i < phi->argument_count (); ++i)
+            {
+              jit_value *arg = phi->argument (i);
+              jit_block *inc = phi->incomming (i);
+              jit_block *split = inc->maybe_split (*this, ablock);
+              jit_terminator *term = split->terminator ();
+              jit_call *release = create<jit_call> (jit_typeinfo::release, arg);
+              release->infer ();
+              split->insert_before (term, release);
+            }
+
+          phi->replace_with (0);
+          phi->remove ();
+        }
+    }
+}
+
+void
+jit_convert::simplify_phi (void)
+{
+  for (block_list::iterator biter = blocks.begin (); biter != blocks.end ();
+       ++biter)
+    {
+      jit_block &ablock = **biter;
+      for (jit_block::iterator iter = ablock.begin (); iter != ablock.end ()
+             && isa<jit_phi> (*iter); ++iter)
+        simplify_phi (*static_cast<jit_phi *> (*iter));
+    }
+}
+
+void
+jit_convert::simplify_phi (jit_phi& phi)
+{
+  jit_block& pblock = *phi.parent ();
+  const jit_operation& cast_fn = jit_typeinfo::cast (phi.type ());
+  jit_variable *dest = phi.dest ();
+  for (size_t i = 0; i < phi.argument_count (); ++i)
+    {
+      jit_value *arg = phi.argument (i);
+      if (arg->type () != phi.type ())
+        {
+          jit_block *pred = phi.incomming (i);
+          jit_block *split = pred->maybe_split (*this, pblock);
+          jit_terminator *term = split->terminator ();
+          jit_instruction *cast = create<jit_call> (cast_fn, arg);
+          jit_assign *assign = create<jit_assign> (dest, cast);
+
+          split->insert_before (term, cast);
+          split->insert_before (term, assign);
+          cast->infer ();
+          assign->infer ();
+          phi.stash_argument (i, assign);
+        }
+    }
+}
+
+void
+jit_convert::finish_breaks (jit_block *dest, const block_list& lst)
+{
+  for (block_list::const_iterator iter = lst.begin (); iter != lst.end ();
+       ++iter)
+    {
+      jit_block *b = *iter;
+      b->append (create<jit_branch> (dest));
+    }
+}
+
+// -------------------- jit_convert::convert_llvm --------------------
+llvm::Function *
+jit_convert::convert_llvm::convert (llvm::Module *module,
+                                    const std::vector<std::pair< std::string, bool> >& args,
+                                    const std::list<jit_block *>& blocks,
+                                    const std::list<jit_value *>& constants)
+{
+  jit_type *any = jit_typeinfo::get_any ();
+
+  // argument is an array of octave_base_value*, or octave_base_value**
+  llvm::Type *arg_type = any->to_llvm (); // this is octave_base_value*
+  arg_type = arg_type->getPointerTo ();
+  llvm::FunctionType *ft = llvm::FunctionType::get (llvm::Type::getVoidTy (context),
+                                                    arg_type, false);
+  function = llvm::Function::Create (ft, llvm::Function::ExternalLinkage,
+                                     "foobar", module);
+
+  try
+    {
+      prelude = llvm::BasicBlock::Create (context, "prelude", function);
+      builder.SetInsertPoint (prelude);
+
+      llvm::Value *arg = function->arg_begin ();
+      for (size_t i = 0; i < args.size (); ++i)
+        {
+          llvm::Value *loaded_arg = builder.CreateConstInBoundsGEP1_32 (arg, i);
+          arguments[args[i].first] = loaded_arg;
+        }
+
+      std::list<jit_block *>::const_iterator biter;
+      for (biter = blocks.begin (); biter != blocks.end (); ++biter)
+        {
+          jit_block *jblock = *biter;
+          llvm::BasicBlock *block = llvm::BasicBlock::Create (context,
+                                                              jblock->name (),
+                                                              function);
+          jblock->stash_llvm (block);
+        }
+
+      jit_block *first = *blocks.begin ();
+      builder.CreateBr (first->to_llvm ());
+
+      // constants aren't in the IR, we visit those first
+      for (std::list<jit_value *>::const_iterator iter = constants.begin ();
+           iter != constants.end (); ++iter)
+        if (! isa<jit_instruction> (*iter))
+          visit (*iter);
+
+      // convert all instructions
+      for (biter = blocks.begin (); biter != blocks.end (); ++biter)
+        visit (*biter);
+
+      // now finish phi nodes
+      for (biter = blocks.begin (); biter != blocks.end (); ++biter)
+        {
+          jit_block& block = **biter;
+          for (jit_block::iterator piter = block.begin ();
+               piter != block.end () && isa<jit_phi> (*piter); ++piter)
+            {
+              jit_instruction *phi = *piter;
+              finish_phi (static_cast<jit_phi *> (phi));
+            }
+        }
+
+      jit_block *last = blocks.back ();
+      builder.SetInsertPoint (last->to_llvm ());
+      builder.CreateRetVoid ();
+    } catch (const jit_fail_exception& e)
+    {
+      function->eraseFromParent ();
+      throw;
+    }
+
+  return function;
+}
+
+void
+jit_convert::convert_llvm::finish_phi (jit_phi *phi)
+{
+  llvm::PHINode *llvm_phi = phi->to_llvm ();
+  for (size_t i = 0; i < phi->argument_count (); ++i)
+    {
+      llvm::BasicBlock *pred = phi->incomming_llvm (i);
+      llvm_phi->addIncoming (phi->argument_llvm (i), pred);
+    }
+}
+
+void
+jit_convert::convert_llvm::visit (jit_const_string& cs)
+{
+  cs.stash_llvm (builder.CreateGlobalStringPtr (cs.value ()));
+}
+
+void
+jit_convert::convert_llvm::visit (jit_const_bool& cb)
+{
+  cb.stash_llvm (llvm::ConstantInt::get (cb.type_llvm (), cb.value ()));
+}
+
+void
+jit_convert::convert_llvm::visit (jit_const_scalar& cs)
+{
+  cs.stash_llvm (llvm::ConstantFP::get (cs.type_llvm (), cs.value ()));
+}
+
+void
+jit_convert::convert_llvm::visit (jit_const_complex& cc)
+{
+  llvm::Type *scalar_t = jit_typeinfo::get_scalar_llvm ();
+  llvm::Constant *values[2];
+  Complex value = cc.value ();
+  values[0] = llvm::ConstantFP::get (scalar_t, value.real ());
+  values[1] = llvm::ConstantFP::get (scalar_t, value.imag ());
+  cc.stash_llvm (llvm::ConstantVector::get (values));
+}
+
+void jit_convert::convert_llvm::visit (jit_const_index& ci)
+{
+  ci.stash_llvm (llvm::ConstantInt::get (ci.type_llvm (), ci.value ()));
+}
+
+void
+jit_convert::convert_llvm::visit (jit_const_range& cr)
+{
+  llvm::StructType *stype = llvm::cast<llvm::StructType>(cr.type_llvm ());
+  llvm::Type *scalar_t = jit_typeinfo::get_scalar_llvm ();
+  llvm::Type *idx = jit_typeinfo::get_index_llvm ();
+  const jit_range& rng = cr.value ();
+
+  llvm::Constant *constants[4];
+  constants[0] = llvm::ConstantFP::get (scalar_t, rng.base);
+  constants[1] = llvm::ConstantFP::get (scalar_t, rng.limit);
+  constants[2] = llvm::ConstantFP::get (scalar_t, rng.inc);
+  constants[3] = llvm::ConstantInt::get (idx, rng.nelem);
+
+  llvm::Value *as_llvm;
+  as_llvm = llvm::ConstantStruct::get (stype,
+                                       llvm::makeArrayRef (constants, 4));
+  cr.stash_llvm (as_llvm);
+}
+
+void
+jit_convert::convert_llvm::visit (jit_block& b)
+{
+  llvm::BasicBlock *block = b.to_llvm ();
+  builder.SetInsertPoint (block);
+  for (jit_block::iterator iter = b.begin (); iter != b.end (); ++iter)
+    visit (*iter);
+}
+
+void
+jit_convert::convert_llvm::visit (jit_branch& b)
+{
+  b.stash_llvm (builder.CreateBr (b.successor_llvm ()));
+}
+
+void
+jit_convert::convert_llvm::visit (jit_cond_branch& cb)
+{
+  llvm::Value *cond = cb.cond_llvm ();
+  llvm::Value *br;
+  br = builder.CreateCondBr (cond, cb.successor_llvm (0),
+                             cb.successor_llvm (1));
+  cb.stash_llvm (br);
+}
+
+void
+jit_convert::convert_llvm::visit (jit_call& call)
+{
+  const jit_function& ol = call.overload ();
+
+  std::vector<jit_value *> args (call.arguments ().size ());
+  for (size_t i = 0; i < args.size (); ++i)
+    args[i] = call.argument (i);
+
+  llvm::Value *ret = ol.call (builder, args);
+  call.stash_llvm (ret);
+}
+
+void
+jit_convert::convert_llvm::visit (jit_extract_argument& extract)
+{
+  llvm::Value *arg = arguments[extract.name ()];
+  assert (arg);
+  arg = builder.CreateLoad (arg);
+
+  const jit_function& ol = extract.overload ();
+  extract.stash_llvm (ol.call (builder, arg));
+}
+
+void
+jit_convert::convert_llvm::visit (jit_store_argument& store)
+{
+  const jit_function& ol = store.overload ();
+  llvm::Value *arg_value = ol.call (builder, store.result ());
+  llvm::Value *arg = arguments[store.name ()];
+  store.stash_llvm (builder.CreateStore (arg_value, arg));
+}
+
+void
+jit_convert::convert_llvm::visit (jit_phi& phi)
+{
+  // we might not have converted all incoming branches, so we don't
+  // set incomming branches now
+  llvm::PHINode *node = llvm::PHINode::Create (phi.type_llvm (),
+                                               phi.argument_count ());
+  builder.Insert (node);
+  phi.stash_llvm (node);
+}
+
+void
+jit_convert::convert_llvm::visit (jit_variable&)
+{
+  throw jit_fail_exception ("ERROR: SSA construction should remove all variables");
+}
+
+void
+jit_convert::convert_llvm::visit (jit_error_check& check)
+{
+  llvm::Value *cond = jit_typeinfo::insert_error_check (builder);
+  llvm::Value *br = builder.CreateCondBr (cond, check.successor_llvm (0),
+                                          check.successor_llvm (1));
+  check.stash_llvm (br);
+}
+
+void
+jit_convert::convert_llvm::visit (jit_assign& assign)
+{
+  jit_value *new_value = assign.src ();
+  assign.stash_llvm (new_value->to_llvm ());
+
+  if (assign.artificial ())
+    return;
+
+  if (isa<jit_assign_base> (new_value))
+    {
+      const jit_function& ol =  jit_typeinfo::get_grab (new_value->type ());
+      if (ol.valid ())
+        assign.stash_llvm (ol.call (builder, new_value));
+    }
+
+  jit_value *overwrite = assign.overwrite ();
+  if (isa<jit_assign_base> (overwrite))
+    {
+      const jit_function& ol = jit_typeinfo::get_release (overwrite->type ());
+      ol.call (builder, overwrite);
+    }
+}
+
+void
+jit_convert::convert_llvm::visit (jit_argument&)
+{}
+
+void
+jit_convert::convert_llvm::visit (jit_magic_end& me)
+{
+  const jit_function& ol = me.overload ();
+  llvm::Value *ret = ol.call (builder, me.resolve_context ());
+  me.stash_llvm (ret);
+}
+
+// -------------------- tree_jit --------------------
+
+tree_jit::tree_jit (void) : module (0), engine (0)
+{
+}
+
+tree_jit::~tree_jit (void)
+{}
+
+bool
+tree_jit::execute (tree_simple_for_command& cmd, const octave_value& bounds)
+{
+  const size_t MIN_TRIP_COUNT = 1000;
+
+  size_t tc = trip_count (bounds);
+  if (! tc || ! initialize ())
+    return false;
+
+  jit_info::vmap extra_vars;
+  extra_vars["#for_bounds0"] = &bounds;
+
+  jit_info *info = cmd.get_info ();
+  if (! info || ! info->match (extra_vars))
+    {
+      if (tc < MIN_TRIP_COUNT)
+        return false;
+
+      delete info;
+      info = new jit_info (*this, cmd, bounds);
+      cmd.stash_info (info);
+    }
+
+  return info->execute (extra_vars);
+}
+
+bool
+tree_jit::execute (tree_while_command& cmd)
+{
+  if (! initialize ())
+    return false;
+
+  jit_info *info = cmd.get_info ();
+  if (! info || ! info->match ())
+    {
+      delete info;
+      info = new jit_info (*this, cmd);
+      cmd.stash_info (info);
+    }
+
+  return info->execute ();
+}
+
+bool
+tree_jit::initialize (void)
+{
+  if (engine)
+    return true;
+
+  if (! module)
+    {
+      llvm::InitializeNativeTarget ();
+      module = new llvm::Module ("octave", context);
+    }
+
+  // sometimes this fails pre main
+  engine = llvm::ExecutionEngine::createJIT (module);
+
+  if (! engine)
+    return false;
+
+  module_pass_manager = new llvm::PassManager ();
+  module_pass_manager->add (llvm::createAlwaysInlinerPass ());
+
+  pass_manager = new llvm::FunctionPassManager (module);
+  pass_manager->add (new llvm::TargetData(*engine->getTargetData ()));
+  pass_manager->add (llvm::createBasicAliasAnalysisPass ());
+  pass_manager->add (llvm::createPromoteMemoryToRegisterPass ());
+  pass_manager->add (llvm::createInstructionCombiningPass ());
+  pass_manager->add (llvm::createReassociatePass ());
+  pass_manager->add (llvm::createGVNPass ());
+  pass_manager->add (llvm::createCFGSimplificationPass ());
+  pass_manager->doInitialization ();
+
+  jit_typeinfo::initialize (module, engine);
+
+  return true;
+}
+
+size_t
+tree_jit::trip_count (const octave_value& bounds) const
+{
+  if (bounds.is_range ())
+    {
+      Range rng = bounds.range_value ();
+      return rng.nelem ();
+    }
+
+  // unsupported type
+  return 0;
+}
+
+
+void
+tree_jit::optimize (llvm::Function *fn)
+{
+  module_pass_manager->run (*module);
+  pass_manager->run (*fn);
+
+#ifdef OCTAVE_JIT_DEBUG
+  std::string error;
+  llvm::raw_fd_ostream fout ("test.bc", error,
+                             llvm::raw_fd_ostream::F_Binary);
+  llvm::WriteBitcodeToFile (module, fout);
+#endif
+}
+
+// -------------------- jit_info --------------------
+jit_info::jit_info (tree_jit& tjit, tree& tee)
+  : engine (tjit.get_engine ()), function (0), llvm_function (0)
+{
+  try
+    {
+      jit_convert conv (tjit.get_module (), tee);
+      initialize (tjit, conv);
+    }
+  catch (const jit_fail_exception& e)
+    {
+#ifdef OCTAVE_JIT_DEBUG
+      if (e.known ())
+        std::cout << "jit fail: " << e.what () << std::endl;
+#endif
+    }
+}
+
+jit_info::jit_info (tree_jit& tjit, tree& tee, const octave_value& for_bounds)
+  : engine (tjit.get_engine ()), function (0), llvm_function (0)
+{
+  try
+    {
+      jit_convert conv (tjit.get_module (), tee,
+                        jit_typeinfo::type_of (for_bounds));
+      initialize (tjit, conv);
+    }
+  catch (const jit_fail_exception& e)
+    {
+#ifdef OCTAVE_JIT_DEBUG
+      if (e.known ())
+        std::cout << "jit fail: " << e.what () << std::endl;
+#endif
+    }
+}
+
+jit_info::~jit_info (void)
+{
+  if (llvm_function)
+    llvm_function->eraseFromParent ();
+}
+
+bool
+jit_info::execute (const vmap& extra_vars) const
+{
+  if (! function)
+    return false;
+
+  std::vector<octave_base_value *> real_arguments (arguments.size ());
+  for (size_t i = 0; i < arguments.size (); ++i)
+    {
+      if (arguments[i].second)
+        {
+          octave_value current = find (extra_vars, arguments[i].first);
+          octave_base_value *obv = current.internal_rep ();
+          obv->grab ();
+          real_arguments[i] = obv;
+        }
+    }
+
+  function (&real_arguments[0]);
+
+  for (size_t i = 0; i < arguments.size (); ++i)
+    {
+      const std::string& name = arguments[i].first;
+
+      // do not store for loop bounds temporary
+      if (name.size () && name[0] != '#')
+        symbol_table::varref (arguments[i].first) = real_arguments[i];
+    }
+
+  return true;
+}
+
+bool
+jit_info::match (const vmap& extra_vars) const
+{
+  if (! function)
+    return true;
+
+  for (size_t i = 0; i < bounds.size (); ++i)
+    {
+      const std::string& arg_name = bounds[i].second;
+      octave_value value = find (extra_vars, arg_name);
+      jit_type *type = jit_typeinfo::type_of (value);
+
+      // FIXME: Check for a parent relationship
+      if (type != bounds[i].first)
+        return false;
+    }
+
+  return true;
+}
+
+void
+jit_info::initialize (tree_jit& tjit, jit_convert& conv)
+{
+  llvm_function = conv.get_function ();
+  arguments = conv.get_arguments ();
+  bounds = conv.get_bounds ();
+
+  if (llvm_function)
+    {
+      tjit.optimize (llvm_function);
+
+#ifdef OCTAVE_JIT_DEBUG
+      std::cout << "-------------------- optimized llvm ir "
+                << "--------------------\n";
+      llvm::raw_os_ostream llvm_cout (std::cout);
+      llvm_function->print (llvm_cout);
+      llvm_cout.flush ();
+      std::cout << std::endl;
+#endif
+
+      void *void_fn = engine->getPointerToFunction (llvm_function);
+      function = reinterpret_cast<jited_function> (void_fn);
+    }
+}
+
+octave_value
+jit_info::find (const vmap& extra_vars, const std::string& vname) const
+{
+  vmap::const_iterator iter = extra_vars.find (vname);
+  return iter == extra_vars.end () ? symbol_table::varval (vname)
+    : *iter->second;
+}
+
+#endif
+
+
+/*
+Test some simple cases that compile.
+
+%!test
+%! inc = 1e-5;
+%! result = 0;
+%! for ii = 0:inc:1
+%!   result = result + inc * (1/3 * ii * ii);
+%! endfor
+%! assert (abs (result - 1/9) < 1e-5);
+
+%!test
+%! inc = 1e-5;
+%! result = 0;
+%! for ii = 0:inc:1
+%!   # the ^ operator's result is complex
+%!   result = result + inc * (1/3 * ii ^ 2);
+%! endfor
+%! assert (abs (result - 1/9) < 1e-5);
+
+%!test
+%! nr = 1001;
+%! mat = zeros (1, nr);
+%! for i = 1:nr
+%!   mat(i) = i;
+%! endfor
+%! assert (mat == 1:nr);
+
+%!test
+%! nr = 1001;
+%! mat = 1:nr;
+%! mat(end) = 0; # force mat to a matrix
+%! total = 0;
+%! for i = 1:nr
+%!   total = mat(i) + total;
+%! endfor
+%! assert (sum (mat) == total);
+
+%!test
+%! nr = 1001;
+%! mat = [3 1 5];
+%! try
+%!   for i = 1:nr
+%!     if i > 500
+%!       result = mat(100);
+%!     else
+%!       result = i;
+%!     endif
+%!   endfor
+%! catch
+%! end
+%! assert (result == 500);
+
+%!function result = gen_test (n)
+%!  result = double (rand (1, n) > .01);
+%!endfunction
+
+%!function z = vectorized (A, K)
+%!  temp = ones (1, K);
+%!  z = conv (A, temp);
+%!  z = z > K-1;
+%!  z = conv (z, temp);
+%!  z = z(K:end-K+1);
+%!  z = z >= 1;
+%!endfunction
+
+%!function z = loopy (A, K)
+%!  z = A;
+%!  n = numel (A);
+%!  counter = 0;
+%!  for ii=1:n
+%!    if z(ii)
+%!      counter = counter + 1;
+%!    else
+%!      if counter > 0 && counter < K
+%!        z(ii-counter:ii-1) = 0;
+%!      endif
+%!      counter = 0;
+%!    endif
+%!  endfor
+%!
+%!  if counter > 0 && counter < K
+%!    z(end-counter+1:end) = 0;
+%!  endif
+%!endfunction
+
+%!test
+%! test_set = gen_test (10000);
+%! assert (all (vectorized (test_set, 3) == loopy (test_set, 3)));
+
+%!test
+%! niter = 1001;
+%! i = 0;
+%! while (i < niter)
+%!   i = i + 1;
+%! endwhile
+%! assert (i == niter);
+
+%!test
+%! niter = 1001;
+%! result = 0;
+%! m = [5 10];
+%! for i=1:niter
+%!   result = result + m(end);
+%! endfor
+%! assert (result == m(end) * niter);
+
+%!test
+%! ndim = 100;
+%! result = 0;
+%! m = zeros (ndim);
+%! m(:) = 1:ndim^2;
+%! i = 1;
+%! while (i <= ndim)
+%!   for j = 1:ndim
+%!     result = result + m(i, j);
+%!    endfor
+%!   i = i + 1;
+%! endwhile
+%! assert (result == sum (sum (m)));
+
+%!test
+%! ndim = 100;
+%! m = zeros (ndim);
+%! i = 1;
+%! while (i <= ndim)
+%!   for j = 1:ndim
+%!     m(i, j) = (j - 1) * ndim + i;
+%!   endfor
+%!   i = i + 1;
+%! endwhile
+%! m2 = zeros (ndim);
+%! m2(:) = 1:(ndim^2);
+%! assert (all (m == m2));
+
+%!test
+%! ndim = 2;
+%! m = zeros (ndim, ndim, ndim, ndim);
+%! result = 0;
+%! i0 = 1;
+%! while (i0 <= ndim)
+%!   for i1 = 1:ndim
+%!     for i2 = 1:ndim
+%!       for i3 = 1:ndim
+%!         m(i0, i1, i2, i3) = 1;
+%!         m(i0, i1, i2, i3, 1, 1, 1, 1, 1, 1) = 1;
+%!         result = result + m(i0, i1, i2, i3);
+%!       endfor
+%!     endfor
+%!   endfor
+%!   i0 = i0 + 1;
+%! endwhile
+%! expected = ones (ndim, ndim, ndim, ndim);
+%! assert (all (m == expected));
+%! assert (result == sum (expected (:)));
+
+%!function test_divide ()
+%! state = warning ("query", "Octave:divide-by-zero").state;
+%! unwind_protect
+%!   warning ("error", "Octave:divide-by-zero");
+%!   for i=1:1e5
+%!     a = 1;
+%!     a / 0;
+%!   endfor
+%! unwind_protect_cleanup
+%!   warning (state, "Octave:divide-by-zero");
+%! end_unwind_protect
+%!endfunction
+
+%!error <division by zero> test_divide ()
+
+%!test
+%! while 1
+%!   a = 0;
+%!   result = a / 1;
+%!   break;
+%! endwhile
+%! assert (result, 0);
+
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/pt-jit.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,491 @@
+/*
+
+Copyright (C) 2012 Max Brister <max@2bass.com>
+
+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/>.
+
+*/
+
+#if !defined (octave_tree_jit_h)
+#define octave_tree_jit_h 1
+
+#ifdef HAVE_LLVM
+
+#include "jit-ir.h"
+
+#include "pt-walk.h"
+
+// -------------------- Current status --------------------
+// Simple binary operations (+-*/) on octave_scalar's (doubles) are optimized.
+// a = 5;
+// b = a * 5 + a;
+//
+// Indexing matrices with scalars works.
+//
+// if, elseif, else, break, continue, and for compile. Compilation is triggered
+// at the start of a simple for loop.
+//
+// The octave low level IR is a linear IR, it works by converting everything to
+// calls to jit_operations. This turns expressions like c = a + b into
+// c = call binary+ (a, b)
+// The jit_operations contain information about overloads for different types.
+// For, example, if we know a and b are scalars, then c must also be a scalar.
+//
+// Support for function calls is in progress. Currently, calls to sin with a
+// scalar argument will compile.
+//
+// TODO:
+// 1. Function calls (In progress)
+// 2. Cleanup/documentation
+// 3. ...
+// ---------------------------------------------------------
+
+// convert between IRs
+// FIXME: Class relationships are messy from here on down. They need to be
+// cleaned up.
+class
+jit_convert : public tree_walker
+{
+public:
+  typedef std::pair<jit_type *, std::string> type_bound;
+  typedef std::vector<type_bound> type_bound_vector;
+
+  jit_convert (llvm::Module *module, tree &tee, jit_type *for_bounds = 0);
+
+  ~jit_convert (void);
+
+  llvm::Function *get_function (void) const { return function; }
+
+  const std::vector<std::pair<std::string, bool> >& get_arguments(void) const
+  { return arguments; }
+
+  const type_bound_vector& get_bounds (void) const { return bounds; }
+
+  void visit_anon_fcn_handle (tree_anon_fcn_handle&);
+
+  void visit_argument_list (tree_argument_list&);
+
+  void visit_binary_expression (tree_binary_expression&);
+
+  void visit_break_command (tree_break_command&);
+
+  void visit_colon_expression (tree_colon_expression&);
+
+  void visit_continue_command (tree_continue_command&);
+
+  void visit_global_command (tree_global_command&);
+
+  void visit_persistent_command (tree_persistent_command&);
+
+  void visit_decl_elt (tree_decl_elt&);
+
+  void visit_decl_init_list (tree_decl_init_list&);
+
+  void visit_simple_for_command (tree_simple_for_command&);
+
+  void visit_complex_for_command (tree_complex_for_command&);
+
+  void visit_octave_user_script (octave_user_script&);
+
+  void visit_octave_user_function (octave_user_function&);
+
+  void visit_octave_user_function_header (octave_user_function&);
+
+  void visit_octave_user_function_trailer (octave_user_function&);
+
+  void visit_function_def (tree_function_def&);
+
+  void visit_identifier (tree_identifier&);
+
+  void visit_if_clause (tree_if_clause&);
+
+  void visit_if_command (tree_if_command&);
+
+  void visit_if_command_list (tree_if_command_list&);
+
+  void visit_index_expression (tree_index_expression&);
+
+  void visit_matrix (tree_matrix&);
+
+  void visit_cell (tree_cell&);
+
+  void visit_multi_assignment (tree_multi_assignment&);
+
+  void visit_no_op_command (tree_no_op_command&);
+
+  void visit_constant (tree_constant&);
+
+  void visit_fcn_handle (tree_fcn_handle&);
+
+  void visit_parameter_list (tree_parameter_list&);
+
+  void visit_postfix_expression (tree_postfix_expression&);
+
+  void visit_prefix_expression (tree_prefix_expression&);
+
+  void visit_return_command (tree_return_command&);
+
+  void visit_return_list (tree_return_list&);
+
+  void visit_simple_assignment (tree_simple_assignment&);
+
+  void visit_statement (tree_statement&);
+
+  void visit_statement_list (tree_statement_list&);
+
+  void visit_switch_case (tree_switch_case&);
+
+  void visit_switch_case_list (tree_switch_case_list&);
+
+  void visit_switch_command (tree_switch_command&);
+
+  void visit_try_catch_command (tree_try_catch_command&);
+
+  void visit_unwind_protect_command (tree_unwind_protect_command&);
+
+  void visit_while_command (tree_while_command&);
+
+  void visit_do_until_command (tree_do_until_command&);
+
+  // this would be easier with variadic templates
+  template <typename T>
+  T *create (void)
+  {
+    T *ret = new T();
+    track_value (ret);
+    return ret;
+  }
+
+#define DECL_ARG(n) const ARG ## n& arg ## n
+#define JIT_CREATE(N)                                           \
+  template <typename T, OCT_MAKE_DECL_LIST (typename, ARG, N)>  \
+  T *create (OCT_MAKE_LIST (DECL_ARG, N))                       \
+  {                                                             \
+    T *ret = new T (OCT_MAKE_ARG_LIST (arg, N));                \
+    track_value (ret);                                          \
+    return ret;                                                 \
+  }
+
+  JIT_CREATE (1)
+  JIT_CREATE (2)
+  JIT_CREATE (3)
+  JIT_CREATE (4)
+
+#undef JIT_CREATE
+
+#define JIT_CREATE_CHECKED(N)                                           \
+  template <OCT_MAKE_DECL_LIST (typename, ARG, N)>                      \
+  jit_call *create_checked (OCT_MAKE_LIST (DECL_ARG, N))                \
+  {                                                                     \
+    jit_call *ret = create<jit_call> (OCT_MAKE_ARG_LIST (arg, N));      \
+    return create_checked_impl (ret);                                   \
+  }
+
+  JIT_CREATE_CHECKED (1)
+  JIT_CREATE_CHECKED (2)
+  JIT_CREATE_CHECKED (3)
+  JIT_CREATE_CHECKED (4)
+
+#undef JIT_CREATE_CHECKED
+#undef DECL_ARG
+
+  typedef std::list<jit_block *> block_list;
+  typedef block_list::iterator block_iterator;
+
+  void append (jit_block *ablock);
+
+  void insert_before (block_iterator iter, jit_block *ablock);
+
+  void insert_before (jit_block *loc, jit_block *ablock)
+  {
+    insert_before (loc->location (), ablock);
+  }
+
+  void insert_after (block_iterator iter, jit_block *ablock);
+
+  void insert_after (jit_block *loc, jit_block *ablock)
+  {
+    insert_after (loc->location (), ablock);
+  }
+private:
+  std::vector<std::pair<std::string, bool> > arguments;
+  type_bound_vector bounds;
+
+  // used instead of return values from visit_* functions
+  jit_value *result;
+
+  jit_block *entry_block;
+
+  jit_block *final_block;
+
+  jit_block *block;
+
+  llvm::Function *function;
+
+  std::list<jit_block *> blocks;
+
+  std::list<jit_instruction *> worklist;
+
+  std::list<jit_value *> constants;
+
+  std::list<jit_value *> all_values;
+
+  std::vector<jit_magic_end::context> end_context;
+
+  size_t iterator_count;
+  size_t for_bounds_count;
+  size_t short_count;
+
+  typedef std::map<std::string, jit_variable *> vmap_t;
+  vmap_t vmap;
+
+  jit_call *create_checked_impl (jit_call *ret)
+  {
+    block->append (ret);
+    create_check (ret);
+    return ret;
+  }
+
+  jit_error_check *create_check (jit_call *call)
+  {
+    jit_block *normal = create<jit_block> (block->name ());
+    jit_error_check *ret
+      = block->append (create<jit_error_check> (call, normal, final_block));
+    append (normal);
+    block = normal;
+
+    return ret;
+  }
+
+  // get an existing vairable. If the variable does not exist, it will not be
+  // created
+  jit_variable *find_variable (const std::string& vname) const;
+
+  // get a variable, create it if it does not exist. The type will default to
+  // the variable's current type in the symbol table.
+  jit_variable *get_variable (const std::string& vname);
+
+  // create a variable of the given name and given type. Will also insert an
+  // extract statement
+  jit_variable *create_variable (const std::string& vname, jit_type *type);
+
+  // The name of the next for loop iterator. If inc is false, then the iterator
+  // counter will not be incremented.
+  std::string next_iterator (bool inc = true)
+  { return next_name ("#iter", iterator_count, inc); }
+
+  std::string next_for_bounds (bool inc = true)
+  { return next_name ("#for_bounds", for_bounds_count, inc); }
+
+  std::string next_shortcircut_result (bool inc = true)
+  { return next_name ("#shortcircut_result", short_count, inc); }
+
+  std::string next_name (const char *prefix, size_t& count, bool inc);
+
+  jit_instruction *resolve (const jit_operation& fres,
+                            tree_index_expression& exp,
+                            jit_value *extra_arg = 0);
+
+  jit_value *do_assign (tree_expression *exp, jit_value *rhs,
+                        bool artificial = false);
+
+  jit_value *do_assign (const std::string& lhs, jit_value *rhs, bool print,
+                        bool artificial = false);
+
+  jit_value *visit (tree *tee) { return visit (*tee); }
+
+  jit_value *visit (tree& tee);
+
+  void push_worklist (jit_instruction *instr)
+  {
+    if (! instr->in_worklist ())
+      {
+        instr->stash_in_worklist (true);
+        worklist.push_back (instr);
+      }
+  }
+
+  void append_users (jit_value *v)
+  {
+    for (jit_use *use = v->first_use (); use; use = use->next ())
+      push_worklist (use->user ());
+  }
+
+  void append_users_term (jit_terminator *term);
+
+  void track_value (jit_value *value)
+  {
+    if (value->type ())
+      constants.push_back (value);
+    all_values.push_back (value);
+  }
+
+  void merge_blocks (void);
+
+  void construct_ssa (void);
+
+  void do_construct_ssa (jit_block& block, size_t avisit_count);
+
+  void remove_dead ();
+
+  void place_releases (void);
+
+  void release_temp (jit_block& ablock, std::set<jit_value *>& temp);
+
+  void release_dead_phi (jit_block& ablock);
+
+  void simplify_phi (void);
+
+  void simplify_phi (jit_phi& phi);
+
+  void print_blocks (const std::string& header)
+  {
+    std::cout << "-------------------- " << header << " --------------------\n";
+    for (std::list<jit_block *>::iterator iter = blocks.begin ();
+         iter != blocks.end (); ++iter)
+      {
+        assert (*iter);
+        (*iter)->print (std::cout, 0);
+      }
+    std::cout << std::endl;
+  }
+
+  void print_dom (void)
+  {
+    std::cout << "-------------------- dom info --------------------\n";
+    for (std::list<jit_block *>::iterator iter = blocks.begin ();
+         iter != blocks.end (); ++iter)
+      {
+        assert (*iter);
+        (*iter)->print_dom (std::cout);
+      }
+    std::cout << std::endl;
+  }
+
+  bool breaking; // true if we are breaking OR continuing
+  block_list breaks;
+  block_list continues;
+
+  void finish_breaks (jit_block *dest, const block_list& lst);
+
+  // this case is much simpler, just convert from the jit ir to llvm
+  class
+  convert_llvm : public jit_ir_walker
+  {
+  public:
+    convert_llvm (jit_convert& jc) : jthis (jc) {}
+
+    llvm::Function *convert (llvm::Module *module,
+                             const std::vector<std::pair<std::string, bool> >& args,
+                             const std::list<jit_block *>& blocks,
+                             const std::list<jit_value *>& constants);
+
+#define JIT_METH(clname)                        \
+    virtual void visit (jit_ ## clname&);
+
+    JIT_VISIT_IR_CLASSES;
+
+#undef JIT_METH
+  private:
+    // name -> llvm argument
+    std::map<std::string, llvm::Value *> arguments;
+
+    void finish_phi (jit_phi *phi);
+
+    void visit (jit_value *jvalue)
+    {
+      return visit (*jvalue);
+    }
+
+    void visit (jit_value &jvalue)
+    {
+      jvalue.accept (*this);
+    }
+  private:
+    jit_convert &jthis;
+    llvm::Function *function;
+    llvm::BasicBlock *prelude;
+  };
+};
+
+class jit_info;
+
+class
+tree_jit
+{
+public:
+  tree_jit (void);
+
+  ~tree_jit (void);
+
+  bool execute (tree_simple_for_command& cmd, const octave_value& bounds);
+
+  bool execute (tree_while_command& cmd);
+
+  llvm::ExecutionEngine *get_engine (void) const { return engine; }
+
+  llvm::Module *get_module (void) const { return module; }
+
+  void optimize (llvm::Function *fn);
+ private:
+  bool initialize (void);
+
+  size_t trip_count (const octave_value& bounds) const;
+
+  // FIXME: Temorary hack to test
+  typedef std::map<tree *, jit_info *> compiled_map;
+  llvm::Module *module;
+  llvm::PassManager *module_pass_manager;
+  llvm::FunctionPassManager *pass_manager;
+  llvm::ExecutionEngine *engine;
+};
+
+class
+jit_info
+{
+public:
+  // we use a pointer here so we don't have to include ov.h
+  typedef std::map<std::string, const octave_value *> vmap;
+
+  jit_info (tree_jit& tjit, tree& tee);
+
+  jit_info (tree_jit& tjit, tree& tee, const octave_value& for_bounds);
+
+  ~jit_info (void);
+
+  bool execute (const vmap& extra_vars = vmap ()) const;
+
+  bool match (const vmap& extra_vars = vmap ()) const;
+private:
+  typedef jit_convert::type_bound type_bound;
+  typedef jit_convert::type_bound_vector type_bound_vector;
+  typedef void (*jited_function)(octave_base_value**);
+
+  void initialize (tree_jit& tjit, jit_convert& conv);
+
+  octave_value find (const vmap& extra_vars, const std::string& vname) const;
+
+  llvm::ExecutionEngine *engine;
+  jited_function function;
+  llvm::Function *llvm_function;
+
+  std::vector<std::pair<std::string, bool> > arguments;
+  type_bound_vector bounds;
+};
+
+#endif
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/siglist.c	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,232 @@
+/*
+
+Copyright (C) 2000-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <signal.h>
+
+#include "siglist.h"
+
+/* The following is all borrowed from Emacs.  */
+
+#if ! (defined HAVE_STRSIGNAL || HAVE_DECL_SYS_SIGLIST)
+
+static char *my_sys_siglist[NSIG];
+
+#ifdef sys_siglist
+#undef sys_siglist
+#endif
+#define sys_siglist my_sys_siglist
+
+#endif
+
+void
+init_signals (void)
+{
+#if ! (defined HAVE_STRSIGNAL || HAVE_DECL_SYS_SIGLIST)
+
+  static int initialized = 0;
+
+  if (! initialized)
+    {
+      initialized = 1;
+
+# ifdef SIGABRT
+      sys_siglist[SIGABRT] = "Aborted";
+# endif
+# ifdef SIGAIO
+      sys_siglist[SIGAIO] = "LAN I/O interrupt";
+# endif
+# ifdef SIGALRM
+      sys_siglist[SIGALRM] = "Alarm clock";
+# endif
+# ifdef SIGBUS
+      sys_siglist[SIGBUS] = "Bus error";
+# endif
+# ifdef SIGCLD
+      sys_siglist[SIGCLD] = "Child status changed";
+# endif
+# ifdef SIGCHLD
+      sys_siglist[SIGCHLD] = "Child status changed";
+# endif
+# ifdef SIGCONT
+      sys_siglist[SIGCONT] = "Continued";
+# endif
+# ifdef SIGDANGER
+      sys_siglist[SIGDANGER] = "Swap space dangerously low";
+# endif
+# ifdef SIGDGNOTIFY
+      sys_siglist[SIGDGNOTIFY] = "Notification message in queue";
+# endif
+# ifdef SIGEMT
+      sys_siglist[SIGEMT] = "Emulation trap";
+# endif
+# ifdef SIGFPE
+      sys_siglist[SIGFPE] = "Arithmetic exception";
+# endif
+# ifdef SIGFREEZE
+      sys_siglist[SIGFREEZE] = "SIGFREEZE";
+# endif
+# ifdef SIGGRANT
+      sys_siglist[SIGGRANT] = "Monitor mode granted";
+# endif
+# ifdef SIGHUP
+      sys_siglist[SIGHUP] = "Hangup";
+# endif
+# ifdef SIGILL
+      sys_siglist[SIGILL] = "Illegal instruction";
+# endif
+# ifdef SIGINT
+      sys_siglist[SIGINT] = "Interrupt";
+# endif
+# ifdef SIGIO
+      sys_siglist[SIGIO] = "I/O possible";
+# endif
+# ifdef SIGIOINT
+      sys_siglist[SIGIOINT] = "I/O intervention required";
+# endif
+# ifdef SIGIOT
+      sys_siglist[SIGIOT] = "IOT trap";
+# endif
+# ifdef SIGKILL
+      sys_siglist[SIGKILL] = "Killed";
+# endif
+# ifdef SIGLOST
+      sys_siglist[SIGLOST] = "Resource lost";
+# endif
+# ifdef SIGLWP
+      sys_siglist[SIGLWP] = "SIGLWP";
+# endif
+# ifdef SIGMSG
+      sys_siglist[SIGMSG] = "Monitor mode data available";
+# endif
+# ifdef SIGPHONE
+      sys_siglist[SIGWIND] = "SIGPHONE";
+# endif
+# ifdef SIGPIPE
+      sys_siglist[SIGPIPE] = "Broken pipe";
+# endif
+# ifdef SIGPOLL
+      sys_siglist[SIGPOLL] = "Pollable event occurred";
+# endif
+# ifdef SIGPROF
+      sys_siglist[SIGPROF] = "Profiling timer expired";
+# endif
+# ifdef SIGPTY
+      sys_siglist[SIGPTY] = "PTY I/O interrupt";
+# endif
+# ifdef SIGPWR
+      sys_siglist[SIGPWR] = "Power-fail restart";
+# endif
+# ifdef SIGQUIT
+      sys_siglist[SIGQUIT] = "Quit";
+# endif
+# ifdef SIGRETRACT
+      sys_siglist[SIGRETRACT] = "Need to relinguish monitor mode";
+# endif
+# ifdef SIGSAK
+      sys_siglist[SIGSAK] = "Secure attention";
+# endif
+# ifdef SIGSEGV
+      sys_siglist[SIGSEGV] = "Segmentation violation";
+# endif
+# ifdef SIGSOUND
+      sys_siglist[SIGSOUND] = "Sound completed";
+# endif
+# ifdef SIGSTOP
+      sys_siglist[SIGSTOP] = "Stopped (signal)";
+# endif
+# ifdef SIGSTP
+      sys_siglist[SIGSTP] = "Stopped (user)";
+# endif
+# ifdef SIGSYS
+      sys_siglist[SIGSYS] = "Bad argument to system call";
+# endif
+# ifdef SIGTERM
+      sys_siglist[SIGTERM] = "Terminated";
+# endif
+# ifdef SIGTHAW
+      sys_siglist[SIGTHAW] = "SIGTHAW";
+# endif
+# ifdef SIGTRAP
+      sys_siglist[SIGTRAP] = "Trace/breakpoint trap";
+# endif
+# ifdef SIGTSTP
+      sys_siglist[SIGTSTP] = "Stopped (user)";
+# endif
+# ifdef SIGTTIN
+      sys_siglist[SIGTTIN] = "Stopped (tty input)";
+# endif
+# ifdef SIGTTOU
+      sys_siglist[SIGTTOU] = "Stopped (tty output)";
+# endif
+# ifdef SIGURG
+      sys_siglist[SIGURG] = "Urgent I/O condition";
+# endif
+# ifdef SIGUSR1
+      sys_siglist[SIGUSR1] = "User defined signal 1";
+# endif
+# ifdef SIGUSR2
+      sys_siglist[SIGUSR2] = "User defined signal 2";
+# endif
+# ifdef SIGVTALRM
+      sys_siglist[SIGVTALRM] = "Virtual timer expired";
+# endif
+# ifdef SIGWAITING
+      sys_siglist[SIGWAITING] = "Process's LWPs are blocked";
+# endif
+# ifdef SIGWINCH
+      sys_siglist[SIGWINCH] = "Window size changed";
+# endif
+# ifdef SIGWIND
+      sys_siglist[SIGWIND] = "SIGWIND";
+# endif
+# ifdef SIGXCPU
+      sys_siglist[SIGXCPU] = "CPU time limit exceeded";
+# endif
+# ifdef SIGXFSZ
+      sys_siglist[SIGXFSZ] = "File size limit exceeded";
+# endif
+    }
+
+#endif
+}
+
+#if ! defined (HAVE_STRSIGNAL)
+
+char *
+strsignal (int code)
+{
+  char *signame = "";
+
+  if (0 <= code && code < NSIG)
+    {
+      /* Cast to suppress warning if the table has const char *.  */
+      signame = (char *) sys_siglist[code];
+    }
+
+  return signame;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/siglist.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,47 @@
+/*
+
+Copyright (C) 2000-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if !defined (octave_siglist_h)
+#define octave_siglist_h 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* This is borrowed from Emacs.  */
+
+#if ! defined (HAVE_DECL_SYS_SIGLIST)
+extern char *sys_siglist[];
+#endif
+
+extern void init_signals (void);
+
+#if ! defined (HAVE_STRSIGNAL)
+extern char *strsignal (int);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/sparse-xdiv.cc	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,633 @@
+/*
+
+Copyright (C) 2004-2012 David Bateman
+Copyright (C) 1998-2004 Andy Adler
+
+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/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <cassert>
+
+#include "Array-util.h"
+#include "oct-cmplx.h"
+#include "quit.h"
+#include "error.h"
+#include "lo-ieee.h"
+
+#include "dSparse.h"
+#include "dDiagMatrix.h"
+#include "CSparse.h"
+#include "CDiagMatrix.h"
+#include "oct-spparms.h"
+#include "sparse-xdiv.h"
+
+static void
+solve_singularity_warning (double rcond)
+{
+  warning ("matrix singular to machine precision, rcond = %g", rcond);
+  warning ("attempting to find minimum norm solution");
+}
+
+template <class T1, class T2>
+bool
+mx_leftdiv_conform (const T1& a, const T2& b)
+{
+  octave_idx_type a_nr = a.rows ();
+  octave_idx_type b_nr = b.rows ();
+
+  if (a_nr != b_nr)
+    {
+      octave_idx_type a_nc = a.cols ();
+      octave_idx_type b_nc = b.cols ();
+
+      gripe_nonconformant ("operator \\", a_nr, a_nc, b_nr, b_nc);
+      return false;
+    }
+
+  return true;
+}
+
+#define INSTANTIATE_MX_LEFTDIV_CONFORM(T1, T2) \
+  template bool mx_leftdiv_conform (const T1&, const T2&)
+
+INSTANTIATE_MX_LEFTDIV_CONFORM (SparseMatrix, SparseMatrix);
+INSTANTIATE_MX_LEFTDIV_CONFORM (SparseMatrix, SparseComplexMatrix);
+INSTANTIATE_MX_LEFTDIV_CONFORM (SparseComplexMatrix, SparseMatrix);
+INSTANTIATE_MX_LEFTDIV_CONFORM (SparseComplexMatrix, SparseComplexMatrix);
+INSTANTIATE_MX_LEFTDIV_CONFORM (SparseMatrix, Matrix);
+INSTANTIATE_MX_LEFTDIV_CONFORM (SparseMatrix, ComplexMatrix);
+INSTANTIATE_MX_LEFTDIV_CONFORM (SparseComplexMatrix, Matrix);
+INSTANTIATE_MX_LEFTDIV_CONFORM (SparseComplexMatrix, ComplexMatrix);
+INSTANTIATE_MX_LEFTDIV_CONFORM (DiagMatrix, SparseMatrix);
+INSTANTIATE_MX_LEFTDIV_CONFORM (DiagMatrix, SparseComplexMatrix);
+INSTANTIATE_MX_LEFTDIV_CONFORM (ComplexDiagMatrix, SparseMatrix);
+INSTANTIATE_MX_LEFTDIV_CONFORM (ComplexDiagMatrix, SparseComplexMatrix);
+
+template <class T1, class T2>
+bool
+mx_div_conform (const T1& a, const T2& b)
+{
+  octave_idx_type a_nc = a.cols ();
+  octave_idx_type b_nc = b.cols ();
+
+  if (a_nc != b_nc)
+    {
+      octave_idx_type a_nr = a.rows ();
+      octave_idx_type b_nr = b.rows ();
+
+      gripe_nonconformant ("operator /", a_nr, a_nc, b_nr, b_nc);
+      return false;
+    }
+
+  return true;
+}
+
+#define INSTANTIATE_MX_DIV_CONFORM(T1, T2) \
+  template bool mx_div_conform (const T1&, const T2&)
+
+INSTANTIATE_MX_DIV_CONFORM (SparseMatrix, SparseMatrix);
+INSTANTIATE_MX_DIV_CONFORM (SparseMatrix, SparseComplexMatrix);
+INSTANTIATE_MX_DIV_CONFORM (SparseComplexMatrix, SparseMatrix);
+INSTANTIATE_MX_DIV_CONFORM (SparseComplexMatrix, SparseComplexMatrix);
+INSTANTIATE_MX_DIV_CONFORM (Matrix, SparseMatrix);
+INSTANTIATE_MX_DIV_CONFORM (Matrix, SparseComplexMatrix);
+INSTANTIATE_MX_DIV_CONFORM (ComplexMatrix, SparseMatrix);
+INSTANTIATE_MX_DIV_CONFORM (ComplexMatrix, SparseComplexMatrix);
+INSTANTIATE_MX_DIV_CONFORM (SparseMatrix, DiagMatrix);
+INSTANTIATE_MX_DIV_CONFORM (SparseMatrix, ComplexDiagMatrix);
+INSTANTIATE_MX_DIV_CONFORM (SparseComplexMatrix, DiagMatrix);
+INSTANTIATE_MX_DIV_CONFORM (SparseComplexMatrix, ComplexDiagMatrix);
+
+// Right division functions.  X / Y = X * inv (Y) = (inv (Y') * X')'
+//
+//                  Y / X:   m   cm   sm  scm
+//                   +--   +---+----+----+----+
+//   sparse matrix         | 1 |  3 |  5 |  7 |
+//                         +---+----+----+----+
+//   sparse complex_matrix | 2 |  4 |  6 |  8 |
+//                         +---+----+----+----+
+//   diagonal matrix                |  9 | 11 |
+//                                  +----+----+
+//   complex diag. matrix           | 10 | 12 |
+//                                  +----+----+
+
+// -*- 1 -*-
+Matrix
+xdiv (const Matrix& a, const SparseMatrix& b, MatrixType &typ)
+{
+  if (! mx_div_conform (a, b))
+    return Matrix ();
+
+  Matrix atmp = a.transpose ();
+  SparseMatrix btmp = b.transpose ();
+  MatrixType btyp = typ.transpose ();
+
+  octave_idx_type info;
+  double rcond = 0.0;
+  Matrix result = btmp.solve (btyp, atmp, info, rcond,
+                              solve_singularity_warning);
+
+  typ = btyp.transpose ();
+  return result.transpose ();
+}
+
+// -*- 2 -*-
+ComplexMatrix
+xdiv (const Matrix& a, const SparseComplexMatrix& b, MatrixType &typ)
+{
+  if (! mx_div_conform (a, b))
+    return ComplexMatrix ();
+
+  Matrix atmp = a.transpose ();
+  SparseComplexMatrix btmp = b.hermitian ();
+  MatrixType btyp = typ.transpose ();
+
+  octave_idx_type info;
+  double rcond = 0.0;
+  ComplexMatrix result
+    = btmp.solve (btyp, atmp, info, rcond, solve_singularity_warning);
+
+  typ = btyp.transpose ();
+  return result.hermitian ();
+}
+
+// -*- 3 -*-
+ComplexMatrix
+xdiv (const ComplexMatrix& a, const SparseMatrix& b, MatrixType &typ)
+{
+  if (! mx_div_conform (a, b))
+    return ComplexMatrix ();
+
+  ComplexMatrix atmp = a.hermitian ();
+  SparseMatrix btmp = b.transpose ();
+  MatrixType btyp = typ.transpose ();
+
+  octave_idx_type info;
+  double rcond = 0.0;
+  ComplexMatrix result
+    = btmp.solve (btyp, atmp, info, rcond, solve_singularity_warning);
+
+  typ = btyp.transpose ();
+  return result.hermitian ();
+}
+
+// -*- 4 -*-
+ComplexMatrix
+xdiv (const ComplexMatrix& a, const SparseComplexMatrix& b, MatrixType &typ)
+{
+  if (! mx_div_conform (a, b))
+    return ComplexMatrix ();
+
+  ComplexMatrix atmp = a.hermitian ();
+  SparseComplexMatrix btmp = b.hermitian ();
+  MatrixType btyp = typ.transpose ();
+
+  octave_idx_type info;
+  double rcond = 0.0;
+  ComplexMatrix result
+    = btmp.solve (btyp, atmp, info, rcond, solve_singularity_warning);
+
+  typ = btyp.transpose ();
+  return result.hermitian ();
+}
+
+// -*- 5 -*-
+SparseMatrix
+xdiv (const SparseMatrix& a, const SparseMatrix& b, MatrixType &typ)
+{
+  if (! mx_div_conform (a, b))
+    return SparseMatrix ();
+
+  SparseMatrix atmp = a.transpose ();
+  SparseMatrix btmp = b.transpose ();
+  MatrixType btyp = typ.transpose ();
+
+  octave_idx_type info;
+  double rcond = 0.0;
+  SparseMatrix result = btmp.solve (btyp, atmp, info, rcond,
+                                    solve_singularity_warning);
+
+  typ = btyp.transpose ();
+  return result.transpose ();
+}
+
+// -*- 6 -*-
+SparseComplexMatrix
+xdiv (const SparseMatrix& a, const SparseComplexMatrix& b, MatrixType &typ)
+{
+  if (! mx_div_conform (a, b))
+    return SparseComplexMatrix ();
+
+  SparseMatrix atmp = a.transpose ();
+  SparseComplexMatrix btmp = b.hermitian ();
+  MatrixType btyp = typ.transpose ();
+
+  octave_idx_type info;
+  double rcond = 0.0;
+  SparseComplexMatrix result
+    = btmp.solve (btyp, atmp, info, rcond, solve_singularity_warning);
+
+  typ = btyp.transpose ();
+  return result.hermitian ();
+}
+
+// -*- 7 -*-
+SparseComplexMatrix
+xdiv (const SparseComplexMatrix& a, const SparseMatrix& b, MatrixType &typ)
+{
+  if (! mx_div_conform (a, b))
+    return SparseComplexMatrix ();
+
+  SparseComplexMatrix atmp = a.hermitian ();
+  SparseMatrix btmp = b.transpose ();
+  MatrixType btyp = typ.transpose ();
+
+  octave_idx_type info;
+  double rcond = 0.0;
+  SparseComplexMatrix result
+    = btmp.solve (btyp, atmp, info, rcond, solve_singularity_warning);
+
+  typ = btyp.transpose ();
+  return result.hermitian ();
+}
+
+// -*- 8 -*-
+SparseComplexMatrix
+xdiv (const SparseComplexMatrix& a, const SparseComplexMatrix& b, MatrixType &typ)
+{
+  if (! mx_div_conform (a, b))
+    return SparseComplexMatrix ();
+
+  SparseComplexMatrix atmp = a.hermitian ();
+  SparseComplexMatrix btmp = b.hermitian ();
+  MatrixType btyp = typ.transpose ();
+
+  octave_idx_type info;
+  double rcond = 0.0;
+  SparseComplexMatrix result
+    = btmp.solve (btyp, atmp, info, rcond, solve_singularity_warning);
+
+  typ = btyp.transpose ();
+  return result.hermitian ();
+}
+
+template <typename RT, typename SM, typename DM>
+RT do_rightdiv_sm_dm (const SM& a, const DM& d)
+{
+  const octave_idx_type d_nr = d.rows ();
+
+  const octave_idx_type a_nr = a.rows ();
+  const octave_idx_type a_nc = a.cols ();
+
+  using std::min;
+  const octave_idx_type nc = min (d_nr, a_nc);
+
+  if ( ! mx_div_conform (a, d))
+    return RT ();
+
+  const octave_idx_type nz = a.nnz ();
+  RT r (a_nr, nc, nz);
+
+  typedef typename DM::element_type DM_elt_type;
+  const DM_elt_type zero = DM_elt_type ();
+
+  octave_idx_type k_result = 0;
+  for (octave_idx_type j = 0; j < nc; ++j)
+    {
+      octave_quit ();
+      const DM_elt_type s = d.dgelem (j);
+      const octave_idx_type colend = a.cidx (j+1);
+      r.xcidx (j) = k_result;
+      if (s != zero)
+        for (octave_idx_type k = a.cidx (j); k < colend; ++k)
+          {
+            r.xdata (k_result) = a.data (k) / s;
+            r.xridx (k_result) = a.ridx (k);
+            ++k_result;
+          }
+    }
+  r.xcidx (nc) = k_result;
+
+  r.maybe_compress (true);
+  return r;
+}
+
+// -*- 9 -*-
+SparseMatrix
+xdiv (const SparseMatrix& a, const DiagMatrix& b, MatrixType &)
+{
+  return do_rightdiv_sm_dm<SparseMatrix> (a, b);
+}
+
+// -*- 10 -*-
+SparseComplexMatrix
+xdiv (const SparseMatrix& a, const ComplexDiagMatrix& b, MatrixType &)
+{
+  return do_rightdiv_sm_dm<SparseComplexMatrix> (a, b);
+}
+
+// -*- 11 -*-
+SparseComplexMatrix
+xdiv (const SparseComplexMatrix& a, const DiagMatrix& b, MatrixType &)
+{
+  return do_rightdiv_sm_dm<SparseComplexMatrix> (a, b);
+}
+
+// -*- 12 -*-
+SparseComplexMatrix
+xdiv (const SparseComplexMatrix& a, const ComplexDiagMatrix& b, MatrixType &)
+{
+  return do_rightdiv_sm_dm<SparseComplexMatrix> (a, b);
+}
+
+// Funny element by element division operations.
+//
+//       op2 \ op1:   s   cs
+//            +--   +---+----+
+//   matrix         | 1 |  3 |
+//                  +---+----+
+//   complex_matrix | 2 |  4 |
+//                  +---+----+
+
+Matrix
+x_el_div (double a, const SparseMatrix& b)
+{
+  octave_idx_type nr = b.rows ();
+  octave_idx_type nc = b.cols ();
+
+  Matrix result;
+  if (a == 0.)
+    result = Matrix (nr, nc, octave_NaN);
+  else if (a > 0.)
+    result = Matrix (nr, nc, octave_Inf);
+  else
+    result = Matrix (nr, nc, -octave_Inf);
+
+
+  for (octave_idx_type j = 0; j < nc; j++)
+    for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++)
+      {
+        octave_quit ();
+        result.elem (b.ridx (i), j) = a / b.data (i);
+      }
+
+  return result;
+}
+
+ComplexMatrix
+x_el_div (double a, const SparseComplexMatrix& b)
+{
+  octave_idx_type nr = b.rows ();
+  octave_idx_type nc = b.cols ();
+
+  ComplexMatrix  result (nr, nc, Complex (octave_NaN, octave_NaN));
+
+  for (octave_idx_type j = 0; j < nc; j++)
+    for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++)
+      {
+        octave_quit ();
+        result.elem (b.ridx (i), j) = a / b.data (i);
+      }
+
+  return result;
+}
+
+ComplexMatrix
+x_el_div (const Complex a, const SparseMatrix& b)
+{
+  octave_idx_type nr = b.rows ();
+  octave_idx_type nc = b.cols ();
+
+  ComplexMatrix result (nr, nc, (a / 0.0));
+
+  for (octave_idx_type j = 0; j < nc; j++)
+    for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++)
+      {
+        octave_quit ();
+        result.elem (b.ridx (i), j) = a / b.data (i);
+      }
+
+  return result;
+}
+
+ComplexMatrix
+x_el_div (const Complex a, const SparseComplexMatrix& b)
+{
+  octave_idx_type nr = b.rows ();
+  octave_idx_type nc = b.cols ();
+
+  ComplexMatrix result (nr, nc, (a / 0.0));
+
+  for (octave_idx_type j = 0; j < nc; j++)
+    for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++)
+      {
+        octave_quit ();
+        result.elem (b.ridx (i), j) = a / b.data (i);
+      }
+
+  return result;
+}
+
+// Left division functions.  X \ Y = inv (X) * Y
+//
+//               Y  \  X :   sm  scm  dm  dcm
+//                   +--   +---+----+
+//   matrix                | 1 |  5 |
+//                         +---+----+
+//   complex_matrix        | 2 |  6 |
+//                         +---+----+----+----+
+//   sparse matrix         | 3 |  7 |  9 | 11 |
+//                         +---+----+----+----+
+//   sparse complex_matrix | 4 |  8 | 10 | 12 |
+//                         +---+----+----+----+
+
+// -*- 1 -*-
+Matrix
+xleftdiv (const SparseMatrix& a, const Matrix& b, MatrixType &typ)
+{
+  if (! mx_leftdiv_conform (a, b))
+    return Matrix ();
+
+  octave_idx_type info;
+  double rcond = 0.0;
+  return a.solve (typ, b, info, rcond, solve_singularity_warning);
+}
+
+// -*- 2 -*-
+ComplexMatrix
+xleftdiv (const SparseMatrix& a, const ComplexMatrix& b, MatrixType &typ)
+{
+  if (! mx_leftdiv_conform (a, b))
+    return ComplexMatrix ();
+
+  octave_idx_type info;
+  double rcond = 0.0;
+  return a.solve (typ, b, info, rcond, solve_singularity_warning);
+}
+
+// -*- 3 -*-
+SparseMatrix
+xleftdiv (const SparseMatrix& a, const SparseMatrix& b, MatrixType &typ)
+{
+  if (! mx_leftdiv_conform (a, b))
+    return SparseMatrix ();
+
+  octave_idx_type info;
+  double rcond = 0.0;
+  return a.solve (typ, b, info, rcond, solve_singularity_warning);
+}
+
+// -*- 4 -*-
+SparseComplexMatrix
+xleftdiv (const SparseMatrix& a, const SparseComplexMatrix& b, MatrixType &typ)
+{
+  if (! mx_leftdiv_conform (a, b))
+    return SparseComplexMatrix ();
+
+  octave_idx_type info;
+  double rcond = 0.0;
+  return a.solve (typ, b, info, rcond, solve_singularity_warning);
+}
+
+// -*- 5 -*-
+ComplexMatrix
+xleftdiv (const SparseComplexMatrix& a, const Matrix& b, MatrixType &typ)
+{
+  if (! mx_leftdiv_conform (a, b))
+    return ComplexMatrix ();
+
+  octave_idx_type info;
+  double rcond = 0.0;
+  return a.solve (typ, b, info, rcond, solve_singularity_warning);
+}
+
+// -*- 6 -*-
+ComplexMatrix
+xleftdiv (const SparseComplexMatrix& a, const ComplexMatrix& b, MatrixType &typ)
+{
+  if (! mx_leftdiv_conform (a, b))
+    return ComplexMatrix ();
+
+  octave_idx_type info;
+  double rcond = 0.0;
+  return a.solve (typ, b, info, rcond, solve_singularity_warning);
+}
+
+// -*- 7 -*-
+SparseComplexMatrix
+xleftdiv (const SparseComplexMatrix& a, const SparseMatrix& b, MatrixType &typ)
+{
+  if (! mx_leftdiv_conform (a, b))
+    return SparseComplexMatrix ();
+
+  octave_idx_type info;
+  double rcond = 0.0;
+  return a.solve (typ, b, info, rcond, solve_singularity_warning);
+}
+
+// -*- 8 -*-
+SparseComplexMatrix
+xleftdiv (const SparseComplexMatrix& a, const SparseComplexMatrix& b,
+          MatrixType &typ)
+{
+  if (! mx_leftdiv_conform (a, b))
+    return SparseComplexMatrix ();
+
+  octave_idx_type info;
+  double rcond = 0.0;
+  return a.solve (typ, b, info, rcond, solve_singularity_warning);
+}
+
+template <typename RT, typename DM, typename SM>
+RT do_leftdiv_dm_sm (const DM& d, const SM& a)
+{
+  const octave_idx_type a_nr = a.rows ();
+  const octave_idx_type a_nc = a.cols ();
+
+  const octave_idx_type d_nc = d.cols ();
+
+  using std::min;
+  const octave_idx_type nr = min (d_nc, a_nr);
+
+  if ( ! mx_leftdiv_conform (d, a))
+    return RT ();
+
+  const octave_idx_type nz = a.nnz ();
+  RT r (nr, a_nc, nz);
+
+  typedef typename DM::element_type DM_elt_type;
+  const DM_elt_type zero = DM_elt_type ();
+
+  octave_idx_type k_result = 0;
+  for (octave_idx_type j = 0; j < a_nc; ++j)
+    {
+      octave_quit ();
+      const octave_idx_type colend = a.cidx (j+1);
+      r.xcidx (j) = k_result;
+      for (octave_idx_type k = a.cidx (j); k < colend; ++k)
+        {
+          const octave_idx_type i = a.ridx (k);
+          if (i < nr)
+            {
+              const DM_elt_type s = d.dgelem (i);
+              if (s != zero)
+                {
+                  r.xdata (k_result) = a.data (k) / s;
+                  r.xridx (k_result) = i;
+                  ++k_result;
+                }
+            }
+        }
+    }
+  r.xcidx (a_nc) = k_result;
+
+  r.maybe_compress (true);
+  return r;
+}
+
+// -*- 9 -*-
+SparseMatrix
+xleftdiv (const DiagMatrix& d, const SparseMatrix& a,  MatrixType&)
+{
+  return do_leftdiv_dm_sm<SparseMatrix> (d, a);
+}
+
+// -*- 10 -*-
+SparseComplexMatrix
+xleftdiv (const DiagMatrix& d, const SparseComplexMatrix& a,  MatrixType&)
+{
+  return do_leftdiv_dm_sm<SparseComplexMatrix> (d, a);
+}
+
+// -*- 11 -*-
+SparseComplexMatrix
+xleftdiv (const ComplexDiagMatrix& d, const SparseMatrix& a,  MatrixType&)
+{
+  return do_leftdiv_dm_sm<SparseComplexMatrix> (d, a);
+}
+
+// -*- 12 -*-
+SparseComplexMatrix
+xleftdiv (const ComplexDiagMatrix& d, const SparseComplexMatrix& a,  MatrixType&)
+{
+  return do_leftdiv_dm_sm<SparseComplexMatrix> (d, a);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/sparse-xdiv.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,93 @@
+/*
+
+Copyright (C) 2004-2012 David Bateman
+Copyright (C) 1998-2004 Andy Adler
+
+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/>.
+
+*/
+
+#if !defined (octave_sparse_xdiv_h)
+#define octave_sparse_xdiv_h 1
+
+#include "oct-cmplx.h"
+#include "MatrixType.h"
+
+class DiagMatrix;
+class ComplexDiagMatrix;
+class SparseMatrix;
+class SparseComplexMatrix;
+
+extern Matrix xdiv (const Matrix& a, const SparseMatrix& b, MatrixType &typ);
+extern ComplexMatrix xdiv (const Matrix& a, const SparseComplexMatrix& b,
+                           MatrixType &typ);
+extern ComplexMatrix xdiv (const ComplexMatrix& a, const SparseMatrix& b,
+                           MatrixType &typ);
+extern ComplexMatrix xdiv (const ComplexMatrix& a,
+                           const SparseComplexMatrix& b, MatrixType &typ);
+
+extern SparseMatrix xdiv (const SparseMatrix& a, const SparseMatrix& b,
+                          MatrixType &typ);
+extern SparseComplexMatrix xdiv (const SparseMatrix& a,
+                                 const SparseComplexMatrix& b, MatrixType &typ);
+extern SparseComplexMatrix xdiv (const SparseComplexMatrix& a,
+                                 const SparseMatrix& b, MatrixType &typ);
+extern SparseComplexMatrix xdiv (const SparseComplexMatrix& a,
+                                 const SparseComplexMatrix& b, MatrixType &typ);
+
+extern SparseMatrix xdiv (const SparseMatrix& a,
+                          const DiagMatrix& b, MatrixType &typ);
+extern SparseComplexMatrix xdiv (const SparseMatrix& a,
+                                 const ComplexDiagMatrix& b, MatrixType &typ);
+extern SparseComplexMatrix xdiv (const SparseComplexMatrix& a,
+                                 const DiagMatrix& b, MatrixType &typ);
+extern SparseComplexMatrix xdiv (const SparseComplexMatrix& a,
+                                 const ComplexDiagMatrix& b, MatrixType &typ);
+
+extern Matrix x_el_div (double a, const SparseMatrix& b);
+extern ComplexMatrix x_el_div (double a, const SparseComplexMatrix& b);
+extern ComplexMatrix x_el_div (const Complex a, const SparseMatrix& b);
+extern ComplexMatrix x_el_div (const Complex a,
+                               const SparseComplexMatrix& b);
+
+extern Matrix xleftdiv (const SparseMatrix& a, const Matrix& b,
+                        MatrixType& typ);
+extern ComplexMatrix xleftdiv (const SparseMatrix& a, const ComplexMatrix& b,
+                               MatrixType &typ);
+extern ComplexMatrix xleftdiv (const SparseComplexMatrix& a, const Matrix& b,
+                               MatrixType &typ);
+extern ComplexMatrix xleftdiv (const SparseComplexMatrix& a,
+                               const ComplexMatrix& b, MatrixType &typ);
+
+extern SparseMatrix xleftdiv (const SparseMatrix& a, const SparseMatrix& b,
+                              MatrixType &typ);
+extern SparseComplexMatrix xleftdiv (const SparseMatrix& a,
+                                     const SparseComplexMatrix& b, MatrixType &typ);
+extern SparseComplexMatrix xleftdiv (const SparseComplexMatrix& a,
+                                     const SparseMatrix& b, MatrixType &typ);
+extern SparseComplexMatrix xleftdiv (const SparseComplexMatrix& a,
+                                     const SparseComplexMatrix& b, MatrixType &typ);
+
+extern SparseMatrix xleftdiv (const DiagMatrix&, const SparseMatrix&, MatrixType&);
+extern SparseComplexMatrix xleftdiv (const ComplexDiagMatrix&, const SparseMatrix&,
+                                     MatrixType&);
+extern SparseComplexMatrix xleftdiv (const DiagMatrix&, const SparseComplexMatrix&,
+                                     MatrixType&);
+extern SparseComplexMatrix xleftdiv (const ComplexDiagMatrix&, const SparseComplexMatrix&,
+                                     MatrixType&);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/sparse-xpow.cc	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,730 @@
+/*
+
+Copyright (C) 2004-2012 David Bateman
+Copyright (C) 1998-2004 Andy Adler
+
+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/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <cassert>
+#include <climits>
+
+#include "Array-util.h"
+#include "oct-cmplx.h"
+#include "quit.h"
+
+#include "error.h"
+#include "oct-obj.h"
+#include "utils.h"
+
+#include "dSparse.h"
+#include "CSparse.h"
+#include "ov-re-sparse.h"
+#include "ov-cx-sparse.h"
+#include "sparse-xpow.h"
+
+static inline int
+xisint (double x)
+{
+  return (D_NINT (x) == x
+          && ((x >= 0 && x < INT_MAX)
+              || (x <= 0 && x > INT_MIN)));
+}
+
+
+// Safer pow functions. Only two make sense for sparse matrices, the
+// others should all promote to full matrices.
+
+octave_value
+xpow (const SparseMatrix& a, double b)
+{
+  octave_value retval;
+
+  octave_idx_type nr = a.rows ();
+  octave_idx_type nc = a.cols ();
+
+  if (nr == 0 || nc == 0 || nr != nc)
+    error ("for A^b, A must be a square matrix");
+  else
+    {
+      if (static_cast<int> (b) == b)
+        {
+          int btmp = static_cast<int> (b);
+          if (btmp == 0)
+            {
+              SparseMatrix tmp = SparseMatrix (nr, nr, nr);
+              for (octave_idx_type i = 0; i < nr; i++)
+                {
+                  tmp.data (i) = 1.0;
+                  tmp.ridx (i) = i;
+                }
+              for (octave_idx_type i = 0; i < nr + 1; i++)
+                tmp.cidx (i) = i;
+
+              retval = tmp;
+            }
+          else
+            {
+              SparseMatrix atmp;
+              if (btmp < 0)
+                {
+                  btmp = -btmp;
+
+                  octave_idx_type info;
+                  double rcond = 0.0;
+                  MatrixType mattyp (a);
+
+                  atmp = a.inverse (mattyp, info, rcond, 1);
+
+                  if (info == -1)
+                    warning ("inverse: matrix singular to machine\
+ precision, rcond = %g", rcond);
+                }
+              else
+                atmp = a;
+
+              SparseMatrix result (atmp);
+
+              btmp--;
+
+              while (btmp > 0)
+                {
+                  if (btmp & 1)
+                    result = result * atmp;
+
+                  btmp >>= 1;
+
+                  if (btmp > 0)
+                    atmp = atmp * atmp;
+                }
+
+              retval = result;
+            }
+        }
+      else
+        error ("use full(a) ^ full(b)");
+    }
+
+  return retval;
+}
+
+octave_value
+xpow (const SparseComplexMatrix& a, double b)
+{
+  octave_value retval;
+
+  octave_idx_type nr = a.rows ();
+  octave_idx_type nc = a.cols ();
+
+  if (nr == 0 || nc == 0 || nr != nc)
+    error ("for A^b, A must be a square matrix");
+  else
+    {
+      if (static_cast<int> (b) == b)
+        {
+          int btmp = static_cast<int> (b);
+          if (btmp == 0)
+            {
+              SparseMatrix tmp = SparseMatrix (nr, nr, nr);
+              for (octave_idx_type i = 0; i < nr; i++)
+                {
+                  tmp.data (i) = 1.0;
+                  tmp.ridx (i) = i;
+                }
+              for (octave_idx_type i = 0; i < nr + 1; i++)
+                tmp.cidx (i) = i;
+
+              retval = tmp;
+            }
+          else
+            {
+              SparseComplexMatrix atmp;
+              if (btmp < 0)
+                {
+                  btmp = -btmp;
+
+                  octave_idx_type info;
+                  double rcond = 0.0;
+                  MatrixType mattyp (a);
+
+                  atmp = a.inverse (mattyp, info, rcond, 1);
+
+                  if (info == -1)
+                    warning ("inverse: matrix singular to machine\
+ precision, rcond = %g", rcond);
+                }
+              else
+                atmp = a;
+
+              SparseComplexMatrix result (atmp);
+
+              btmp--;
+
+              while (btmp > 0)
+                {
+                  if (btmp & 1)
+                    result = result * atmp;
+
+                  btmp >>= 1;
+
+                  if (btmp > 0)
+                    atmp = atmp * atmp;
+                }
+
+              retval = result;
+            }
+        }
+      else
+        error ("use full(a) ^ full(b)");
+    }
+
+  return retval;
+}
+
+// Safer pow functions that work elementwise for matrices.
+//
+//       op2 \ op1:   s   m   cs   cm
+//            +--   +---+---+----+----+
+//   scalar   |     | * | 3 |  * |  9 |
+//                  +---+---+----+----+
+//   matrix         | 1 | 4 |  7 | 10 |
+//                  +---+---+----+----+
+//   complex_scalar | * | 5 |  * | 11 |
+//                  +---+---+----+----+
+//   complex_matrix | 2 | 6 |  8 | 12 |
+//                  +---+---+----+----+
+//
+//   * -> not needed.
+
+// FIXME -- these functions need to be fixed so that things
+// like
+//
+//   a = -1; b = [ 0, 0.5, 1 ]; r = a .^ b
+//
+// and
+//
+//   a = -1; b = [ 0, 0.5, 1 ]; for i = 1:3, r(i) = a .^ b(i), end
+//
+// produce identical results.  Also, it would be nice if -1^0.5
+// produced a pure imaginary result instead of a complex number with a
+// small real part.  But perhaps that's really a problem with the math
+// library...
+
+// -*- 1 -*-
+octave_value
+elem_xpow (double a, const SparseMatrix& b)
+{
+  octave_value retval;
+
+  octave_idx_type nr = b.rows ();
+  octave_idx_type nc = b.cols ();
+
+  double d1, d2;
+
+  if (a < 0.0 && ! b.all_integers (d1, d2))
+    {
+      Complex atmp (a);
+      ComplexMatrix result (nr, nc);
+
+      for (octave_idx_type j = 0; j < nc; j++)
+        {
+          for (octave_idx_type i = 0; i < nr; i++)
+            {
+              octave_quit ();
+              result(i, j) = std::pow (atmp, b(i,j));
+            }
+        }
+
+      retval = result;
+    }
+  else
+    {
+      Matrix result (nr, nc);
+
+      for (octave_idx_type j = 0; j < nc; j++)
+        {
+          for (octave_idx_type i = 0; i < nr; i++)
+            {
+              octave_quit ();
+              result(i, j) = std::pow (a, b(i,j));
+            }
+        }
+
+      retval = result;
+    }
+
+  return retval;
+}
+
+// -*- 2 -*-
+octave_value
+elem_xpow (double a, const SparseComplexMatrix& b)
+{
+  octave_idx_type nr = b.rows ();
+  octave_idx_type nc = b.cols ();
+
+  Complex atmp (a);
+  ComplexMatrix result (nr, nc);
+
+  for (octave_idx_type j = 0; j < nc; j++)
+    {
+      for (octave_idx_type i = 0; i < nr; i++)
+        {
+          octave_quit ();
+          result(i, j) = std::pow (atmp, b(i,j));
+        }
+    }
+
+  return result;
+}
+
+// -*- 3 -*-
+octave_value
+elem_xpow (const SparseMatrix& a, double b)
+{
+  // FIXME What should a .^ 0 give?? Matlab gives a
+  // sparse matrix with same structure as a, which is strictly
+  // incorrect. Keep compatiability.
+
+  octave_value retval;
+
+  octave_idx_type nz = a.nnz ();
+
+  if (b <= 0.0)
+    {
+      octave_idx_type nr = a.rows ();
+      octave_idx_type nc = a.cols ();
+
+      if (static_cast<int> (b) != b && a.any_element_is_negative ())
+        {
+          ComplexMatrix result (nr, nc, Complex (std::pow (0.0, b)));
+
+          // FIXME -- avoid apparent GNU libm bug by
+          // converting A and B to complex instead of just A.
+          Complex btmp (b);
+
+          for (octave_idx_type j = 0; j < nc; j++)
+            for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)
+              {
+                octave_quit ();
+
+                Complex atmp (a.data (i));
+
+                result(a.ridx (i), j) = std::pow (atmp, btmp);
+              }
+
+          retval = octave_value (result);
+        }
+      else
+        {
+          Matrix result (nr, nc, (std::pow (0.0, b)));
+
+          for (octave_idx_type j = 0; j < nc; j++)
+            for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)
+              {
+                octave_quit ();
+                result(a.ridx (i), j) = std::pow (a.data (i), b);
+              }
+
+          retval = octave_value (result);
+        }
+    }
+  else if (static_cast<int> (b) != b && a.any_element_is_negative ())
+    {
+      SparseComplexMatrix result (a);
+
+      for (octave_idx_type i = 0; i < nz; i++)
+        {
+          octave_quit ();
+
+          // FIXME -- avoid apparent GNU libm bug by
+          // converting A and B to complex instead of just A.
+
+          Complex atmp (a.data (i));
+          Complex btmp (b);
+
+          result.data (i) = std::pow (atmp, btmp);
+        }
+
+      result.maybe_compress (true);
+
+      retval = result;
+    }
+  else
+    {
+      SparseMatrix result (a);
+
+      for (octave_idx_type i = 0; i < nz; i++)
+        {
+          octave_quit ();
+          result.data (i) = std::pow (a.data (i), b);
+        }
+
+      result.maybe_compress (true);
+
+      retval = result;
+    }
+
+  return retval;
+}
+
+// -*- 4 -*-
+octave_value
+elem_xpow (const SparseMatrix& a, const SparseMatrix& b)
+{
+  octave_value retval;
+
+  octave_idx_type nr = a.rows ();
+  octave_idx_type nc = a.cols ();
+
+  octave_idx_type b_nr = b.rows ();
+  octave_idx_type b_nc = b.cols ();
+
+  if (nr != b_nr || nc != b_nc)
+    {
+      gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc);
+      return octave_value ();
+    }
+
+  int convert_to_complex = 0;
+  for (octave_idx_type j = 0; j < nc; j++)
+    for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)
+      {
+        if (a.data(i) < 0.0)
+          {
+            double btmp = b (a.ridx (i), j);
+            if (static_cast<int> (btmp) != btmp)
+              {
+                convert_to_complex = 1;
+                goto done;
+              }
+          }
+      }
+
+done:
+
+  // This is a dumb operator for sparse matrices anyway, and there is
+  // no sensible way to handle the 0.^0 versus the 0.^x cases. Therefore
+  // allocate a full matrix filled for the 0.^0 case and shrink it later
+  // as needed
+
+  if (convert_to_complex)
+    {
+      SparseComplexMatrix complex_result (nr, nc, Complex (1.0, 0.0));
+
+      for (octave_idx_type j = 0; j < nc; j++)
+        {
+          for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)
+            {
+              octave_quit ();
+              complex_result.xelem (a.ridx (i), j) =
+                std::pow (Complex (a.data (i)), Complex (b(a.ridx (i), j)));
+            }
+        }
+      complex_result.maybe_compress (true);
+      retval = complex_result;
+    }
+  else
+    {
+      SparseMatrix result (nr, nc, 1.0);
+
+      for (octave_idx_type j = 0; j < nc; j++)
+        {
+          for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)
+            {
+              octave_quit ();
+              result.xelem (a.ridx (i), j) = std::pow (a.data (i),
+                                                       b(a.ridx (i), j));
+            }
+        }
+      result.maybe_compress (true);
+      retval = result;
+    }
+
+  return retval;
+}
+
+// -*- 5 -*-
+octave_value
+elem_xpow (const SparseMatrix& a, const Complex& b)
+{
+  octave_value retval;
+
+  if (b == 0.0)
+    // Can this case ever happen, due to automatic retyping with maybe_mutate?
+    retval = octave_value (NDArray (a.dims (), 1));
+  else
+    {
+      octave_idx_type nz = a.nnz ();
+      SparseComplexMatrix result (a);
+
+      for (octave_idx_type i = 0; i < nz; i++)
+        {
+          octave_quit ();
+          result.data (i) = std::pow (Complex (a.data (i)), b);
+        }
+
+      result.maybe_compress (true);
+
+      retval = result;
+    }
+
+  return retval;
+}
+
+// -*- 6 -*-
+octave_value
+elem_xpow (const SparseMatrix& a, const SparseComplexMatrix& b)
+{
+  octave_idx_type nr = a.rows ();
+  octave_idx_type nc = a.cols ();
+
+  octave_idx_type b_nr = b.rows ();
+  octave_idx_type b_nc = b.cols ();
+
+  if (nr != b_nr || nc != b_nc)
+    {
+      gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc);
+      return octave_value ();
+    }
+
+  SparseComplexMatrix result (nr, nc, Complex (1.0, 0.0));
+  for (octave_idx_type j = 0; j < nc; j++)
+    {
+      for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)
+        {
+          octave_quit ();
+          result.xelem (a.ridx(i), j) = std::pow (a.data (i), b(a.ridx (i), j));
+        }
+    }
+
+  result.maybe_compress (true);
+
+  return result;
+}
+
+// -*- 7 -*-
+octave_value
+elem_xpow (const Complex& a, const SparseMatrix& b)
+{
+  octave_idx_type nr = b.rows ();
+  octave_idx_type nc = b.cols ();
+
+  ComplexMatrix result (nr, nc);
+
+  for (octave_idx_type j = 0; j < nc; j++)
+    {
+      for (octave_idx_type i = 0; i < nr; i++)
+        {
+          octave_quit ();
+          double btmp = b (i, j);
+          if (xisint (btmp))
+            result (i, j) = std::pow (a, static_cast<int> (btmp));
+          else
+            result (i, j) = std::pow (a, btmp);
+        }
+    }
+
+  return result;
+}
+
+// -*- 8 -*-
+octave_value
+elem_xpow (const Complex& a, const SparseComplexMatrix& b)
+{
+  octave_idx_type nr = b.rows ();
+  octave_idx_type nc = b.cols ();
+
+  ComplexMatrix result (nr, nc);
+  for (octave_idx_type j = 0; j < nc; j++)
+    for (octave_idx_type i = 0; i < nr; i++)
+      {
+        octave_quit ();
+        result (i, j) = std::pow (a, b (i, j));
+      }
+
+  return result;
+}
+
+// -*- 9 -*-
+octave_value
+elem_xpow (const SparseComplexMatrix& a, double b)
+{
+  octave_value retval;
+
+  if (b <= 0)
+    {
+      octave_idx_type nr = a.rows ();
+      octave_idx_type nc = a.cols ();
+
+      ComplexMatrix result (nr, nc, Complex (std::pow (0.0, b)));
+
+      if (xisint (b))
+        {
+          for (octave_idx_type j = 0; j < nc; j++)
+            for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)
+              {
+                octave_quit ();
+                result (a.ridx (i), j) =
+                  std::pow (a.data (i), static_cast<int> (b));
+              }
+        }
+      else
+        {
+          for (octave_idx_type j = 0; j < nc; j++)
+            for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)
+              {
+                octave_quit ();
+                result (a.ridx (i), j) = std::pow (a.data (i), b);
+              }
+        }
+
+      retval = result;
+    }
+  else
+    {
+      octave_idx_type nz = a.nnz ();
+
+      SparseComplexMatrix result (a);
+
+      if (xisint (b))
+        {
+          for (octave_idx_type i = 0; i < nz; i++)
+            {
+              octave_quit ();
+              result.data (i) = std::pow (a.data (i), static_cast<int> (b));
+            }
+        }
+      else
+        {
+          for (octave_idx_type i = 0; i < nz; i++)
+            {
+              octave_quit ();
+              result.data (i) = std::pow (a.data (i), b);
+            }
+        }
+
+      result.maybe_compress (true);
+
+      retval = result;
+    }
+
+  return retval;
+}
+
+// -*- 10 -*-
+octave_value
+elem_xpow (const SparseComplexMatrix& a, const SparseMatrix& b)
+{
+  octave_idx_type nr = a.rows ();
+  octave_idx_type nc = a.cols ();
+
+  octave_idx_type b_nr = b.rows ();
+  octave_idx_type b_nc = b.cols ();
+
+  if (nr != b_nr || nc != b_nc)
+    {
+      gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc);
+      return octave_value ();
+    }
+
+  SparseComplexMatrix result (nr, nc, Complex (1.0, 0.0));
+  for (octave_idx_type j = 0; j < nc; j++)
+    {
+      for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)
+        {
+          octave_quit ();
+          double btmp = b(a.ridx (i), j);
+          Complex tmp;
+
+          if (xisint (btmp))
+            result.xelem (a.ridx (i), j) = std::pow (a.data (i),
+                                              static_cast<int> (btmp));
+          else
+            result.xelem (a.ridx (i), j) = std::pow (a.data (i), btmp);
+        }
+    }
+
+  result.maybe_compress (true);
+
+  return result;
+}
+
+// -*- 11 -*-
+octave_value
+elem_xpow (const SparseComplexMatrix& a, const Complex& b)
+{
+  octave_value retval;
+
+  if (b == 0.0)
+    // Can this case ever happen, due to automatic retyping with maybe_mutate?
+    retval = octave_value (NDArray (a.dims (), 1));
+  else
+    {
+
+      octave_idx_type nz = a.nnz ();
+
+      SparseComplexMatrix result (a);
+
+      for (octave_idx_type i = 0; i < nz; i++)
+        {
+          octave_quit ();
+          result.data (i) = std::pow (a.data (i), b);
+        }
+
+      result.maybe_compress (true);
+
+      retval = result;
+    }
+
+  return retval;
+}
+
+// -*- 12 -*-
+octave_value
+elem_xpow (const SparseComplexMatrix& a, const SparseComplexMatrix& b)
+{
+  octave_idx_type nr = a.rows ();
+  octave_idx_type nc = a.cols ();
+
+  octave_idx_type b_nr = b.rows ();
+  octave_idx_type b_nc = b.cols ();
+
+  if (nr != b_nr || nc != b_nc)
+    {
+      gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc);
+      return octave_value ();
+    }
+
+  SparseComplexMatrix result (nr, nc, Complex (1.0, 0.0));
+  for (octave_idx_type j = 0; j < nc; j++)
+    {
+      for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)
+        {
+          octave_quit ();
+          result.xelem (a.ridx (i), j) = std::pow (a.data (i), b(a.ridx (i), j));
+        }
+    }
+  result.maybe_compress (true);
+
+  return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/sparse-xpow.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,57 @@
+/*
+
+Copyright (C) 2004-2012 David Bateman
+Copyright (C) 1998-2004 Andy Adler
+
+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/>.
+
+*/
+
+#if !defined (octave_sparse_xpow_h)
+#define octave_sparse_xpow_h 1
+
+#include "oct-cmplx.h"
+
+class SparseMatrix;
+class SparseComplexMatrix;
+class octave_value;
+
+extern octave_value xpow (const SparseMatrix& a, double b);
+extern octave_value xpow (const SparseComplexMatrix& a, double b);
+
+extern octave_value elem_xpow (double a, const SparseMatrix& b);
+extern octave_value elem_xpow (double a, const SparseComplexMatrix& b);
+
+extern octave_value elem_xpow (const SparseMatrix& a, double b);
+extern octave_value elem_xpow (const SparseMatrix& a, const SparseMatrix& b);
+extern octave_value elem_xpow (const SparseMatrix& a, const Complex& b);
+extern octave_value elem_xpow (const SparseMatrix& a,
+                               const SparseComplexMatrix& b);
+
+extern octave_value elem_xpow (const Complex& a, const SparseMatrix& b);
+extern octave_value elem_xpow (const Complex& a,
+                               const SparseComplexMatrix& b);
+
+extern octave_value elem_xpow (const SparseComplexMatrix& a, double b);
+extern octave_value elem_xpow (const SparseComplexMatrix& a,
+                               const SparseMatrix& b);
+extern octave_value elem_xpow (const SparseComplexMatrix& a,
+                               const Complex& b);
+extern octave_value elem_xpow (const SparseComplexMatrix& a,
+                               const SparseComplexMatrix& b);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/txt-eng-ft.cc	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,669 @@
+/*
+
+Copyright (C) 2009-2012 Michael Goffioul
+
+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/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#if defined (HAVE_FREETYPE)
+
+#if defined (HAVE_FONTCONFIG)
+#include <fontconfig/fontconfig.h>
+#endif
+
+#include <iostream>
+
+#include "singleton-cleanup.h"
+
+#include "error.h"
+#include "pr-output.h"
+#include "txt-eng-ft.h"
+
+// FIXME -- maybe issue at most one warning per glyph/font/size/weight
+// combination.
+
+static void
+gripe_missing_glyph (char c)
+{
+  warning_with_id ("Octave:missing-glyph",
+                   "ft_render: skipping missing glyph for character `%c'",
+                   c);
+}
+
+static void
+gripe_glyph_render (char c)
+{
+  warning_with_id ("Octave:glyph-render",
+                   "ft_render: unable to render glyph for character `%c'",
+                   c);
+}
+
+#ifdef _MSC_VER
+// This is just a trick to avoid multiply symbols definition.
+// PermMatrix.h contains a dllexport'ed Array<octave_idx_type>
+// that will make MSVC not to generate new instantiation and
+// use the imported one.
+#include "PermMatrix.h"
+#endif
+
+class
+ft_manager
+{
+public:
+  static bool instance_ok (void)
+    {
+      bool retval = true;
+
+      if (! instance)
+        {
+          instance = new ft_manager ();
+
+          if (instance)
+            singleton_cleanup_list::add (cleanup_instance);
+        }
+
+      if (! instance)
+        {
+          ::error ("unable to create ft_manager!");
+
+          retval = false;
+        }
+
+      return retval;
+    }
+
+  static void cleanup_instance (void) { delete instance; instance = 0; }
+
+  static FT_Face get_font (const std::string& name, const std::string& weight,
+                           const std::string& angle, double size)
+    { return (instance_ok ()
+              ? instance->do_get_font (name, weight, angle, size)
+              : 0); }
+
+private:
+
+  static ft_manager *instance;
+
+private:
+
+  // No copying!
+
+  ft_manager (const ft_manager&);
+
+  ft_manager& operator = (const ft_manager&);
+
+  ft_manager (void)
+    : library (), freetype_initialized (false), fontconfig_initialized (false)
+    {
+      if (FT_Init_FreeType (&library))
+        ::error ("unable to initialize freetype library");
+      else
+        freetype_initialized = true;
+
+#if defined (HAVE_FONTCONFIG)
+      if (! FcInit ())
+        ::error ("unable to initialize fontconfig library");
+      else
+        fontconfig_initialized = true;
+#endif
+    }
+
+  ~ft_manager (void)
+    {
+      if (freetype_initialized)
+        FT_Done_FreeType (library);
+
+#if defined (HAVE_FONTCONFIG)
+      // FIXME -- Skip the call to FcFini because it can trigger the
+      // assertion
+      //
+      //   octave: fccache.c:507: FcCacheFini: Assertion `fcCacheChains[i] == ((void *)0)' failed.
+      //
+      // if (fontconfig_initialized)
+      //   FcFini ();
+#endif
+    }
+
+
+  FT_Face do_get_font (const std::string& name, const std::string& weight,
+                       const std::string& angle, double size)
+    {
+      FT_Face retval = 0;
+
+      std::string file;
+
+#if defined (HAVE_FONTCONFIG)
+      if (fontconfig_initialized)
+        {
+          int fc_weight, fc_angle;
+
+          if (weight == "bold")
+            fc_weight = FC_WEIGHT_BOLD;
+          else if (weight == "light")
+            fc_weight = FC_WEIGHT_LIGHT;
+          else if (weight == "demi")
+            fc_weight = FC_WEIGHT_DEMIBOLD;
+          else
+            fc_weight = FC_WEIGHT_NORMAL;
+
+          if (angle == "italic")
+            fc_angle = FC_SLANT_ITALIC;
+          else if (angle == "oblique")
+            fc_angle = FC_SLANT_OBLIQUE;
+          else
+            fc_angle = FC_SLANT_ROMAN;
+
+          FcPattern *pat = FcPatternCreate ();
+
+          FcPatternAddString (pat, FC_FAMILY,
+                              (reinterpret_cast<const FcChar8*>
+                               (name == "*" ? "sans" : name.c_str ())));
+
+          FcPatternAddInteger (pat, FC_WEIGHT, fc_weight);
+          FcPatternAddInteger (pat, FC_SLANT, fc_angle);
+          FcPatternAddDouble (pat, FC_PIXEL_SIZE, size);
+
+          if (FcConfigSubstitute (0, pat, FcMatchPattern))
+            {
+              FcResult res;
+              FcPattern *match;
+
+              FcDefaultSubstitute (pat);
+              match = FcFontMatch (0, pat, &res);
+
+              // FIXME -- originally, this test also required that
+              // res != FcResultNoMatch.  Is that really needed?
+              if (match)
+                {
+                  unsigned char *tmp;
+
+                  FcPatternGetString (match, FC_FILE, 0, &tmp);
+                  file = reinterpret_cast<char*> (tmp);
+                }
+              else
+                ::warning ("could not match any font: %s-%s-%s-%g",
+                         name.c_str (), weight.c_str (), angle.c_str (),
+                         size);
+
+              if (match)
+                FcPatternDestroy (match);
+            }
+
+          FcPatternDestroy (pat);
+        }
+#endif
+
+      if (file.empty ())
+        {
+#ifdef __WIN32__
+          file = "C:/WINDOWS/Fonts/verdana.ttf";
+#else
+          // FIXME: find a "standard" font for UNIX platforms
+#endif
+        }
+
+      if (! file.empty () && FT_New_Face (library, file.c_str (), 0, &retval))
+        ::warning ("ft_manager: unable to load font: %s", file.c_str ());
+
+      return retval;
+    }
+
+private:
+  FT_Library library;
+  bool freetype_initialized;
+  bool fontconfig_initialized;
+};
+
+ft_manager* ft_manager::instance = 0;
+
+// ---------------------------------------------------------------------------
+
+ft_render::ft_render (void)
+    : text_processor (), face (0), bbox (1, 4, 0.0),
+      xoffset (0), yoffset (0), multiline_halign (0),
+      multiline_align_xoffsets (), mode (MODE_BBOX),
+      red (0), green (0), blue (0)
+{
+}
+
+ft_render::~ft_render (void)
+{
+  if (face)
+    FT_Done_Face (face);
+}
+
+void
+ft_render::set_font (const std::string& name, const std::string& weight,
+                     const std::string& angle, double size)
+{
+  if (face)
+    FT_Done_Face (face);
+
+  // FIXME: take "fontunits" into account
+  face = ft_manager::get_font (name, weight, angle, size);
+
+  if (face)
+    {
+      if (FT_Set_Char_Size (face, 0, size*64, 0, 0))
+        ::warning ("ft_render: unable to set font size to %d", size);
+    }
+  else
+    ::warning ("ft_render: unable to load appropriate font");
+}
+
+void
+ft_render::set_mode (int m)
+{
+  mode = m;
+
+  switch (mode)
+    {
+    case MODE_BBOX:
+      xoffset = yoffset = 0;
+      bbox = Matrix (1, 4, 0.0);
+      break;
+    case MODE_RENDER:
+      if (bbox.numel () != 4)
+        {
+          ::warning ("ft_render: invalid bounding box, cannot render");
+
+          xoffset = yoffset = 0;
+          pixels = uint8NDArray ();
+        }
+      else
+        {
+          pixels = uint8NDArray (dim_vector (4, bbox(2), bbox(3)),
+                                 static_cast<uint8_t> (0));
+          xoffset = 0;
+          yoffset = -bbox(1)-1;
+        }
+      break;
+    default:
+      ::error ("ft_render: invalid mode `%d'", mode);
+      break;
+    }
+}
+
+void
+ft_render::visit (text_element_string& e)
+{
+  if (face)
+    {
+      int line_index = 0;
+      FT_UInt box_line_width = 0;
+      std::string str = e.string_value ();
+      FT_UInt glyph_index, previous = 0;
+
+      if (mode == MODE_BBOX)
+        multiline_align_xoffsets.clear ();
+      else if (mode == MODE_RENDER)
+        xoffset += multiline_align_xoffsets[line_index];
+
+      for (size_t i = 0; i < str.length (); i++)
+        {
+          glyph_index = FT_Get_Char_Index (face, str[i]);
+
+          if (str[i] != '\n'
+              && (! glyph_index
+              || FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT)))
+            gripe_missing_glyph (str[i]);
+          else
+            {
+              switch (mode)
+                {
+                case MODE_RENDER:
+                  if (str[i] == '\n')
+                    {
+                    glyph_index = FT_Get_Char_Index (face, ' ');
+                    if (!glyph_index || FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT))
+                      {
+                        gripe_missing_glyph (' ');
+                      }
+                    else
+                      {
+                        line_index++;
+                        xoffset = multiline_align_xoffsets[line_index];
+                        yoffset -= (face->size->metrics.height >> 6);
+                      }
+                    }
+                  else if (FT_Render_Glyph (face->glyph, FT_RENDER_MODE_NORMAL))
+                    {
+                      gripe_glyph_render (str[i]);
+                    }
+                  else
+                    {
+                      FT_Bitmap& bitmap = face->glyph->bitmap;
+                      int x0, y0;
+
+                      if (previous)
+                        {
+                          FT_Vector delta;
+
+                          FT_Get_Kerning (face, previous, glyph_index, FT_KERNING_DEFAULT, &delta);
+                          xoffset += (delta.x >> 6);
+                        }
+
+                      x0 = xoffset+face->glyph->bitmap_left;
+                      y0 = yoffset+face->glyph->bitmap_top;
+
+                      // 'w' seems to have a negative -1
+                      // face->glyph->bitmap_left, this is so we don't
+                      // index out of bound, and assumes we we allocated
+                      // the right amount of horizontal space in the bbox.
+                      if (x0 < 0)
+                        x0 = 0;
+
+                      for (int r = 0; r < bitmap.rows; r++)
+                        for (int c = 0; c < bitmap.width; c++)
+                          {
+                            unsigned char pix = bitmap.buffer[r*bitmap.width+c];
+                            if (x0+c < 0 || x0+c >= pixels.dim2 ()
+                                || y0-r < 0 || y0-r >= pixels.dim3 ())
+                              {
+                                //::error ("out-of-bound indexing!!");
+                              }
+                            else if (pixels(3, x0+c, y0-r).value () == 0)
+                              {
+                                pixels(0, x0+c, y0-r) = red;
+                                pixels(1, x0+c, y0-r) = green;
+                                pixels(2, x0+c, y0-r) = blue;
+                                pixels(3, x0+c, y0-r) = pix;
+                              }
+                          }
+
+                      xoffset += (face->glyph->advance.x >> 6);
+                    }
+                  break;
+
+                case MODE_BBOX:
+                  if (str[i] == '\n')
+                    {
+                      glyph_index = FT_Get_Char_Index (face, ' ');
+                      if (! glyph_index
+                          || FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT))
+                      {
+                        gripe_missing_glyph (' ');
+                      }
+                    else
+                      {
+                        multiline_align_xoffsets.push_back (box_line_width);
+                        // Reset the pixel width for this newline, so we don't
+                        // allocate a bounding box larger than the horizontal
+                        // width of the multi-line
+                        box_line_width = 0;
+                        bbox(1) -= (face->size->metrics.height >> 6);
+                      }
+                    }
+                  else
+                    {
+                    // width
+                    if (previous)
+                      {
+                        FT_Vector delta;
+
+                        FT_Get_Kerning (face, previous, glyph_index,
+                                        FT_KERNING_DEFAULT, &delta);
+
+                        box_line_width += (delta.x >> 6);
+                      }
+
+                    box_line_width += (face->glyph->advance.x >> 6);
+
+                    int asc, desc;
+
+                    if (false /*tight*/)
+                      {
+                        desc = face->glyph->metrics.horiBearingY - face->glyph->metrics.height;
+                        asc = face->glyph->metrics.horiBearingY;
+                      }
+                    else
+                      {
+                        asc = face->size->metrics.ascender;
+                        desc = face->size->metrics.descender;
+                      }
+
+                    asc = yoffset + (asc >> 6);
+                    desc = yoffset + (desc >> 6);
+
+                    if (desc < bbox(1))
+                      {
+                        bbox(3) += (bbox(1) - desc);
+                        bbox(1) = desc;
+                      }
+                    if (asc > (bbox(3)+bbox(1)))
+                      bbox(3) = asc-bbox(1);
+                    if (bbox(2) < box_line_width)
+                      bbox(2) = box_line_width;
+                  }
+                  break;
+                }
+                if (str[i] == '\n')
+                  previous = 0;
+                else
+                  previous = glyph_index;
+            }
+        }
+      if (mode == MODE_BBOX)
+        {
+          /* Push last the width associated with the last line */
+          multiline_align_xoffsets.push_back (box_line_width);
+
+          for (unsigned int i = 0; i < multiline_align_xoffsets.size (); i++)
+            {
+            /* Center align */
+            if (multiline_halign == 1)
+              multiline_align_xoffsets[i] = (bbox(2) - multiline_align_xoffsets[i])/2;
+            /* Right align */
+            else if (multiline_halign == 2)
+              multiline_align_xoffsets[i] = (bbox(2) - multiline_align_xoffsets[i]);
+            /* Left align */
+            else
+              multiline_align_xoffsets[i] = 0;
+            }
+        }
+    }
+}
+
+void
+ft_render::reset (void)
+{
+  set_mode (MODE_BBOX);
+  set_color (Matrix (1, 3, 0.0));
+}
+
+void
+ft_render::set_color (Matrix c)
+{
+  if (c.numel () == 3)
+    {
+      red = static_cast<uint8_t> (c(0)*255);
+      green = static_cast<uint8_t> (c(1)*255);
+      blue = static_cast<uint8_t> (c(2)*255);
+    }
+  else
+    ::warning ("ft_render::set_color: invalid color");
+}
+
+uint8NDArray
+ft_render::render (text_element* elt, Matrix& box, int rotation)
+{
+  set_mode (MODE_BBOX);
+  elt->accept (*this);
+  box = bbox;
+
+  set_mode (MODE_RENDER);
+  if (pixels.numel () > 0)
+    {
+      elt->accept (*this);
+
+      switch (rotation)
+        {
+        case ROTATION_0:
+          break;
+        case ROTATION_90:
+            {
+              Array<octave_idx_type> perm (dim_vector (3, 1));
+              perm(0) = 0;
+              perm(1) = 2;
+              perm(2) = 1;
+              pixels = pixels.permute (perm);
+
+              Array<idx_vector> idx (dim_vector (3, 1));
+              idx(0) = idx_vector (':');
+              idx(1) = idx_vector (pixels.dim2 ()-1, -1, -1);
+              idx(2) = idx_vector (':');
+              pixels = uint8NDArray (pixels.index (idx));
+            }
+          break;
+        case ROTATION_180:
+            {
+              Array<idx_vector> idx (dim_vector (3, 1));
+              idx(0) = idx_vector (':');
+              idx(1) = idx_vector (pixels.dim2 ()-1, -1, -1);
+              idx(2)=  idx_vector (pixels.dim3 ()-1, -1, -1);
+              pixels = uint8NDArray (pixels.index (idx));
+            }
+          break;
+        case ROTATION_270:
+            {
+              Array<octave_idx_type> perm (dim_vector (3, 1));
+              perm(0) = 0;
+              perm(1) = 2;
+              perm(2) = 1;
+              pixels = pixels.permute (perm);
+
+              Array<idx_vector> idx (dim_vector (3, 1));
+              idx(0) = idx_vector (':');
+              idx(1) = idx_vector (':');
+              idx(2) = idx_vector (pixels.dim3 ()-1, -1, -1);
+              pixels = uint8NDArray (pixels.index (idx));
+            }
+          break;
+        }
+    }
+
+  return pixels;
+}
+
+Matrix
+ft_render::get_extent (text_element *elt, double rotation)
+{
+  set_mode (MODE_BBOX);
+  elt->accept (*this);
+
+  Matrix extent (1, 2, 0.0);
+
+  switch (rotation_to_mode (rotation))
+    {
+    case ROTATION_0:
+    case ROTATION_180:
+      extent(0) = bbox(2);
+      extent(1) = bbox(3);
+      break;
+    case ROTATION_90:
+    case ROTATION_270:
+      extent(0) = bbox(3);
+      extent(1) = bbox(2);
+    }
+
+  return extent;
+}
+
+Matrix
+ft_render::get_extent (const std::string& txt, double rotation)
+{
+  text_element *elt = text_parser_none ().parse (txt);
+  Matrix extent = get_extent (elt, rotation);
+  delete elt;
+
+  return extent;
+}
+
+int
+ft_render::rotation_to_mode (double rotation) const
+{
+  if (rotation == 0.0)
+    return ROTATION_0;
+  else if (rotation == 90.0)
+    return ROTATION_90;
+  else if (rotation == 180.0)
+    return ROTATION_180;
+  else if (rotation == 270.0)
+    return ROTATION_270;
+  else
+    return ROTATION_0;
+}
+
+void
+ft_render::text_to_pixels (const std::string& txt,
+                           uint8NDArray& pixels_, Matrix& box,
+                           int halign, int valign, double rotation)
+{
+  // FIXME: clip "rotation" between 0 and 360
+  int rot_mode = rotation_to_mode (rotation);
+
+  multiline_halign = halign;
+
+  text_element *elt = text_parser_none ().parse (txt);
+  pixels_ = render (elt, box, rot_mode);
+  delete elt;
+
+  if (pixels_.numel () == 0)
+    {
+      // nothing to render
+      return;
+    }
+
+  switch (halign)
+    {
+    default: box(0) = 0; break;
+    case 1: box(0) = -box(2)/2; break;
+    case 2: box(0) = -box(2); break;
+    }
+  switch (valign)
+    {
+    default: box(1) = 0; break;
+    case 1: box(1) = -box(3)/2; break;
+    case 2: box(1) = -box(3); break;
+    case 3: break;
+    }
+
+  switch (rot_mode)
+    {
+    case ROTATION_90:
+      std::swap (box(0), box(1));
+      std::swap (box(2), box(3));
+      box(0) = -box(0)-box(2);
+      break;
+    case ROTATION_180:
+      box(0) = -box(0)-box(2);
+      box(1) = -box(1)-box(3);
+      break;
+    case ROTATION_270:
+      std::swap (box(0), box(1));
+      std::swap (box(2), box(3));
+      box(1) = -box(1)-box(3);
+      break;
+    }
+}
+
+#endif // HAVE_FREETYPE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/txt-eng-ft.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,107 @@
+/*
+
+Copyright (C) 2009-2012 Michael Goffioul
+
+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/>.
+
+*/
+
+#if ! defined (txt_eng_ft_h)
+#define txt_eng_ft_h 1
+
+#if HAVE_FREETYPE
+
+#include <vector>
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#include <dMatrix.h>
+#include <uint8NDArray.h>
+#include "txt-eng.h"
+
+class
+OCTINTERP_API
+ft_render : public text_processor
+{
+public:
+  enum {
+      MODE_BBOX   = 0,
+      MODE_RENDER = 1
+  };
+
+  enum {
+      ROTATION_0   = 0,
+      ROTATION_90  = 1,
+      ROTATION_180 = 2,
+      ROTATION_270 = 3
+  };
+
+public:
+  ft_render (void);
+
+  ~ft_render (void);
+
+  void visit (text_element_string& e);
+
+  void reset (void);
+
+  uint8NDArray get_pixels (void) const { return pixels; }
+
+  Matrix get_boundingbox (void) const { return bbox; }
+
+  uint8NDArray render (text_element* elt, Matrix& box,
+                       int rotation = ROTATION_0);
+
+  Matrix get_extent (text_element *elt, double rotation = 0.0);
+  Matrix get_extent (const std::string& txt, double rotation = 0.0);
+
+  void set_font (const std::string& name, const std::string& weight,
+                 const std::string& angle, double size);
+
+  void set_color (Matrix c);
+
+  void set_mode (int m);
+
+  void text_to_pixels (const std::string& txt,
+                       uint8NDArray& pixels_, Matrix& bbox,
+                       int halign, int valign, double rotation);
+
+private:
+  int rotation_to_mode (double rotation) const;
+
+  // No copying!
+
+  ft_render (const ft_render&);
+
+  ft_render& operator = (const ft_render&);
+
+private:
+  FT_Face face;
+  Matrix bbox;
+  uint8NDArray pixels;
+  int xoffset;
+  int yoffset;
+  int multiline_halign;
+  std::vector<int> multiline_align_xoffsets;
+  int mode;
+  uint8_t red, green, blue;
+};
+
+#endif // HAVE_FREETYPE
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/txt-eng.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,193 @@
+/*
+
+Copyright (C) 2009-2012 Michael Goffioul
+
+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/>.
+
+*/
+
+#if ! defined (txt_eng_h)
+#define txt_eng_h 1
+
+#include "base-list.h"
+
+class text_element;
+class text_element_string;
+class text_element_list;
+class text_subscript_element;
+class text_superscript_element;
+
+class text_processor;
+
+class
+OCTINTERP_API
+text_element
+{
+public:
+  text_element (void) { }
+
+  virtual ~text_element (void) { }
+
+  virtual void accept (text_processor& p) = 0;
+
+private:
+  text_element (const text_element&);
+};
+
+class
+OCTINTERP_API
+text_element_string : public text_element
+{
+public:
+  text_element_string (const std::string& s = "")
+      : text_element (), str (s) { }
+
+  ~text_element_string (void) { }
+
+  std::string string_value (void) const { return str; }
+
+  void accept (text_processor& p);
+
+private:
+  std::string str;
+
+private:
+  text_element_string (const text_element_string &);
+};
+
+class
+OCTINTERP_API
+text_element_list :
+    public text_element,
+    public octave_base_list<text_element *>
+{
+public:
+  text_element_list (void)
+      : text_element (), octave_base_list<text_element*> () { }
+
+  ~text_element_list (void)
+    {
+      while (! empty ())
+        {
+          iterator it = begin ();
+          delete (*it);
+          erase (it);
+        }
+    }
+
+  void accept (text_processor& p);
+};
+
+class
+OCTINTERP_API
+text_subscript_element : public text_element_list
+{
+public:
+  text_subscript_element (void)
+      : text_element_list () { }
+
+  ~text_subscript_element (void) { }
+
+  void accept (text_processor& p);
+};
+
+class
+OCTINTERP_API
+text_superscript_element : public text_element_list
+{
+public:
+  text_superscript_element (void)
+      : text_element_list () { }
+
+  ~text_superscript_element (void) { }
+
+  void accept (text_processor& p);
+};
+
+class
+OCTINTERP_API
+text_processor
+{
+public:
+  virtual void visit (text_element_string& e) = 0;
+
+  virtual void visit (text_element_list& e)
+    {
+      for (text_element_list::iterator it = e.begin ();
+           it != e.end (); ++it)
+        {
+          (*it)->accept (*this);
+        }
+    }
+
+  virtual void visit (text_subscript_element& e)
+    { visit (dynamic_cast<text_element_list&> (e)); }
+
+  virtual void visit (text_superscript_element& e)
+    { visit (dynamic_cast<text_element_list&> (e)); }
+
+  virtual void reset (void) { }
+
+protected:
+  text_processor (void) { }
+
+  virtual ~text_processor (void) { }
+};
+
+#define TEXT_ELEMENT_ACCEPT(cls) \
+inline void \
+cls::accept (text_processor& p) \
+{ p.visit (*this); }
+
+TEXT_ELEMENT_ACCEPT(text_element_string)
+TEXT_ELEMENT_ACCEPT(text_element_list)
+TEXT_ELEMENT_ACCEPT(text_subscript_element)
+TEXT_ELEMENT_ACCEPT(text_superscript_element)
+
+class
+OCTINTERP_API
+text_parser
+{
+public:
+  text_parser (void) { }
+
+  virtual ~text_parser (void) { }
+
+  virtual text_element* parse (const std::string& s) = 0;
+};
+
+class
+OCTINTERP_API
+text_parser_none : public text_parser
+{
+public:
+  text_parser_none (void) : text_parser () { }
+
+  ~text_parser_none (void) { }
+
+  // FIXME: is it possible to use reference counting to manage the
+  // memory for the object returned by the text parser?  That would be
+  // preferable to having to know when and where to delete the object it
+  // creates...
+
+  text_element* parse (const std::string& s)
+    {
+      return new text_element_string (s);
+    }
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/unwind-prot.cc	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,39 @@
+/*
+
+Copyright (C) 1993-2012 John W. Eaton
+Copyright (C) 2009 VZLU Prague
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <cstddef>
+#include <cstring>
+
+#include "error.h"
+#include "unwind-prot.h"
+#include "utils.h"
+
+void unwind_protect_safe::gripe_exception (void)
+{
+  // FIXME: can this throw an exception?
+  error ("internal: unhandled exception in unwind_protect handler");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/unwind-prot.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,344 @@
+/*
+
+Copyright (C) 1993-2012 John W. Eaton
+Copyright (C) 2009-2010 VZLU Prague
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if !defined (octave_unwind_prot_h)
+#define octave_unwind_prot_h 1
+
+#include <cstddef>
+
+#include <string>
+#include <memory>
+
+// This class allows registering cleanup actions.
+class
+OCTINTERP_API
+unwind_protect
+{
+public:
+
+  // A generic unwind_protect element. Knows how to run itself and discard itself.
+  // Also, contains a pointer to the next element.
+  class elem
+  {
+    elem *next;
+
+  public:
+    elem (void) : next (0) { }
+
+    virtual void run (void) { }
+
+    virtual ~elem (void) { }
+
+    friend class unwind_protect;
+
+  private:
+
+    // No copying!
+
+    elem (const elem&);
+
+    elem& operator = (const elem&);
+  };
+
+  // An element that merely runs a void (*)(void) function.
+
+  class fcn_elem : public elem
+  {
+  public:
+    fcn_elem (void (*fptr) (void))
+      : e_fptr (fptr) { }
+
+    void run (void) { e_fptr (); }
+
+  private:
+    void (*e_fptr) (void);
+  };
+
+  // An element that stores a variable of type T along with a void (*) (T)
+  // function pointer, and calls the function with the parameter.
+
+  template <class T>
+  class fcn_arg_elem : public elem
+  {
+  public:
+    fcn_arg_elem (void (*fcn) (T), T arg)
+      : e_fcn (fcn), e_arg (arg) { }
+
+    void run (void) { e_fcn (e_arg); }
+
+  private:
+
+    // No copying!
+
+    fcn_arg_elem (const fcn_arg_elem&);
+
+    fcn_arg_elem& operator = (const fcn_arg_elem&);
+
+    void (*e_fcn) (T);
+    T e_arg;
+  };
+
+  // An element that stores a variable of type T along with a void (*) (const T&)
+  // function pointer, and calls the function with the parameter.
+
+  template <class T>
+  class fcn_crefarg_elem : public elem
+  {
+  public:
+    fcn_crefarg_elem (void (*fcn) (const T&), T arg)
+      : e_fcn (fcn), e_arg (arg) { }
+
+    void run (void) { e_fcn (e_arg); }
+
+  private:
+    void (*e_fcn) (const T&);
+    T e_arg;
+  };
+
+  // An element for calling a member function.
+
+  template <class T>
+  class method_elem : public elem
+  {
+  public:
+    method_elem (T *obj, void (T::*method) (void))
+      : e_obj (obj), e_method (method) { }
+
+    void run (void) { (e_obj->*e_method) (); }
+
+  private:
+
+    T *e_obj;
+    void (T::*e_method) (void);
+
+    // No copying!
+
+    method_elem (const method_elem&);
+
+    method_elem operator = (const method_elem&);
+  };
+
+  // An element that stores arbitrary variable, and restores it.
+
+  template <class T>
+  class restore_var_elem : public elem
+  {
+  public:
+    restore_var_elem (T& ref, const T& val)
+      : e_ptr (&ref), e_val (val) { }
+
+    void run (void) { *e_ptr = e_val; }
+
+  private:
+
+    // No copying!
+
+    restore_var_elem (const restore_var_elem&);
+
+    restore_var_elem& operator = (const restore_var_elem&);
+
+    T *e_ptr, e_val;
+  };
+
+  // Deletes a class allocated using new.
+
+  template <class T>
+  class delete_ptr_elem : public elem
+  {
+  public:
+    delete_ptr_elem (T *ptr)
+      : e_ptr (ptr) { }
+
+    void run (void) { delete e_ptr; }
+
+  private:
+
+    T *e_ptr;
+
+    // No copying!
+
+    delete_ptr_elem (const delete_ptr_elem&);
+
+    delete_ptr_elem operator = (const delete_ptr_elem&);
+  };
+
+  unwind_protect (void) : head () { }
+
+  void add (elem *new_elem)
+    {
+      new_elem->next = head;
+      head = new_elem;
+    }
+
+  // For backward compatibility.
+  void add (void (*fcn) (void *), void *ptr = 0)
+    {
+      add (new fcn_arg_elem<void *> (fcn, ptr));
+    }
+
+  // Call to void func (void).
+  void add_fcn (void (*fcn) (void))
+    {
+      add (new fcn_elem (fcn));
+    }
+
+  // Call to void func (T).
+  template <class T>
+  void add_fcn (void (*action) (T), T val)
+    {
+      add (new fcn_arg_elem<T> (action, val));
+    }
+
+  // Call to void func (const T&).
+  template <class T>
+  void add_fcn (void (*action) (const T&), T val)
+    {
+      add (new fcn_crefarg_elem<T> (action, val));
+    }
+
+  // Call to T::method (void).
+  template <class T>
+  void add_method (T *obj, void (T::*method) (void))
+    {
+      add (new method_elem<T> (obj, method));
+    }
+
+  // Call to delete (T*).
+
+  template <class T>
+  void add_delete (T *obj)
+    {
+      add (new delete_ptr_elem<T> (obj));
+    }
+
+  // Protect any variable.
+  template <class T>
+  void protect_var (T& var)
+    {
+      add (new restore_var_elem<T> (var, var));
+    }
+
+  // Protect any variable, value given.
+  template <class T>
+  void protect_var (T& var, const T& val)
+    {
+      add (new restore_var_elem<T> (var, val));
+    }
+
+  operator bool (void) const
+    {
+      return head != 0;
+    }
+
+  void run_top (void)
+    {
+      if (head)
+        {
+          // No leak on exception!
+          std::auto_ptr<elem> ptr (head);
+          head = ptr->next;
+          ptr->run ();
+        }
+    }
+
+  void run_top (int num)
+    {
+      while (num-- > 0)
+        run_top ();
+    }
+
+  void discard_top (void)
+    {
+      if (head)
+        {
+          elem *ptr = head;
+          head = ptr->next;
+          delete ptr;
+        }
+    }
+
+  void discard_top (int num)
+    {
+      while (num-- > 0)
+        discard_top ();
+    }
+
+  void run (void)
+    {
+      while (head)
+        run_top ();
+    }
+
+  void discard (void)
+    {
+      while (head)
+        discard_top ();
+    }
+
+  // Destructor should not raise an exception, so all actions registered should
+  // be exception-safe (but setting error_state is allowed). If you're not sure,
+  // see unwind_protect_safe.
+  ~unwind_protect (void)
+    {
+      run ();
+    }
+
+private:
+
+  elem *head;
+
+  // No copying!
+
+  unwind_protect (const unwind_protect&);
+
+  unwind_protect& operator = (const unwind_protect&);
+};
+
+// Like unwind_protect, but this one will guard against the possibility of seeing
+// an exception (or interrupt) in the cleanup actions. Not that we can do much about
+// it, but at least we won't crash.
+
+class
+OCTINTERP_API
+unwind_protect_safe : public unwind_protect
+{
+  static void gripe_exception (void);
+
+public:
+  ~unwind_protect_safe (void)
+    {
+      while (*this)
+        {
+          try
+            {
+              run_top ();
+            }
+          catch (...) // Yes, the black hole. Remember we're in a dtor.
+            {
+              gripe_exception ();
+            }
+        }
+    }
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/xdiv.cc	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,1000 @@
+/*
+
+Copyright (C) 1993-2012 John W. Eaton
+Copyright (C) 2008 Jaroslav Hajek
+Copyright (C) 2009-2010 VZLU Prague
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <cassert>
+
+#include "Array-util.h"
+#include "CMatrix.h"
+#include "dMatrix.h"
+#include "CNDArray.h"
+#include "dNDArray.h"
+#include "fCMatrix.h"
+#include "fMatrix.h"
+#include "fCNDArray.h"
+#include "fNDArray.h"
+#include "oct-cmplx.h"
+#include "dDiagMatrix.h"
+#include "fDiagMatrix.h"
+#include "CDiagMatrix.h"
+#include "fCDiagMatrix.h"
+#include "quit.h"
+
+#include "error.h"
+#include "xdiv.h"
+
+static inline bool
+result_ok (octave_idx_type info)
+{
+  assert (info != -1);
+
+  return (info != -2);
+}
+
+static void
+solve_singularity_warning (double rcond)
+{
+  warning_with_id ("Octave:singular-matrix-div",
+                   "matrix singular to machine precision, rcond = %g", rcond);
+}
+
+template <class T1, class T2>
+bool
+mx_leftdiv_conform (const T1& a, const T2& b, blas_trans_type blas_trans)
+{
+  octave_idx_type a_nr = blas_trans == blas_no_trans ? a.rows () : a.cols ();
+  octave_idx_type b_nr = b.rows ();
+
+  if (a_nr != b_nr)
+    {
+      octave_idx_type a_nc = blas_trans == blas_no_trans ? a.cols () : a.rows ();
+      octave_idx_type b_nc = b.cols ();
+
+      gripe_nonconformant ("operator \\", a_nr, a_nc, b_nr, b_nc);
+      return false;
+    }
+
+  return true;
+}
+
+#define INSTANTIATE_MX_LEFTDIV_CONFORM(T1, T2) \
+  template bool mx_leftdiv_conform (const T1&, const T2&, blas_trans_type)
+
+INSTANTIATE_MX_LEFTDIV_CONFORM (Matrix, Matrix);
+INSTANTIATE_MX_LEFTDIV_CONFORM (Matrix, ComplexMatrix);
+INSTANTIATE_MX_LEFTDIV_CONFORM (ComplexMatrix, Matrix);
+INSTANTIATE_MX_LEFTDIV_CONFORM (ComplexMatrix, ComplexMatrix);
+
+template <class T1, class T2>
+bool
+mx_div_conform (const T1& a, const T2& b)
+{
+  octave_idx_type a_nc = a.cols ();
+  octave_idx_type b_nc = b.cols ();
+
+  if (a_nc != b_nc)
+    {
+      octave_idx_type a_nr = a.rows ();
+      octave_idx_type b_nr = b.rows ();
+
+      gripe_nonconformant ("operator /", a_nr, a_nc, b_nr, b_nc);
+      return false;
+    }
+
+  return true;
+}
+
+#define INSTANTIATE_MX_DIV_CONFORM(T1, T2) \
+  template bool mx_div_conform (const T1&, const T2&)
+
+INSTANTIATE_MX_DIV_CONFORM (Matrix, Matrix);
+INSTANTIATE_MX_DIV_CONFORM (Matrix, ComplexMatrix);
+INSTANTIATE_MX_DIV_CONFORM (ComplexMatrix, Matrix);
+INSTANTIATE_MX_DIV_CONFORM (ComplexMatrix, ComplexMatrix);
+
+// Right division functions.
+//
+//       op2 / op1:   m   cm
+//            +--   +---+----+
+//   matrix         | 1 |  3 |
+//                  +---+----+
+//   complex_matrix | 2 |  4 |
+//                  +---+----+
+
+// -*- 1 -*-
+Matrix
+xdiv (const Matrix& a, const Matrix& b, MatrixType &typ)
+{
+  if (! mx_div_conform (a, b))
+    return Matrix ();
+
+  octave_idx_type info;
+  double rcond = 0.0;
+
+  Matrix result
+    = b.solve (typ, a.transpose (), info, rcond,
+               solve_singularity_warning, true, blas_trans);
+
+  return result.transpose ();
+}
+
+// -*- 2 -*-
+ComplexMatrix
+xdiv (const Matrix& a, const ComplexMatrix& b, MatrixType &typ)
+{
+  if (! mx_div_conform (a, b))
+    return ComplexMatrix ();
+
+  octave_idx_type info;
+  double rcond = 0.0;
+
+  ComplexMatrix result
+    = b.solve (typ, a.transpose (), info, rcond,
+               solve_singularity_warning, true, blas_trans);
+
+  return result.transpose ();
+}
+
+// -*- 3 -*-
+ComplexMatrix
+xdiv (const ComplexMatrix& a, const Matrix& b, MatrixType &typ)
+{
+  if (! mx_div_conform (a, b))
+    return ComplexMatrix ();
+
+  octave_idx_type info;
+  double rcond = 0.0;
+
+  ComplexMatrix result
+    = b.solve (typ, a.transpose (), info, rcond,
+               solve_singularity_warning, true, blas_trans);
+
+  return result.transpose ();
+}
+
+// -*- 4 -*-
+ComplexMatrix
+xdiv (const ComplexMatrix& a, const ComplexMatrix& b, MatrixType &typ)
+{
+  if (! mx_div_conform (a, b))
+    return ComplexMatrix ();
+
+  octave_idx_type info;
+  double rcond = 0.0;
+
+  ComplexMatrix result
+    = b.solve (typ, a.transpose (), info, rcond,
+               solve_singularity_warning, true, blas_trans);
+
+  return result.transpose ();
+}
+
+// Funny element by element division operations.
+//
+//       op2 \ op1:   s   cs
+//            +--   +---+----+
+//   matrix         | 1 |  3 |
+//                  +---+----+
+//   complex_matrix | 2 |  4 |
+//                  +---+----+
+
+Matrix
+x_el_div (double a, const Matrix& b)
+{
+  octave_idx_type nr = b.rows ();
+  octave_idx_type nc = b.columns ();
+
+  Matrix result (nr, nc);
+
+  for (octave_idx_type j = 0; j < nc; j++)
+    for (octave_idx_type i = 0; i < nr; i++)
+      {
+        octave_quit ();
+        result (i, j) = a / b (i, j);
+      }
+
+  return result;
+}
+
+ComplexMatrix
+x_el_div (double a, const ComplexMatrix& b)
+{
+  octave_idx_type nr = b.rows ();
+  octave_idx_type nc = b.columns ();
+
+  ComplexMatrix result (nr, nc);
+
+  for (octave_idx_type j = 0; j < nc; j++)
+    for (octave_idx_type i = 0; i < nr; i++)
+      {
+        octave_quit ();
+        result (i, j) = a / b (i, j);
+      }
+
+  return result;
+}
+
+ComplexMatrix
+x_el_div (const Complex a, const Matrix& b)
+{
+  octave_idx_type nr = b.rows ();
+  octave_idx_type nc = b.columns ();
+
+  ComplexMatrix result (nr, nc);
+
+  for (octave_idx_type j = 0; j < nc; j++)
+    for (octave_idx_type i = 0; i < nr; i++)
+      {
+        octave_quit ();
+        result (i, j) = a / b (i, j);
+      }
+
+  return result;
+}
+
+ComplexMatrix
+x_el_div (const Complex a, const ComplexMatrix& b)
+{
+  octave_idx_type nr = b.rows ();
+  octave_idx_type nc = b.columns ();
+
+  ComplexMatrix result (nr, nc);
+
+  for (octave_idx_type j = 0; j < nc; j++)
+    for (octave_idx_type i = 0; i < nr; i++)
+      {
+        octave_quit ();
+        result (i, j) = a / b (i, j);
+      }
+
+  return result;
+}
+
+// Funny element by element division operations.
+//
+//          op2 \ op1:   s   cs
+//               +--   +---+----+
+//   N-d array         | 1 |  3 |
+//                     +---+----+
+//   complex N-d array | 2 |  4 |
+//                     +---+----+
+
+NDArray
+x_el_div (double a, const NDArray& b)
+{
+  NDArray result (b.dims ());
+
+  for (octave_idx_type i = 0; i < b.length (); i++)
+    {
+      octave_quit ();
+      result (i) = a / b (i);
+    }
+
+  return result;
+}
+
+ComplexNDArray
+x_el_div (double a, const ComplexNDArray& b)
+{
+  ComplexNDArray result (b.dims ());
+
+  for (octave_idx_type i = 0; i < b.length (); i++)
+    {
+      octave_quit ();
+      result (i) = a / b (i);
+    }
+
+  return result;
+}
+
+ComplexNDArray
+x_el_div (const Complex a, const NDArray& b)
+{
+  ComplexNDArray result (b.dims ());
+
+  for (octave_idx_type i = 0; i < b.length (); i++)
+    {
+      octave_quit ();
+      result (i) = a / b (i);
+    }
+
+  return result;
+}
+
+ComplexNDArray
+x_el_div (const Complex a, const ComplexNDArray& b)
+{
+  ComplexNDArray result (b.dims ());
+
+  for (octave_idx_type i = 0; i < b.length (); i++)
+    {
+      octave_quit ();
+      result (i) = a / b (i);
+    }
+
+  return result;
+}
+
+// Left division functions.
+//
+//       op2 \ op1:   m   cm
+//            +--   +---+----+
+//   matrix         | 1 |  3 |
+//                  +---+----+
+//   complex_matrix | 2 |  4 |
+//                  +---+----+
+
+// -*- 1 -*-
+Matrix
+xleftdiv (const Matrix& a, const Matrix& b, MatrixType &typ, blas_trans_type transt)
+{
+  if (! mx_leftdiv_conform (a, b, transt))
+    return Matrix ();
+
+  octave_idx_type info;
+  double rcond = 0.0;
+  return a.solve (typ, b, info, rcond, solve_singularity_warning, true, transt);
+}
+
+// -*- 2 -*-
+ComplexMatrix
+xleftdiv (const Matrix& a, const ComplexMatrix& b, MatrixType &typ, blas_trans_type transt)
+{
+  if (! mx_leftdiv_conform (a, b, transt))
+    return ComplexMatrix ();
+
+  octave_idx_type info;
+  double rcond = 0.0;
+
+  return a.solve (typ, b, info, rcond, solve_singularity_warning, true, transt);
+}
+
+// -*- 3 -*-
+ComplexMatrix
+xleftdiv (const ComplexMatrix& a, const Matrix& b, MatrixType &typ, blas_trans_type transt)
+{
+  if (! mx_leftdiv_conform (a, b, transt))
+    return ComplexMatrix ();
+
+  octave_idx_type info;
+  double rcond = 0.0;
+  return a.solve (typ, b, info, rcond, solve_singularity_warning, true, transt);
+}
+
+// -*- 4 -*-
+ComplexMatrix
+xleftdiv (const ComplexMatrix& a, const ComplexMatrix& b, MatrixType &typ, blas_trans_type transt)
+{
+  if (! mx_leftdiv_conform (a, b, transt))
+    return ComplexMatrix ();
+
+  octave_idx_type info;
+  double rcond = 0.0;
+  return a.solve (typ, b, info, rcond, solve_singularity_warning, true, transt);
+}
+
+static void
+solve_singularity_warning (float rcond)
+{
+  warning ("matrix singular to machine precision, rcond = %g", rcond);
+  warning ("attempting to find minimum norm solution");
+}
+
+INSTANTIATE_MX_LEFTDIV_CONFORM (FloatMatrix, FloatMatrix);
+INSTANTIATE_MX_LEFTDIV_CONFORM (FloatMatrix, FloatComplexMatrix);
+INSTANTIATE_MX_LEFTDIV_CONFORM (FloatComplexMatrix, FloatMatrix);
+INSTANTIATE_MX_LEFTDIV_CONFORM (FloatComplexMatrix, FloatComplexMatrix);
+
+INSTANTIATE_MX_DIV_CONFORM (FloatMatrix, FloatMatrix);
+INSTANTIATE_MX_DIV_CONFORM (FloatMatrix, FloatComplexMatrix);
+INSTANTIATE_MX_DIV_CONFORM (FloatComplexMatrix, FloatMatrix);
+INSTANTIATE_MX_DIV_CONFORM (FloatComplexMatrix, FloatComplexMatrix);
+
+// Right division functions.
+//
+//       op2 / op1:   m   cm
+//            +--   +---+----+
+//   matrix         | 1 |  3 |
+//                  +---+----+
+//   complex_matrix | 2 |  4 |
+//                  +---+----+
+
+// -*- 1 -*-
+FloatMatrix
+xdiv (const FloatMatrix& a, const FloatMatrix& b, MatrixType &typ)
+{
+  if (! mx_div_conform (a, b))
+    return FloatMatrix ();
+
+  octave_idx_type info;
+  float rcond = 0.0;
+
+  FloatMatrix result
+    = b.solve (typ, a.transpose (), info, rcond,
+               solve_singularity_warning, true, blas_trans);
+
+  return result.transpose ();
+}
+
+// -*- 2 -*-
+FloatComplexMatrix
+xdiv (const FloatMatrix& a, const FloatComplexMatrix& b, MatrixType &typ)
+{
+  if (! mx_div_conform (a, b))
+    return FloatComplexMatrix ();
+
+  octave_idx_type info;
+  float rcond = 0.0;
+
+  FloatComplexMatrix result
+    = b.solve (typ, a.transpose (), info, rcond,
+               solve_singularity_warning, true, blas_trans);
+
+  return result.transpose ();
+}
+
+// -*- 3 -*-
+FloatComplexMatrix
+xdiv (const FloatComplexMatrix& a, const FloatMatrix& b, MatrixType &typ)
+{
+  if (! mx_div_conform (a, b))
+    return FloatComplexMatrix ();
+
+  octave_idx_type info;
+  float rcond = 0.0;
+
+  FloatComplexMatrix result
+    = b.solve (typ, a.transpose (), info, rcond,
+               solve_singularity_warning, true, blas_trans);
+
+  return result.transpose ();
+}
+
+// -*- 4 -*-
+FloatComplexMatrix
+xdiv (const FloatComplexMatrix& a, const FloatComplexMatrix& b, MatrixType &typ)
+{
+  if (! mx_div_conform (a, b))
+    return FloatComplexMatrix ();
+
+  octave_idx_type info;
+  float rcond = 0.0;
+
+  FloatComplexMatrix result
+    = b.solve (typ, a.transpose (), info, rcond,
+               solve_singularity_warning, true, blas_trans);
+
+  return result.transpose ();
+}
+
+// Funny element by element division operations.
+//
+//       op2 \ op1:   s   cs
+//            +--   +---+----+
+//   matrix         | 1 |  3 |
+//                  +---+----+
+//   complex_matrix | 2 |  4 |
+//                  +---+----+
+
+FloatMatrix
+x_el_div (float a, const FloatMatrix& b)
+{
+  octave_idx_type nr = b.rows ();
+  octave_idx_type nc = b.columns ();
+
+  FloatMatrix result (nr, nc);
+
+  for (octave_idx_type j = 0; j < nc; j++)
+    for (octave_idx_type i = 0; i < nr; i++)
+      {
+        octave_quit ();
+        result (i, j) = a / b (i, j);
+      }
+
+  return result;
+}
+
+FloatComplexMatrix
+x_el_div (float a, const FloatComplexMatrix& b)
+{
+  octave_idx_type nr = b.rows ();
+  octave_idx_type nc = b.columns ();
+
+  FloatComplexMatrix result (nr, nc);
+
+  for (octave_idx_type j = 0; j < nc; j++)
+    for (octave_idx_type i = 0; i < nr; i++)
+      {
+        octave_quit ();
+        result (i, j) = a / b (i, j);
+      }
+
+  return result;
+}
+
+FloatComplexMatrix
+x_el_div (const FloatComplex a, const FloatMatrix& b)
+{
+  octave_idx_type nr = b.rows ();
+  octave_idx_type nc = b.columns ();
+
+  FloatComplexMatrix result (nr, nc);
+
+  for (octave_idx_type j = 0; j < nc; j++)
+    for (octave_idx_type i = 0; i < nr; i++)
+      {
+        octave_quit ();
+        result (i, j) = a / b (i, j);
+      }
+
+  return result;
+}
+
+FloatComplexMatrix
+x_el_div (const FloatComplex a, const FloatComplexMatrix& b)
+{
+  octave_idx_type nr = b.rows ();
+  octave_idx_type nc = b.columns ();
+
+  FloatComplexMatrix result (nr, nc);
+
+  for (octave_idx_type j = 0; j < nc; j++)
+    for (octave_idx_type i = 0; i < nr; i++)
+      {
+        octave_quit ();
+        result (i, j) = a / b (i, j);
+      }
+
+  return result;
+}
+
+// Funny element by element division operations.
+//
+//          op2 \ op1:   s   cs
+//               +--   +---+----+
+//   N-d array         | 1 |  3 |
+//                     +---+----+
+//   complex N-d array | 2 |  4 |
+//                     +---+----+
+
+FloatNDArray
+x_el_div (float a, const FloatNDArray& b)
+{
+  FloatNDArray result (b.dims ());
+
+  for (octave_idx_type i = 0; i < b.length (); i++)
+    {
+      octave_quit ();
+      result (i) = a / b (i);
+    }
+
+  return result;
+}
+
+FloatComplexNDArray
+x_el_div (float a, const FloatComplexNDArray& b)
+{
+  FloatComplexNDArray result (b.dims ());
+
+  for (octave_idx_type i = 0; i < b.length (); i++)
+    {
+      octave_quit ();
+      result (i) = a / b (i);
+    }
+
+  return result;
+}
+
+FloatComplexNDArray
+x_el_div (const FloatComplex a, const FloatNDArray& b)
+{
+  FloatComplexNDArray result (b.dims ());
+
+  for (octave_idx_type i = 0; i < b.length (); i++)
+    {
+      octave_quit ();
+      result (i) = a / b (i);
+    }
+
+  return result;
+}
+
+FloatComplexNDArray
+x_el_div (const FloatComplex a, const FloatComplexNDArray& b)
+{
+  FloatComplexNDArray result (b.dims ());
+
+  for (octave_idx_type i = 0; i < b.length (); i++)
+    {
+      octave_quit ();
+      result (i) = a / b (i);
+    }
+
+  return result;
+}
+
+// Left division functions.
+//
+//       op2 \ op1:   m   cm
+//            +--   +---+----+
+//   matrix         | 1 |  3 |
+//                  +---+----+
+//   complex_matrix | 2 |  4 |
+//                  +---+----+
+
+// -*- 1 -*-
+FloatMatrix
+xleftdiv (const FloatMatrix& a, const FloatMatrix& b, MatrixType &typ, blas_trans_type transt)
+{
+  if (! mx_leftdiv_conform (a, b, transt))
+    return FloatMatrix ();
+
+  octave_idx_type info;
+  float rcond = 0.0;
+  return a.solve (typ, b, info, rcond, solve_singularity_warning, true, transt);
+}
+
+// -*- 2 -*-
+FloatComplexMatrix
+xleftdiv (const FloatMatrix& a, const FloatComplexMatrix& b, MatrixType &typ, blas_trans_type transt)
+{
+  if (! mx_leftdiv_conform (a, b, transt))
+    return FloatComplexMatrix ();
+
+  octave_idx_type info;
+  float rcond = 0.0;
+
+  return a.solve (typ, b, info, rcond, solve_singularity_warning, true, transt);
+}
+
+// -*- 3 -*-
+FloatComplexMatrix
+xleftdiv (const FloatComplexMatrix& a, const FloatMatrix& b, MatrixType &typ, blas_trans_type transt)
+{
+  if (! mx_leftdiv_conform (a, b, transt))
+    return FloatComplexMatrix ();
+
+  octave_idx_type info;
+  float rcond = 0.0;
+  return a.solve (typ, b, info, rcond, solve_singularity_warning, true, transt);
+}
+
+// -*- 4 -*-
+FloatComplexMatrix
+xleftdiv (const FloatComplexMatrix& a, const FloatComplexMatrix& b, MatrixType &typ, blas_trans_type transt)
+{
+  if (! mx_leftdiv_conform (a, b, transt))
+    return FloatComplexMatrix ();
+
+  octave_idx_type info;
+  float rcond = 0.0;
+  return a.solve (typ, b, info, rcond, solve_singularity_warning, true, transt);
+}
+
+// Diagonal matrix division.
+
+template <class MT, class DMT>
+MT
+mdm_div_impl (const MT& a, const DMT& d)
+{
+  if (! mx_div_conform (a, d))
+    return MT ();
+
+  octave_idx_type m = a.rows (), n = d.rows (), l = d.length ();
+  MT x (m, n);
+  typedef typename DMT::element_type S;
+  typedef typename MT::element_type T;
+  const T *aa = a.data ();
+  const S *dd = d.data ();
+  T *xx = x.fortran_vec ();
+
+  for (octave_idx_type j = 0; j < l; j++)
+    {
+      const S del = dd[j];
+      if (del != S ())
+        for (octave_idx_type i = 0; i < m; i++)
+          xx[i] = aa[i] / del;
+      else
+        for (octave_idx_type i = 0; i < m; i++)
+          xx[i] = T ();
+      aa += m; xx += m;
+    }
+
+  for (octave_idx_type i = l*m; i < n*m; i++)
+    xx[i] = T ();
+
+  return x;
+}
+
+// Right division functions.
+//
+//       op2 / op1:   dm  cdm
+//            +--   +---+----+
+//   matrix         | 1 |    |
+//                  +---+----+
+//   complex_matrix | 2 |  3 |
+//                  +---+----+
+
+// -*- 1 -*-
+Matrix
+xdiv (const Matrix& a, const DiagMatrix& b)
+{ return mdm_div_impl (a, b); }
+
+// -*- 2 -*-
+ComplexMatrix
+xdiv (const ComplexMatrix& a, const DiagMatrix& b)
+{ return mdm_div_impl (a, b); }
+
+// -*- 3 -*-
+ComplexMatrix
+xdiv (const ComplexMatrix& a, const ComplexDiagMatrix& b)
+{ return mdm_div_impl (a, b); }
+
+// Right division functions, float type.
+//
+//       op2 / op1:   dm  cdm
+//            +--   +---+----+
+//   matrix         | 1 |    |
+//                  +---+----+
+//   complex_matrix | 2 |  3 |
+//                  +---+----+
+
+// -*- 1 -*-
+FloatMatrix
+xdiv (const FloatMatrix& a, const FloatDiagMatrix& b)
+{ return mdm_div_impl (a, b); }
+
+// -*- 2 -*-
+FloatComplexMatrix
+xdiv (const FloatComplexMatrix& a, const FloatDiagMatrix& b)
+{ return mdm_div_impl (a, b); }
+
+// -*- 3 -*-
+FloatComplexMatrix
+xdiv (const FloatComplexMatrix& a, const FloatComplexDiagMatrix& b)
+{ return mdm_div_impl (a, b); }
+
+template <class MT, class DMT>
+MT
+dmm_leftdiv_impl (const DMT& d, const MT& a)
+{
+  if (! mx_leftdiv_conform (d, a, blas_no_trans))
+    return MT ();
+
+  octave_idx_type m = d.cols (), n = a.cols (), k = a.rows (), l = d.length ();
+  MT x (m, n);
+  typedef typename DMT::element_type S;
+  typedef typename MT::element_type T;
+  const T *aa = a.data ();
+  const S *dd = d.data ();
+  T *xx = x.fortran_vec ();
+
+  for (octave_idx_type j = 0; j < n; j++)
+    {
+      for (octave_idx_type i = 0; i < l; i++)
+        xx[i] = dd[i] != S () ? aa[i] / dd[i] : T ();
+      for (octave_idx_type i = l; i < m; i++)
+        xx[i] = T ();
+      aa += k; xx += m;
+    }
+
+  return x;
+}
+
+// Left division functions.
+//
+//       op2 \ op1:         m   cm
+//                        +---+----+
+//   diag_matrix          | 1 |  2 |
+//                        +---+----+
+//   complex_diag_matrix  |   |  3 |
+//                        +---+----+
+
+// -*- 1 -*-
+Matrix
+xleftdiv (const DiagMatrix& a, const Matrix& b)
+{ return dmm_leftdiv_impl (a, b); }
+
+// -*- 2 -*-
+ComplexMatrix
+xleftdiv (const DiagMatrix& a, const ComplexMatrix& b)
+{ return dmm_leftdiv_impl (a, b); }
+
+// -*- 3 -*-
+ComplexMatrix
+xleftdiv (const ComplexDiagMatrix& a, const ComplexMatrix& b)
+{ return dmm_leftdiv_impl (a, b); }
+
+// Left division functions, float type.
+//
+//       op2 \ op1:         m   cm
+//                        +---+----+
+//   diag_matrix          | 1 |  2 |
+//                        +---+----+
+//   complex_diag_matrix  |   |  3 |
+//                        +---+----+
+
+// -*- 1 -*-
+FloatMatrix
+xleftdiv (const FloatDiagMatrix& a, const FloatMatrix& b)
+{ return dmm_leftdiv_impl (a, b); }
+
+// -*- 2 -*-
+FloatComplexMatrix
+xleftdiv (const FloatDiagMatrix& a, const FloatComplexMatrix& b)
+{ return dmm_leftdiv_impl (a, b); }
+
+// -*- 3 -*-
+FloatComplexMatrix
+xleftdiv (const FloatComplexDiagMatrix& a, const FloatComplexMatrix& b)
+{ return dmm_leftdiv_impl (a, b); }
+
+// Diagonal by diagonal matrix division.
+
+template <class MT, class DMT>
+MT
+dmdm_div_impl (const MT& a, const DMT& d)
+{
+  if (! mx_div_conform (a, d))
+    return MT ();
+
+  octave_idx_type m = a.rows (), n = d.rows (), k = d.cols ();
+  octave_idx_type l = std::min (m, n), lk = std::min (l, k);
+  MT x (m, n);
+  typedef typename DMT::element_type S;
+  typedef typename MT::element_type T;
+  const T *aa = a.data ();
+  const S *dd = d.data ();
+  T *xx = x.fortran_vec ();
+
+  for (octave_idx_type i = 0; i < lk; i++)
+    xx[i] = dd[i] != S () ? aa[i] / dd[i] : T ();
+  for (octave_idx_type i = lk; i < l; i++)
+    xx[i] = T ();
+
+  return x;
+}
+
+// Right division functions.
+//
+//       op2 / op1:        dm  cdm
+//            +--        +---+----+
+//   diag_matrix         | 1 |    |
+//                       +---+----+
+//   complex_diag_matrix | 2 |  3 |
+//                       +---+----+
+
+// -*- 1 -*-
+DiagMatrix
+xdiv (const DiagMatrix& a, const DiagMatrix& b)
+{ return dmdm_div_impl (a, b); }
+
+// -*- 2 -*-
+ComplexDiagMatrix
+xdiv (const ComplexDiagMatrix& a, const DiagMatrix& b)
+{ return dmdm_div_impl (a, b); }
+
+// -*- 3 -*-
+ComplexDiagMatrix
+xdiv (const ComplexDiagMatrix& a, const ComplexDiagMatrix& b)
+{ return dmdm_div_impl (a, b); }
+
+// Right division functions, float type.
+//
+//       op2 / op1:        dm  cdm
+//            +--        +---+----+
+//   diag_matrix         | 1 |    |
+//                       +---+----+
+//   complex_diag_matrix | 2 |  3 |
+//                       +---+----+
+
+// -*- 1 -*-
+FloatDiagMatrix
+xdiv (const FloatDiagMatrix& a, const FloatDiagMatrix& b)
+{ return dmdm_div_impl (a, b); }
+
+// -*- 2 -*-
+FloatComplexDiagMatrix
+xdiv (const FloatComplexDiagMatrix& a, const FloatDiagMatrix& b)
+{ return dmdm_div_impl (a, b); }
+
+// -*- 3 -*-
+FloatComplexDiagMatrix
+xdiv (const FloatComplexDiagMatrix& a, const FloatComplexDiagMatrix& b)
+{ return dmdm_div_impl (a, b); }
+
+template <class MT, class DMT>
+MT
+dmdm_leftdiv_impl (const DMT& d, const MT& a)
+{
+  if (! mx_leftdiv_conform (d, a, blas_no_trans))
+    return MT ();
+
+  octave_idx_type m = d.cols (), n = a.cols (), k = d.rows ();
+  octave_idx_type l = std::min (m, n), lk = std::min (l, k);
+  MT x (m, n);
+  typedef typename DMT::element_type S;
+  typedef typename MT::element_type T;
+  const T *aa = a.data ();
+  const S *dd = d.data ();
+  T *xx = x.fortran_vec ();
+
+  for (octave_idx_type i = 0; i < lk; i++)
+    xx[i] = dd[i] != S () ? aa[i] / dd[i] : T ();
+  for (octave_idx_type i = lk; i < l; i++)
+    xx[i] = T ();
+
+  return x;
+}
+
+// Left division functions.
+//
+//       op2 \ op1:         dm  cdm
+//                        +---+----+
+//   diag_matrix          | 1 |  2 |
+//                        +---+----+
+//   complex_diag_matrix  |   |  3 |
+//                        +---+----+
+
+// -*- 1 -*-
+DiagMatrix
+xleftdiv (const DiagMatrix& a, const DiagMatrix& b)
+{ return dmdm_leftdiv_impl (a, b); }
+
+// -*- 2 -*-
+ComplexDiagMatrix
+xleftdiv (const DiagMatrix& a, const ComplexDiagMatrix& b)
+{ return dmdm_leftdiv_impl (a, b); }
+
+// -*- 3 -*-
+ComplexDiagMatrix
+xleftdiv (const ComplexDiagMatrix& a, const ComplexDiagMatrix& b)
+{ return dmdm_leftdiv_impl (a, b); }
+
+// Left division functions, float type.
+//
+//       op2 \ op1:         dm  cdm
+//                        +---+----+
+//   diag_matrix          | 1 |  2 |
+//                        +---+----+
+//   complex_diag_matrix  |   |  3 |
+//                        +---+----+
+
+// -*- 1 -*-
+FloatDiagMatrix
+xleftdiv (const FloatDiagMatrix& a, const FloatDiagMatrix& b)
+{ return dmdm_leftdiv_impl (a, b); }
+
+// -*- 2 -*-
+FloatComplexDiagMatrix
+xleftdiv (const FloatDiagMatrix& a, const FloatComplexDiagMatrix& b)
+{ return dmdm_leftdiv_impl (a, b); }
+
+// -*- 3 -*-
+FloatComplexDiagMatrix
+xleftdiv (const FloatComplexDiagMatrix& a, const FloatComplexDiagMatrix& b)
+{ return dmdm_leftdiv_impl (a, b); }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/xdiv.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,129 @@
+/*
+
+Copyright (C) 1993-2012 John W. Eaton
+Copyright (C) 2008 Jaroslav Hajek
+
+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/>.
+
+*/
+
+#if !defined (octave_xdiv_h)
+#define octave_xdiv_h 1
+
+#include "mx-defs.h"
+#include "MatrixType.h"
+
+extern Matrix xdiv (const Matrix& a, const Matrix& b, MatrixType &typ);
+extern ComplexMatrix xdiv (const Matrix& a, const ComplexMatrix& b,
+                           MatrixType &typ);
+extern ComplexMatrix xdiv (const ComplexMatrix& a, const Matrix& b,
+                           MatrixType &typ);
+extern ComplexMatrix xdiv (const ComplexMatrix& a, const ComplexMatrix& b,
+                           MatrixType &typ);
+
+extern Matrix x_el_div (double a, const Matrix& b);
+extern ComplexMatrix x_el_div (double a, const ComplexMatrix& b);
+extern ComplexMatrix x_el_div (const Complex a, const Matrix& b);
+extern ComplexMatrix x_el_div (const Complex a, const ComplexMatrix& b);
+
+extern NDArray x_el_div (double a, const NDArray& b);
+extern ComplexNDArray x_el_div (double a, const ComplexNDArray& b);
+extern ComplexNDArray x_el_div (const Complex a, const NDArray& b);
+extern ComplexNDArray x_el_div (const Complex a, const ComplexNDArray& b);
+
+extern Matrix xleftdiv (const Matrix& a, const Matrix& b, MatrixType &typ,
+                        blas_trans_type transt = blas_no_trans);
+extern ComplexMatrix xleftdiv (const Matrix& a, const ComplexMatrix& b,
+                               MatrixType &typ, blas_trans_type transt = blas_no_trans);
+extern ComplexMatrix xleftdiv (const ComplexMatrix& a, const Matrix& b,
+                               MatrixType &typ, blas_trans_type transt = blas_no_trans);
+extern ComplexMatrix xleftdiv (const ComplexMatrix& a, const ComplexMatrix& b,
+                               MatrixType &typ, blas_trans_type transt = blas_no_trans);
+
+extern FloatMatrix xdiv (const FloatMatrix& a, const FloatMatrix& b, MatrixType &typ);
+extern FloatComplexMatrix xdiv (const FloatMatrix& a, const FloatComplexMatrix& b,
+                           MatrixType &typ);
+extern FloatComplexMatrix xdiv (const FloatComplexMatrix& a, const FloatMatrix& b,
+                           MatrixType &typ);
+extern FloatComplexMatrix xdiv (const FloatComplexMatrix& a, const FloatComplexMatrix& b,
+                           MatrixType &typ);
+
+extern FloatMatrix x_el_div (float a, const FloatMatrix& b);
+extern FloatComplexMatrix x_el_div (float a, const FloatComplexMatrix& b);
+extern FloatComplexMatrix x_el_div (const FloatComplex a, const FloatMatrix& b);
+extern FloatComplexMatrix x_el_div (const FloatComplex a, const FloatComplexMatrix& b);
+
+extern FloatNDArray x_el_div (float a, const FloatNDArray& b);
+extern FloatComplexNDArray x_el_div (float a, const FloatComplexNDArray& b);
+extern FloatComplexNDArray x_el_div (const FloatComplex a, const FloatNDArray& b);
+extern FloatComplexNDArray x_el_div (const FloatComplex a, const FloatComplexNDArray& b);
+
+extern FloatMatrix xleftdiv (const FloatMatrix& a, const FloatMatrix& b, MatrixType &typ,
+                             blas_trans_type transt = blas_no_trans);
+extern FloatComplexMatrix xleftdiv (const FloatMatrix& a, const FloatComplexMatrix& b,
+                               MatrixType &typ, blas_trans_type transt = blas_no_trans);
+extern FloatComplexMatrix xleftdiv (const FloatComplexMatrix& a, const FloatMatrix& b,
+                               MatrixType &typ, blas_trans_type transt = blas_no_trans);
+extern FloatComplexMatrix xleftdiv (const FloatComplexMatrix& a, const FloatComplexMatrix& b,
+                               MatrixType &typ, blas_trans_type transt = blas_no_trans);
+
+
+extern Matrix xdiv (const Matrix& a, const DiagMatrix& b);
+extern ComplexMatrix xdiv (const ComplexMatrix& a, const DiagMatrix& b);
+extern ComplexMatrix xdiv (const ComplexMatrix& a, const ComplexDiagMatrix& b);
+
+extern DiagMatrix xdiv (const DiagMatrix& a, const DiagMatrix& b);
+extern ComplexDiagMatrix xdiv (const ComplexDiagMatrix& a, const DiagMatrix& b);
+extern ComplexDiagMatrix xdiv (const ComplexDiagMatrix& a, const ComplexDiagMatrix& b);
+
+extern FloatMatrix xdiv (const FloatMatrix& a, const FloatDiagMatrix& b);
+extern FloatComplexMatrix xdiv (const FloatComplexMatrix& a,
+                                const FloatDiagMatrix& b);
+extern FloatComplexMatrix xdiv (const FloatMatrix& a,
+                                const FloatComplexDiagMatrix& b);
+extern FloatComplexMatrix xdiv (const FloatComplexMatrix& a,
+                                const FloatComplexDiagMatrix& b);
+
+extern FloatDiagMatrix xdiv (const FloatDiagMatrix& a, const FloatDiagMatrix& b);
+extern FloatComplexDiagMatrix xdiv (const FloatComplexDiagMatrix& a,
+                                    const FloatDiagMatrix& b);
+extern FloatComplexDiagMatrix xdiv (const FloatComplexDiagMatrix& a,
+                                    const FloatComplexDiagMatrix& b);
+
+extern Matrix xleftdiv (const DiagMatrix& a, const Matrix& b);
+extern ComplexMatrix xleftdiv (const DiagMatrix& a, const ComplexMatrix& b);
+extern ComplexMatrix xleftdiv (const ComplexDiagMatrix& a, const ComplexMatrix& b);
+
+extern DiagMatrix xleftdiv (const DiagMatrix& a, const DiagMatrix& b);
+extern ComplexDiagMatrix xleftdiv (const DiagMatrix& a, const ComplexDiagMatrix& b);
+extern ComplexDiagMatrix xleftdiv (const ComplexDiagMatrix& a, const ComplexDiagMatrix& b);
+
+extern FloatMatrix xleftdiv (const FloatDiagMatrix& a,
+                             const FloatMatrix& b);
+extern FloatComplexMatrix xleftdiv (const FloatDiagMatrix& a,
+                                    const FloatComplexMatrix& b);
+extern FloatComplexMatrix xleftdiv (const FloatComplexDiagMatrix& a,
+                                    const FloatComplexMatrix& b);
+
+extern FloatDiagMatrix xleftdiv (const FloatDiagMatrix& a,
+                                 const FloatDiagMatrix& b);
+extern FloatComplexDiagMatrix xleftdiv (const FloatDiagMatrix& a,
+                                        const FloatComplexDiagMatrix& b);
+extern FloatComplexDiagMatrix xleftdiv (const FloatComplexDiagMatrix& a,
+                                        const FloatComplexDiagMatrix& b);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/xgl2ps.c	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,34 @@
+/*
+
+Copyright (C) 2009-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+// Wrapper for "imported" file gl2ps.c so that config.h will be included
+// before any other system or gnulib headers.
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#if defined (HAVE_OPENGL)
+
+#include "gl2ps.c"
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/xnorm.cc	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,212 @@
+/*
+
+Copyright (C) 2008-2012 VZLU Prague, a.s.
+
+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/>.
+
+*/
+
+// author: Jaroslav Hajek <highegg@gmail.com>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <cassert>
+#include <cfloat>
+#include <cmath>
+
+#include "oct-norm.h"
+
+#include "error.h"
+#include "xnorm.h"
+#include "ov.h"
+#include "gripes.h"
+
+octave_value xnorm (const octave_value& x, const octave_value& p)
+{
+  octave_value retval;
+
+  bool isvector = (x.columns () == 1 || x.rows () == 1);
+  bool iscomplex = x.is_complex_type ();
+  bool issparse = x.is_sparse_type ();
+  bool isfloat = x.is_single_type ();
+
+  if (isfloat || x.is_double_type ())
+    {
+      if (isvector)
+        {
+          if (isfloat & iscomplex)
+            retval = xnorm (x.float_complex_column_vector_value (),
+                            p.float_value ());
+          else if (isfloat)
+            retval = xnorm (x.float_column_vector_value (),
+                            p.float_value ());
+          else if (iscomplex)
+            retval = xnorm (x.complex_column_vector_value (),
+                            p.double_value ());
+          else
+            retval = xnorm (x.column_vector_value (),
+                            p.double_value ());
+        }
+      else if (issparse)
+        {
+          if (iscomplex)
+            retval = xnorm (x.sparse_complex_matrix_value (),
+                            p.double_value ());
+          else
+            retval = xnorm (x.sparse_matrix_value (),
+                            p.double_value ());
+        }
+      else
+        {
+          if (isfloat & iscomplex)
+            retval = xnorm (x.float_complex_matrix_value (),
+                            p.float_value ());
+          else if (isfloat)
+            retval = xnorm (x.float_matrix_value (),
+                            p.float_value ());
+          else if (iscomplex)
+            retval = xnorm (x.complex_matrix_value (),
+                            p.double_value ());
+          else
+            retval = xnorm (x.matrix_value (),
+                            p.double_value ());
+        }
+    }
+  else
+    gripe_wrong_type_arg ("xnorm", x, true);
+
+  return retval;
+}
+
+octave_value xcolnorms (const octave_value& x, const octave_value& p)
+{
+  octave_value retval;
+
+  bool iscomplex = x.is_complex_type ();
+  bool issparse = x.is_sparse_type ();
+  bool isfloat = x.is_single_type ();
+
+  if (isfloat || x.is_double_type ())
+    {
+      if (issparse)
+        {
+          if (iscomplex)
+            retval = xcolnorms (x.sparse_complex_matrix_value (),
+                                p.double_value ());
+          else
+            retval = xcolnorms (x.sparse_matrix_value (),
+                                p.double_value ());
+        }
+      else
+        {
+          if (isfloat & iscomplex)
+            retval = xcolnorms (x.float_complex_matrix_value (),
+                                p.float_value ());
+          else if (isfloat)
+            retval = xcolnorms (x.float_matrix_value (),
+                                p.float_value ());
+          else if (iscomplex)
+            retval = xcolnorms (x.complex_matrix_value (),
+                                p.double_value ());
+          else
+            retval = xcolnorms (x.matrix_value (),
+                                p.double_value ());
+        }
+    }
+  else
+    gripe_wrong_type_arg ("xcolnorms", x, true);
+
+  return retval;
+}
+
+octave_value xrownorms (const octave_value& x, const octave_value& p)
+{
+  octave_value retval;
+
+  bool iscomplex = x.is_complex_type ();
+  bool issparse = x.is_sparse_type ();
+  bool isfloat = x.is_single_type ();
+
+  if (isfloat || x.is_double_type ())
+    {
+      if (issparse)
+        {
+          if (iscomplex)
+            retval = xrownorms (x.sparse_complex_matrix_value (),
+                                p.double_value ());
+          else
+            retval = xrownorms (x.sparse_matrix_value (),
+                                p.double_value ());
+        }
+      else
+        {
+          if (isfloat & iscomplex)
+            retval = xrownorms (x.float_complex_matrix_value (),
+                                p.float_value ());
+          else if (isfloat)
+            retval = xrownorms (x.float_matrix_value (),
+                                p.float_value ());
+          else if (iscomplex)
+            retval = xrownorms (x.complex_matrix_value (),
+                                p.double_value ());
+          else
+            retval = xrownorms (x.matrix_value (),
+                                p.double_value ());
+        }
+    }
+  else
+    gripe_wrong_type_arg ("xrownorms", x, true);
+
+  return retval;
+}
+
+octave_value xfrobnorm (const octave_value& x)
+{
+  octave_value retval;
+
+  bool iscomplex = x.is_complex_type ();
+  bool issparse = x.is_sparse_type ();
+  bool isfloat = x.is_single_type ();
+
+  if (isfloat || x.is_double_type ())
+    {
+      if (issparse)
+        {
+          if (iscomplex)
+            retval = xfrobnorm (x.sparse_complex_matrix_value ());
+          else
+            retval = xfrobnorm (x.sparse_matrix_value ());
+        }
+      else
+        {
+          if (isfloat & iscomplex)
+            retval = xfrobnorm (x.float_complex_matrix_value ());
+          else if (isfloat)
+            retval = xfrobnorm (x.float_matrix_value ());
+          else if (iscomplex)
+            retval = xfrobnorm (x.complex_matrix_value ());
+          else
+            retval = xfrobnorm (x.matrix_value ());
+        }
+    }
+  else
+    gripe_wrong_type_arg ("xfrobnorm", x, true);
+
+  return retval;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/xnorm.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,37 @@
+/*
+
+Copyright (C) 2008-2012 VZLU Prague, a.s.
+
+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/>.
+
+*/
+
+// author: Jaroslav Hajek <highegg@gmail.com>
+
+#if !defined (octave_xnorm_h)
+#define octave_xnorm_h 1
+
+#include "oct-norm.h"
+
+class octave_value;
+
+extern OCTINTERP_API octave_value xnorm (const octave_value& x, const octave_value& p);
+extern OCTINTERP_API octave_value xcolnorms (const octave_value& x, const octave_value& p);
+extern OCTINTERP_API octave_value xrownorms (const octave_value& x, const octave_value& p);
+extern OCTINTERP_API octave_value xfrobnorm (const octave_value& x);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/xpow.cc	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,2858 @@
+/*
+
+Copyright (C) 1993-2012 John W. Eaton
+Copyright (C) 2009-2010 VZLU Prague
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <cassert>
+#include <climits>
+
+#include "Array-util.h"
+#include "CColVector.h"
+#include "CDiagMatrix.h"
+#include "fCDiagMatrix.h"
+#include "CMatrix.h"
+#include "EIG.h"
+#include "fEIG.h"
+#include "dDiagMatrix.h"
+#include "fDiagMatrix.h"
+#include "dMatrix.h"
+#include "PermMatrix.h"
+#include "mx-cm-cdm.h"
+#include "oct-cmplx.h"
+#include "Range.h"
+#include "quit.h"
+
+#include "error.h"
+#include "oct-obj.h"
+#include "utils.h"
+#include "xpow.h"
+
+#include "bsxfun.h"
+
+#ifdef _OPENMP
+#include <omp.h>
+#endif
+
+static inline int
+xisint (double x)
+{
+  return (D_NINT (x) == x
+          && ((x >= 0 && x < INT_MAX)
+              || (x <= 0 && x > INT_MIN)));
+}
+
+// Safer pow functions.
+//
+//       op2 \ op1:   s   m   cs   cm
+//            +--   +---+---+----+----+
+//   scalar   |     | 1 | 5 |  7 | 11 |
+//                  +---+---+----+----+
+//   matrix         | 2 | * |  8 |  * |
+//                  +---+---+----+----+
+//   complex_scalar | 3 | 6 |  9 | 12 |
+//                  +---+---+----+----+
+//   complex_matrix | 4 | * | 10 |  * |
+//                  +---+---+----+----+
+
+// -*- 1 -*-
+octave_value
+xpow (double a, double b)
+{
+  double retval;
+
+  if (a < 0.0 && ! xisint (b))
+    {
+      Complex atmp (a);
+
+      return std::pow (atmp, b);
+    }
+  else
+    retval = std::pow (a, b);
+
+  return retval;
+}
+
+// -*- 2 -*-
+octave_value
+xpow (double a, const Matrix& b)
+{
+  octave_value retval;
+
+  octave_idx_type nr = b.rows ();
+  octave_idx_type nc = b.cols ();
+
+  if (nr == 0 || nc == 0 || nr != nc)
+    error ("for x^A, A must be a square matrix");
+  else
+    {
+      EIG b_eig (b);
+
+      if (! error_state)
+        {
+          ComplexColumnVector lambda (b_eig.eigenvalues ());
+          ComplexMatrix Q (b_eig.eigenvectors ());
+
+          for (octave_idx_type i = 0; i < nr; i++)
+            {
+              Complex elt = lambda(i);
+              if (std::imag (elt) == 0.0)
+                lambda(i) = std::pow (a, std::real (elt));
+              else
+                lambda(i) = std::pow (a, elt);
+            }
+          ComplexDiagMatrix D (lambda);
+
+          ComplexMatrix C = Q * D * Q.inverse ();
+          if (a > 0)
+            retval = real (C);
+          else
+            retval = C;
+        }
+      else
+        error ("xpow: matrix diagonalization failed");
+    }
+
+  return retval;
+}
+
+// -*- 3 -*-
+octave_value
+xpow (double a, const Complex& b)
+{
+  Complex result = std::pow (a, b);
+  return result;
+}
+
+// -*- 4 -*-
+octave_value
+xpow (double a, const ComplexMatrix& b)
+{
+  octave_value retval;
+
+  octave_idx_type nr = b.rows ();
+  octave_idx_type nc = b.cols ();
+
+  if (nr == 0 || nc == 0 || nr != nc)
+    error ("for x^A, A must be a square matrix");
+  else
+    {
+      EIG b_eig (b);
+
+      if (! error_state)
+        {
+          ComplexColumnVector lambda (b_eig.eigenvalues ());
+          ComplexMatrix Q (b_eig.eigenvectors ());
+
+          for (octave_idx_type i = 0; i < nr; i++)
+            {
+              Complex elt = lambda(i);
+              if (std::imag (elt) == 0.0)
+                lambda(i) = std::pow (a, std::real (elt));
+              else
+                lambda(i) = std::pow (a, elt);
+            }
+          ComplexDiagMatrix D (lambda);
+
+          retval = ComplexMatrix (Q * D * Q.inverse ());
+        }
+      else
+        error ("xpow: matrix diagonalization failed");
+    }
+
+  return retval;
+}
+
+// -*- 5 -*-
+octave_value
+xpow (const Matrix& a, double b)
+{
+  octave_value retval;
+
+  octave_idx_type nr = a.rows ();
+  octave_idx_type nc = a.cols ();
+
+  if (nr == 0 || nc == 0 || nr != nc)
+    error ("for A^b, A must be a square matrix");
+  else
+    {
+      if (static_cast<int> (b) == b)
+        {
+          int btmp = static_cast<int> (b);
+          if (btmp == 0)
+            {
+              retval = DiagMatrix (nr, nr, 1.0);
+            }
+          else
+            {
+              // Too much copying?
+              // FIXME -- we shouldn't do this if the exponent is
+              // large...
+
+              Matrix atmp;
+              if (btmp < 0)
+                {
+                  btmp = -btmp;
+
+                  octave_idx_type info;
+                  double rcond = 0.0;
+                  MatrixType mattype (a);
+
+                  atmp = a.inverse (mattype, info, rcond, 1);
+
+                  if (info == -1)
+                    warning ("inverse: matrix singular to machine\
+ precision, rcond = %g", rcond);
+                }
+              else
+                atmp = a;
+
+              Matrix result (atmp);
+
+              btmp--;
+
+              while (btmp > 0)
+                {
+                  if (btmp & 1)
+                    result = result * atmp;
+
+                  btmp >>= 1;
+
+                  if (btmp > 0)
+                    atmp = atmp * atmp;
+                }
+
+              retval = result;
+            }
+        }
+      else
+        {
+          EIG a_eig (a);
+
+          if (! error_state)
+            {
+              ComplexColumnVector lambda (a_eig.eigenvalues ());
+              ComplexMatrix Q (a_eig.eigenvectors ());
+
+              for (octave_idx_type i = 0; i < nr; i++)
+                lambda(i) = std::pow (lambda(i), b);
+
+              ComplexDiagMatrix D (lambda);
+
+              retval = ComplexMatrix (Q * D * Q.inverse ());
+            }
+          else
+            error ("xpow: matrix diagonalization failed");
+        }
+    }
+
+  return retval;
+}
+
+// -*- 5d -*-
+octave_value
+xpow (const DiagMatrix& a, double b)
+{
+  octave_value retval;
+
+  octave_idx_type nr = a.rows ();
+  octave_idx_type nc = a.cols ();
+
+  if (nr == 0 || nc == 0 || nr != nc)
+    error ("for A^b, A must be a square matrix");
+  else
+    {
+      if (static_cast<int> (b) == b)
+        {
+          DiagMatrix r (nr, nc);
+          for (octave_idx_type i = 0; i < nc; i++)
+            r.dgelem (i) = std::pow (a.dgelem (i), b);
+          retval = r;
+        }
+      else
+        {
+          ComplexDiagMatrix r (nr, nc);
+          for (octave_idx_type i = 0; i < nc; i++)
+            r.dgelem (i) = std::pow (static_cast<Complex> (a.dgelem (i)), b);
+          retval = r;
+        }
+    }
+
+  return retval;
+}
+
+// -*- 5p -*-
+octave_value
+xpow (const PermMatrix& a, double b)
+{
+  octave_value retval;
+  int btmp = static_cast<int> (b);
+  if (btmp == b)
+    return a.power (btmp);
+  else
+    return xpow (Matrix (a), b);
+}
+
+// -*- 6 -*-
+octave_value
+xpow (const Matrix& a, const Complex& b)
+{
+  octave_value retval;
+
+  octave_idx_type nr = a.rows ();
+  octave_idx_type nc = a.cols ();
+
+  if (nr == 0 || nc == 0 || nr != nc)
+    error ("for A^b, A must be a square matrix");
+  else
+    {
+      EIG a_eig (a);
+
+      if (! error_state)
+        {
+          ComplexColumnVector lambda (a_eig.eigenvalues ());
+          ComplexMatrix Q (a_eig.eigenvectors ());
+
+          for (octave_idx_type i = 0; i < nr; i++)
+            lambda(i) = std::pow (lambda(i), b);
+
+          ComplexDiagMatrix D (lambda);
+
+          retval = ComplexMatrix (Q * D * Q.inverse ());
+        }
+      else
+        error ("xpow: matrix diagonalization failed");
+    }
+
+  return retval;
+}
+
+// -*- 7 -*-
+octave_value
+xpow (const Complex& a, double b)
+{
+  Complex result;
+
+  if (xisint (b))
+    result = std::pow (a, static_cast<int> (b));
+  else
+    result = std::pow (a, b);
+
+  return result;
+}
+
+// -*- 8 -*-
+octave_value
+xpow (const Complex& a, const Matrix& b)
+{
+  octave_value retval;
+
+  octave_idx_type nr = b.rows ();
+  octave_idx_type nc = b.cols ();
+
+  if (nr == 0 || nc == 0 || nr != nc)
+    error ("for x^A, A must be a square matrix");
+  else
+    {
+      EIG b_eig (b);
+
+      if (! error_state)
+        {
+          ComplexColumnVector lambda (b_eig.eigenvalues ());
+          ComplexMatrix Q (b_eig.eigenvectors ());
+
+          for (octave_idx_type i = 0; i < nr; i++)
+            {
+              Complex elt = lambda(i);
+              if (std::imag (elt) == 0.0)
+                lambda(i) = std::pow (a, std::real (elt));
+              else
+                lambda(i) = std::pow (a, elt);
+            }
+          ComplexDiagMatrix D (lambda);
+
+          retval = ComplexMatrix (Q * D * Q.inverse ());
+        }
+      else
+        error ("xpow: matrix diagonalization failed");
+    }
+
+  return retval;
+}
+
+// -*- 9 -*-
+octave_value
+xpow (const Complex& a, const Complex& b)
+{
+  Complex result;
+  result = std::pow (a, b);
+  return result;
+}
+
+// -*- 10 -*-
+octave_value
+xpow (const Complex& a, const ComplexMatrix& b)
+{
+  octave_value retval;
+
+  octave_idx_type nr = b.rows ();
+  octave_idx_type nc = b.cols ();
+
+  if (nr == 0 || nc == 0 || nr != nc)
+    error ("for x^A, A must be a square matrix");
+  else
+    {
+      EIG b_eig (b);
+
+      if (! error_state)
+        {
+          ComplexColumnVector lambda (b_eig.eigenvalues ());
+          ComplexMatrix Q (b_eig.eigenvectors ());
+
+          for (octave_idx_type i = 0; i < nr; i++)
+            {
+              Complex elt = lambda(i);
+              if (std::imag (elt) == 0.0)
+                lambda(i) = std::pow (a, std::real (elt));
+              else
+                lambda(i) = std::pow (a, elt);
+            }
+          ComplexDiagMatrix D (lambda);
+
+          retval = ComplexMatrix (Q * D * Q.inverse ());
+        }
+      else
+        error ("xpow: matrix diagonalization failed");
+    }
+
+  return retval;
+}
+
+// -*- 11 -*-
+octave_value
+xpow (const ComplexMatrix& a, double b)
+{
+  octave_value retval;
+
+  octave_idx_type nr = a.rows ();
+  octave_idx_type nc = a.cols ();
+
+  if (nr == 0 || nc == 0 || nr != nc)
+    error ("for A^b, A must be a square matrix");
+  else
+    {
+      if (static_cast<int> (b) == b)
+        {
+          int btmp = static_cast<int> (b);
+          if (btmp == 0)
+            {
+              retval = DiagMatrix (nr, nr, 1.0);
+            }
+          else
+            {
+              // Too much copying?
+              // FIXME -- we shouldn't do this if the exponent is
+              // large...
+
+              ComplexMatrix atmp;
+              if (btmp < 0)
+                {
+                  btmp = -btmp;
+
+                  octave_idx_type info;
+                  double rcond = 0.0;
+                  MatrixType mattype (a);
+
+                  atmp = a.inverse (mattype, info, rcond, 1);
+
+                  if (info == -1)
+                    warning ("inverse: matrix singular to machine\
+ precision, rcond = %g", rcond);
+                }
+              else
+                atmp = a;
+
+              ComplexMatrix result (atmp);
+
+              btmp--;
+
+              while (btmp > 0)
+                {
+                  if (btmp & 1)
+                    result = result * atmp;
+
+                  btmp >>= 1;
+
+                  if (btmp > 0)
+                    atmp = atmp * atmp;
+                }
+
+              retval = result;
+            }
+        }
+      else
+        {
+          EIG a_eig (a);
+
+          if (! error_state)
+            {
+              ComplexColumnVector lambda (a_eig.eigenvalues ());
+              ComplexMatrix Q (a_eig.eigenvectors ());
+
+              for (octave_idx_type i = 0; i < nr; i++)
+                lambda(i) = std::pow (lambda(i), b);
+
+              ComplexDiagMatrix D (lambda);
+
+              retval = ComplexMatrix (Q * D * Q.inverse ());
+            }
+          else
+            error ("xpow: matrix diagonalization failed");
+        }
+    }
+
+  return retval;
+}
+
+// -*- 12 -*-
+octave_value
+xpow (const ComplexMatrix& a, const Complex& b)
+{
+  octave_value retval;
+
+  octave_idx_type nr = a.rows ();
+  octave_idx_type nc = a.cols ();
+
+  if (nr == 0 || nc == 0 || nr != nc)
+    error ("for A^b, A must be a square matrix");
+  else
+    {
+      EIG a_eig (a);
+
+      if (! error_state)
+        {
+          ComplexColumnVector lambda (a_eig.eigenvalues ());
+          ComplexMatrix Q (a_eig.eigenvectors ());
+
+          for (octave_idx_type i = 0; i < nr; i++)
+            lambda(i) = std::pow (lambda(i), b);
+
+          ComplexDiagMatrix D (lambda);
+
+          retval = ComplexMatrix (Q * D * Q.inverse ());
+        }
+      else
+        error ("xpow: matrix diagonalization failed");
+    }
+
+  return retval;
+}
+
+// -*- 12d -*-
+octave_value
+xpow (const ComplexDiagMatrix& a, const Complex& b)
+{
+  octave_value retval;
+
+  octave_idx_type nr = a.rows ();
+  octave_idx_type nc = a.cols ();
+
+  if (nr == 0 || nc == 0 || nr != nc)
+    error ("for A^b, A must be a square matrix");
+  else
+    {
+      ComplexDiagMatrix r (nr, nc);
+      for (octave_idx_type i = 0; i < nc; i++)
+        r(i, i) = std::pow (a(i, i), b);
+      retval = r;
+    }
+
+  return retval;
+}
+
+// mixed
+octave_value
+xpow (const ComplexDiagMatrix& a, double b)
+{
+  return xpow (a, static_cast<Complex> (b));
+}
+
+octave_value
+xpow (const DiagMatrix& a, const Complex& b)
+{
+  return xpow (ComplexDiagMatrix (a), b);
+}
+
+
+// Safer pow functions that work elementwise for matrices.
+//
+//       op2 \ op1:   s   m   cs   cm
+//            +--   +---+---+----+----+
+//   scalar   |     | * | 3 |  * |  9 |
+//                  +---+---+----+----+
+//   matrix         | 1 | 4 |  7 | 10 |
+//                  +---+---+----+----+
+//   complex_scalar | * | 5 |  * | 11 |
+//                  +---+---+----+----+
+//   complex_matrix | 2 | 6 |  8 | 12 |
+//                  +---+---+----+----+
+//
+//   * -> not needed.
+
+// FIXME -- these functions need to be fixed so that things
+// like
+//
+//   a = -1; b = [ 0, 0.5, 1 ]; r = a .^ b
+//
+// and
+//
+//   a = -1; b = [ 0, 0.5, 1 ]; for i = 1:3, r(i) = a .^ b(i), end
+//
+// produce identical results.  Also, it would be nice if -1^0.5
+// produced a pure imaginary result instead of a complex number with a
+// small real part.  But perhaps that's really a problem with the math
+// library...
+
+// -*- 1 -*-
+octave_value
+elem_xpow (double a, const Matrix& b)
+{
+  octave_value retval;
+
+  octave_idx_type nr = b.rows ();
+  octave_idx_type nc = b.cols ();
+
+  double d1, d2;
+
+  if (a < 0.0 && ! b.all_integers (d1, d2))
+    {
+      Complex atmp (a);
+      ComplexMatrix result (nr, nc);
+
+      for (octave_idx_type j = 0; j < nc; j++)
+        for (octave_idx_type i = 0; i < nr; i++)
+          {
+            octave_quit ();
+            result (i, j) = std::pow (atmp, b (i, j));
+          }
+
+      retval = result;
+    }
+  else
+    {
+      Matrix result (nr, nc);
+
+      for (octave_idx_type j = 0; j < nc; j++)
+        for (octave_idx_type i = 0; i < nr; i++)
+          {
+            octave_quit ();
+            result (i, j) = std::pow (a, b (i, j));
+          }
+
+      retval = result;
+    }
+
+  return retval;
+}
+
+// -*- 2 -*-
+octave_value
+elem_xpow (double a, const ComplexMatrix& b)
+{
+  octave_idx_type nr = b.rows ();
+  octave_idx_type nc = b.cols ();
+
+  ComplexMatrix result (nr, nc);
+  Complex atmp (a);
+
+  for (octave_idx_type j = 0; j < nc; j++)
+    for (octave_idx_type i = 0; i < nr; i++)
+      {
+        octave_quit ();
+        result (i, j) = std::pow (atmp, b (i, j));
+      }
+
+  return result;
+}
+
+static inline bool
+same_sign (double a, double b)
+{
+  return (a >= 0 && b >= 0) || (a <= 0 && b <= 0);
+}
+
+octave_value
+elem_xpow (double a, const Range& r)
+{
+  octave_value retval;
+
+  // Only optimize powers with ranges that are integer and monotonic in
+  // magnitude.
+  if (r.nelem () > 1 && r.all_elements_are_ints ()
+      && same_sign (r.base (), r.limit ()))
+    {
+      octave_idx_type n = r.nelem ();
+      Matrix result (1, n);
+      if (same_sign (r.base (), r.inc ()))
+        {
+          double base = std::pow (a, r.base ());
+          double inc = std::pow (a, r.inc ());
+          result(0) = base;
+          for (octave_idx_type i = 1; i < n; i++)
+            result(i) = (base *= inc);
+        }
+      else
+        {
+          // Don't use Range::limit () here.
+          double limit = std::pow (a, r.base () + (n-1) * r.inc ());
+          double inc = std::pow (a, -r.inc ());
+          result(n-1) = limit;
+          for (octave_idx_type i = n-2; i >= 0; i--)
+            result(i) = (limit *= inc);
+        }
+
+      retval = result;
+    }
+  else
+    retval = elem_xpow (a, r.matrix_value ());
+
+  return retval;
+}
+
+// -*- 3 -*-
+octave_value
+elem_xpow (const Matrix& a, double b)
+{
+  octave_value retval;
+
+  octave_idx_type nr = a.rows ();
+  octave_idx_type nc = a.cols ();
+
+  if (! xisint (b) && a.any_element_is_negative ())
+    {
+      ComplexMatrix result (nr, nc);
+
+      for (octave_idx_type j = 0; j < nc; j++)
+        for (octave_idx_type i = 0; i < nr; i++)
+          {
+            octave_quit ();
+
+            Complex atmp (a (i, j));
+
+            result (i, j) = std::pow (atmp, b);
+          }
+
+      retval = result;
+    }
+  else
+    {
+      Matrix result (nr, nc);
+
+      for (octave_idx_type j = 0; j < nc; j++)
+        for (octave_idx_type i = 0; i < nr; i++)
+          {
+            octave_quit ();
+            result (i, j) = std::pow (a (i, j), b);
+          }
+
+      retval = result;
+    }
+
+  return retval;
+}
+
+// -*- 4 -*-
+octave_value
+elem_xpow (const Matrix& a, const Matrix& b)
+{
+  octave_value retval;
+
+  octave_idx_type nr = a.rows ();
+  octave_idx_type nc = a.cols ();
+
+  octave_idx_type b_nr = b.rows ();
+  octave_idx_type b_nc = b.cols ();
+
+  if (nr != b_nr || nc != b_nc)
+    {
+      gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc);
+      return octave_value ();
+    }
+
+  int convert_to_complex = 0;
+  for (octave_idx_type j = 0; j < nc; j++)
+    for (octave_idx_type i = 0; i < nr; i++)
+      {
+        octave_quit ();
+        double atmp = a (i, j);
+        double btmp = b (i, j);
+        if (atmp < 0.0 && static_cast<int> (btmp) != btmp)
+          {
+            convert_to_complex = 1;
+            goto done;
+          }
+      }
+
+done:
+
+  if (convert_to_complex)
+    {
+      ComplexMatrix complex_result (nr, nc);
+
+      for (octave_idx_type j = 0; j < nc; j++)
+        for (octave_idx_type i = 0; i < nr; i++)
+          {
+            octave_quit ();
+            Complex atmp (a (i, j));
+            Complex btmp (b (i, j));
+            complex_result (i, j) = std::pow (atmp, btmp);
+          }
+
+      retval = complex_result;
+    }
+  else
+    {
+      Matrix result (nr, nc);
+
+      for (octave_idx_type j = 0; j < nc; j++)
+        for (octave_idx_type i = 0; i < nr; i++)
+          {
+            octave_quit ();
+            result (i, j) = std::pow (a (i, j), b (i, j));
+          }
+
+      retval = result;
+    }
+
+  return retval;
+}
+
+// -*- 5 -*-
+octave_value
+elem_xpow (const Matrix& a, const Complex& b)
+{
+  octave_idx_type nr = a.rows ();
+  octave_idx_type nc = a.cols ();
+
+  ComplexMatrix result (nr, nc);
+
+  for (octave_idx_type j = 0; j < nc; j++)
+    for (octave_idx_type i = 0; i < nr; i++)
+      {
+        octave_quit ();
+        result (i, j) = std::pow (Complex (a (i, j)), b);
+      }
+
+  return result;
+}
+
+// -*- 6 -*-
+octave_value
+elem_xpow (const Matrix& a, const ComplexMatrix& b)
+{
+  octave_idx_type nr = a.rows ();
+  octave_idx_type nc = a.cols ();
+
+  octave_idx_type b_nr = b.rows ();
+  octave_idx_type b_nc = b.cols ();
+
+  if (nr != b_nr || nc != b_nc)
+    {
+      gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc);
+      return octave_value ();
+    }
+
+  ComplexMatrix result (nr, nc);
+
+  for (octave_idx_type j = 0; j < nc; j++)
+    for (octave_idx_type i = 0; i < nr; i++)
+      {
+        octave_quit ();
+        result (i, j) = std::pow (Complex (a (i, j)), b (i, j));
+      }
+
+  return result;
+}
+
+// -*- 7 -*-
+octave_value
+elem_xpow (const Complex& a, const Matrix& b)
+{
+  octave_idx_type nr = b.rows ();
+  octave_idx_type nc = b.cols ();
+
+  ComplexMatrix result (nr, nc);
+
+  for (octave_idx_type j = 0; j < nc; j++)
+    for (octave_idx_type i = 0; i < nr; i++)
+      {
+        octave_quit ();
+        double btmp = b (i, j);
+        if (xisint (btmp))
+          result (i, j) = std::pow (a, static_cast<int> (btmp));
+        else
+          result (i, j) = std::pow (a, btmp);
+      }
+
+  return result;
+}
+
+// -*- 8 -*-
+octave_value
+elem_xpow (const Complex& a, const ComplexMatrix& b)
+{
+  octave_idx_type nr = b.rows ();
+  octave_idx_type nc = b.cols ();
+
+  ComplexMatrix result (nr, nc);
+
+  for (octave_idx_type j = 0; j < nc; j++)
+    for (octave_idx_type i = 0; i < nr; i++)
+      {
+        octave_quit ();
+        result (i, j) = std::pow (a, b (i, j));
+      }
+
+  return result;
+}
+
+octave_value
+elem_xpow (const Complex& a, const Range& r)
+{
+  octave_value retval;
+
+  // Only optimize powers with ranges that are integer and monotonic in
+  // magnitude.
+  if (r.nelem () > 1 && r.all_elements_are_ints ()
+      && same_sign (r.base (), r.limit ()))
+    {
+      octave_idx_type n = r.nelem ();
+      ComplexMatrix result (1, n);
+
+      if (same_sign (r.base (), r.inc ()))
+        {
+          Complex base = std::pow (a, r.base ());
+          Complex inc = std::pow (a, r.inc ());
+          result(0) = base;
+          for (octave_idx_type i = 1; i < n; i++)
+            result(i) = (base *= inc);
+        }
+      else
+        {
+          // Don't use Range::limit () here.
+          Complex limit = std::pow (a, r.base () + (n-1) * r.inc ());
+          Complex inc = std::pow (a, -r.inc ());
+          result(n-1) = limit;
+          for (octave_idx_type i = n-2; i >= 0; i--)
+            result(i) = (limit *= inc);
+        }
+
+      retval = result;
+    }
+  else
+    retval = elem_xpow (a, r.matrix_value ());
+
+
+  return retval;
+}
+
+// -*- 9 -*-
+octave_value
+elem_xpow (const ComplexMatrix& a, double b)
+{
+  octave_idx_type nr = a.rows ();
+  octave_idx_type nc = a.cols ();
+
+  ComplexMatrix result (nr, nc);
+
+  if (xisint (b))
+    {
+      for (octave_idx_type j = 0; j < nc; j++)
+        for (octave_idx_type i = 0; i < nr; i++)
+          {
+            octave_quit ();
+            result (i, j) = std::pow (a (i, j), static_cast<int> (b));
+          }
+    }
+  else
+    {
+      for (octave_idx_type j = 0; j < nc; j++)
+        for (octave_idx_type i = 0; i < nr; i++)
+          {
+            octave_quit ();
+            result (i, j) = std::pow (a (i, j), b);
+          }
+    }
+
+  return result;
+}
+
+// -*- 10 -*-
+octave_value
+elem_xpow (const ComplexMatrix& a, const Matrix& b)
+{
+  octave_idx_type nr = a.rows ();
+  octave_idx_type nc = a.cols ();
+
+  octave_idx_type b_nr = b.rows ();
+  octave_idx_type b_nc = b.cols ();
+
+  if (nr != b_nr || nc != b_nc)
+    {
+      gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc);
+      return octave_value ();
+    }
+
+  ComplexMatrix result (nr, nc);
+
+  for (octave_idx_type j = 0; j < nc; j++)
+    for (octave_idx_type i = 0; i < nr; i++)
+      {
+        octave_quit ();
+        double btmp = b (i, j);
+        if (xisint (btmp))
+          result (i, j) = std::pow (a (i, j), static_cast<int> (btmp));
+        else
+          result (i, j) = std::pow (a (i, j), btmp);
+      }
+
+  return result;
+}
+
+// -*- 11 -*-
+octave_value
+elem_xpow (const ComplexMatrix& a, const Complex& b)
+{
+  octave_idx_type nr = a.rows ();
+  octave_idx_type nc = a.cols ();
+
+  ComplexMatrix result (nr, nc);
+
+  for (octave_idx_type j = 0; j < nc; j++)
+    for (octave_idx_type i = 0; i < nr; i++)
+      {
+        octave_quit ();
+        result (i, j) = std::pow (a (i, j), b);
+      }
+
+  return result;
+}
+
+// -*- 12 -*-
+octave_value
+elem_xpow (const ComplexMatrix& a, const ComplexMatrix& b)
+{
+  octave_idx_type nr = a.rows ();
+  octave_idx_type nc = a.cols ();
+
+  octave_idx_type b_nr = b.rows ();
+  octave_idx_type b_nc = b.cols ();
+
+  if (nr != b_nr || nc != b_nc)
+    {
+      gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc);
+      return octave_value ();
+    }
+
+  ComplexMatrix result (nr, nc);
+
+  for (octave_idx_type j = 0; j < nc; j++)
+    for (octave_idx_type i = 0; i < nr; i++)
+      {
+        octave_quit ();
+        result (i, j) = std::pow (a (i, j), b (i, j));
+      }
+
+  return result;
+}
+
+// Safer pow functions that work elementwise for N-d arrays.
+//
+//       op2 \ op1:   s   nd  cs   cnd
+//            +--   +---+---+----+----+
+//   scalar   |     | * | 3 |  * |  9 |
+//                  +---+---+----+----+
+//   N_d            | 1 | 4 |  7 | 10 |
+//                  +---+---+----+----+
+//   complex_scalar | * | 5 |  * | 11 |
+//                  +---+---+----+----+
+//   complex_N_d    | 2 | 6 |  8 | 12 |
+//                  +---+---+----+----+
+//
+//   * -> not needed.
+
+// FIXME -- these functions need to be fixed so that things
+// like
+//
+//   a = -1; b = [ 0, 0.5, 1 ]; r = a .^ b
+//
+// and
+//
+//   a = -1; b = [ 0, 0.5, 1 ]; for i = 1:3, r(i) = a .^ b(i), end
+//
+// produce identical results.  Also, it would be nice if -1^0.5
+// produced a pure imaginary result instead of a complex number with a
+// small real part.  But perhaps that's really a problem with the math
+// library...
+
+// -*- 1 -*-
+octave_value
+elem_xpow (double a, const NDArray& b)
+{
+  octave_value retval;
+
+  if (a < 0.0 && ! b.all_integers ())
+    {
+      Complex atmp (a);
+      ComplexNDArray result (b.dims ());
+      for (octave_idx_type i = 0; i < b.length (); i++)
+        {
+          octave_quit ();
+          result(i) = std::pow (atmp, b(i));
+        }
+
+      retval = result;
+    }
+  else
+    {
+      NDArray result (b.dims ());
+      for (octave_idx_type i = 0; i < b.length (); i++)
+        {
+          octave_quit ();
+          result (i) = std::pow (a, b(i));
+        }
+
+      retval = result;
+    }
+
+  return retval;
+}
+
+// -*- 2 -*-
+octave_value
+elem_xpow (double a, const ComplexNDArray& b)
+{
+  ComplexNDArray result (b.dims ());
+
+  for (octave_idx_type i = 0; i < b.length (); i++)
+    {
+      octave_quit ();
+      result(i) = std::pow (a, b(i));
+    }
+
+  return result;
+}
+
+// -*- 3 -*-
+octave_value
+elem_xpow (const NDArray& a, double b)
+{
+  octave_value retval;
+
+  if (! xisint (b))
+    {
+      if (a.any_element_is_negative ())
+        {
+          ComplexNDArray result (a.dims ());
+
+          for (octave_idx_type i = 0; i < a.length (); i++)
+            {
+              octave_quit ();
+
+              Complex atmp (a (i));
+
+              result(i) = std::pow (atmp, b);
+            }
+
+          retval = result;
+        }
+      else
+        {
+          NDArray result (a.dims ());
+          for (octave_idx_type i = 0; i < a.length (); i++)
+            {
+              octave_quit ();
+              result(i) = std::pow (a(i), b);
+            }
+
+          retval = result;
+        }
+    }
+  else
+    {
+      NoAlias<NDArray> result (a.dims ());
+
+      int ib = static_cast<int> (b);
+      if (ib == 2)
+        {
+          for (octave_idx_type i = 0; i < a.length (); i++)
+            result(i) = a(i) * a(i);
+        }
+      else if (ib == 3)
+        {
+          for (octave_idx_type i = 0; i < a.length (); i++)
+            result(i) = a(i) * a(i) * a(i);
+        }
+      else if (ib == -1)
+        {
+          for (octave_idx_type i = 0; i < a.length (); i++)
+            result(i) = 1.0 / a(i);
+        }
+      else
+        {
+          for (octave_idx_type i = 0; i < a.length (); i++)
+            {
+              octave_quit ();
+              result(i) = std::pow (a(i), ib);
+            }
+        }
+
+      retval = result;
+    }
+
+  return retval;
+}
+
+// -*- 4 -*-
+octave_value
+elem_xpow (const NDArray& a, const NDArray& b)
+{
+  octave_value retval;
+
+  dim_vector a_dims = a.dims ();
+  dim_vector b_dims = b.dims ();
+
+  if (a_dims != b_dims)
+    {
+      if (is_valid_bsxfun ("operator .^", a_dims, b_dims))
+        {
+          //Potentially complex results
+          NDArray xa = octave_value_extract<NDArray> (a);
+          NDArray xb = octave_value_extract<NDArray> (b);
+          if (! xb.all_integers () && xa.any_element_is_negative ())
+            return octave_value (bsxfun_pow (ComplexNDArray (xa), xb));
+          else
+            return octave_value (bsxfun_pow (xa, xb));
+        }
+      else
+        {
+          gripe_nonconformant ("operator .^", a_dims, b_dims);
+          return octave_value ();
+        }
+    }
+
+  int len = a.length ();
+
+  bool convert_to_complex = false;
+
+  for (octave_idx_type i = 0; i < len; i++)
+    {
+      octave_quit ();
+      double atmp = a(i);
+      double btmp = b(i);
+      if (atmp < 0.0 && static_cast<int> (btmp) != btmp)
+        {
+          convert_to_complex = true;
+          goto done;
+        }
+    }
+
+done:
+
+  if (convert_to_complex)
+    {
+      ComplexNDArray complex_result (a_dims);
+
+      for (octave_idx_type i = 0; i < len; i++)
+        {
+          octave_quit ();
+          Complex atmp (a(i));
+          complex_result(i) = std::pow (atmp, b(i));
+        }
+
+      retval = complex_result;
+    }
+  else
+    {
+      NDArray result (a_dims);
+
+      for (octave_idx_type i = 0; i < len; i++)
+        {
+          octave_quit ();
+          result(i) = std::pow (a(i), b(i));
+        }
+
+      retval = result;
+    }
+
+  return retval;
+}
+
+// -*- 5 -*-
+octave_value
+elem_xpow (const NDArray& a, const Complex& b)
+{
+  ComplexNDArray result (a.dims ());
+
+  for (octave_idx_type i = 0; i < a.length (); i++)
+    {
+      octave_quit ();
+      result(i) = std::pow (a(i), b);
+    }
+
+  return result;
+}
+
+// -*- 6 -*-
+octave_value
+elem_xpow (const NDArray& a, const ComplexNDArray& b)
+{
+  dim_vector a_dims = a.dims ();
+  dim_vector b_dims = b.dims ();
+
+  if (a_dims != b_dims)
+    {
+      if (is_valid_bsxfun ("operator .^", a_dims, b_dims))
+        {
+          return bsxfun_pow (a, b);
+        }
+      else
+        {
+          gripe_nonconformant ("operator .^", a_dims, b_dims);
+          return octave_value ();
+        }
+    }
+
+  ComplexNDArray result (a_dims);
+
+  for (octave_idx_type i = 0; i < a.length (); i++)
+    {
+      octave_quit ();
+      result(i) = std::pow (a(i), b(i));
+    }
+
+  return result;
+}
+
+// -*- 7 -*-
+octave_value
+elem_xpow (const Complex& a, const NDArray& b)
+{
+  ComplexNDArray result (b.dims ());
+
+  for (octave_idx_type i = 0; i < b.length (); i++)
+    {
+      octave_quit ();
+      double btmp = b(i);
+      if (xisint (btmp))
+        result(i) = std::pow (a, static_cast<int> (btmp));
+      else
+        result(i) = std::pow (a, btmp);
+    }
+
+  return result;
+}
+
+// -*- 8 -*-
+octave_value
+elem_xpow (const Complex& a, const ComplexNDArray& b)
+{
+  ComplexNDArray result (b.dims ());
+
+  for (octave_idx_type i = 0; i < b.length (); i++)
+    {
+      octave_quit ();
+      result(i) = std::pow (a, b(i));
+    }
+
+  return result;
+}
+
+// -*- 9 -*-
+octave_value
+elem_xpow (const ComplexNDArray& a, double b)
+{
+  ComplexNDArray result (a.dims ());
+
+  if (xisint (b))
+    {
+      if (b == -1)
+        {
+          for (octave_idx_type i = 0; i < a.length (); i++)
+            result.xelem (i) = 1.0 / a(i);
+        }
+      else
+        {
+          for (octave_idx_type i = 0; i < a.length (); i++)
+            {
+              octave_quit ();
+              result(i) = std::pow (a(i), static_cast<int> (b));
+            }
+        }
+    }
+  else
+    {
+      for (octave_idx_type i = 0; i < a.length (); i++)
+        {
+          octave_quit ();
+          result(i) = std::pow (a(i), b);
+        }
+    }
+
+  return result;
+}
+
+// -*- 10 -*-
+octave_value
+elem_xpow (const ComplexNDArray& a, const NDArray& b)
+{
+  dim_vector a_dims = a.dims ();
+  dim_vector b_dims = b.dims ();
+
+  if (a_dims != b_dims)
+    {
+      if (is_valid_bsxfun ("operator .^", a_dims, b_dims))
+        {
+          return bsxfun_pow (a, b);
+        }
+      else
+        {
+          gripe_nonconformant ("operator .^", a_dims, b_dims);
+          return octave_value ();
+        }
+    }
+
+  ComplexNDArray result (a_dims);
+
+  for (octave_idx_type i = 0; i < a.length (); i++)
+    {
+      octave_quit ();
+      double btmp = b(i);
+      if (xisint (btmp))
+        result(i) = std::pow (a(i), static_cast<int> (btmp));
+      else
+        result(i) = std::pow (a(i), btmp);
+    }
+
+  return result;
+}
+
+// -*- 11 -*-
+octave_value
+elem_xpow (const ComplexNDArray& a, const Complex& b)
+{
+  ComplexNDArray result (a.dims ());
+
+  for (octave_idx_type i = 0; i < a.length (); i++)
+    {
+      octave_quit ();
+      result(i) = std::pow (a(i), b);
+    }
+
+  return result;
+}
+
+// -*- 12 -*-
+octave_value
+elem_xpow (const ComplexNDArray& a, const ComplexNDArray& b)
+{
+  dim_vector a_dims = a.dims ();
+  dim_vector b_dims = b.dims ();
+
+  if (a_dims != b_dims)
+    {
+      if (is_valid_bsxfun ("operator .^", a_dims, b_dims))
+        {
+          return bsxfun_pow (a, b);
+        }
+      else
+        {
+          gripe_nonconformant ("operator .^", a_dims, b_dims);
+          return octave_value ();
+        }
+    }
+
+  ComplexNDArray result (a_dims);
+
+  for (octave_idx_type i = 0; i < a.length (); i++)
+    {
+      octave_quit ();
+      result(i) = std::pow (a(i), b(i));
+    }
+
+  return result;
+}
+
+static inline int
+xisint (float x)
+{
+  return (D_NINT (x) == x
+          && ((x >= 0 && x < INT_MAX)
+              || (x <= 0 && x > INT_MIN)));
+}
+
+// Safer pow functions.
+//
+//       op2 \ op1:   s   m   cs   cm
+//            +--   +---+---+----+----+
+//   scalar   |     | 1 | 5 |  7 | 11 |
+//                  +---+---+----+----+
+//   matrix         | 2 | * |  8 |  * |
+//                  +---+---+----+----+
+//   complex_scalar | 3 | 6 |  9 | 12 |
+//                  +---+---+----+----+
+//   complex_matrix | 4 | * | 10 |  * |
+//                  +---+---+----+----+
+
+// -*- 1 -*-
+octave_value
+xpow (float a, float b)
+{
+  float retval;
+
+  if (a < 0.0 && ! xisint (b))
+    {
+      FloatComplex atmp (a);
+
+      return std::pow (atmp, b);
+    }
+  else
+    retval = std::pow (a, b);
+
+  return retval;
+}
+
+// -*- 2 -*-
+octave_value
+xpow (float a, const FloatMatrix& b)
+{
+  octave_value retval;
+
+  octave_idx_type nr = b.rows ();
+  octave_idx_type nc = b.cols ();
+
+  if (nr == 0 || nc == 0 || nr != nc)
+    error ("for x^A, A must be a square matrix");
+  else
+    {
+      FloatEIG b_eig (b);
+
+      if (! error_state)
+        {
+          FloatComplexColumnVector lambda (b_eig.eigenvalues ());
+          FloatComplexMatrix Q (b_eig.eigenvectors ());
+
+          for (octave_idx_type i = 0; i < nr; i++)
+            {
+              FloatComplex elt = lambda(i);
+              if (std::imag (elt) == 0.0)
+                lambda(i) = std::pow (a, std::real (elt));
+              else
+                lambda(i) = std::pow (a, elt);
+            }
+          FloatComplexDiagMatrix D (lambda);
+
+          FloatComplexMatrix C = Q * D * Q.inverse ();
+
+          if (a > 0)
+            retval = real (C);
+          else
+            retval = C;
+        }
+      else
+        error ("xpow: matrix diagonalization failed");
+    }
+
+  return retval;
+}
+
+// -*- 3 -*-
+octave_value
+xpow (float a, const FloatComplex& b)
+{
+  FloatComplex result = std::pow (a, b);
+  return result;
+}
+
+// -*- 4 -*-
+octave_value
+xpow (float a, const FloatComplexMatrix& b)
+{
+  octave_value retval;
+
+  octave_idx_type nr = b.rows ();
+  octave_idx_type nc = b.cols ();
+
+  if (nr == 0 || nc == 0 || nr != nc)
+    error ("for x^A, A must be a square matrix");
+  else
+    {
+      FloatEIG b_eig (b);
+
+      if (! error_state)
+        {
+          FloatComplexColumnVector lambda (b_eig.eigenvalues ());
+          FloatComplexMatrix Q (b_eig.eigenvectors ());
+
+          for (octave_idx_type i = 0; i < nr; i++)
+            {
+              FloatComplex elt = lambda(i);
+              if (std::imag (elt) == 0.0)
+                lambda(i) = std::pow (a, std::real (elt));
+              else
+                lambda(i) = std::pow (a, elt);
+            }
+          FloatComplexDiagMatrix D (lambda);
+
+          retval = FloatComplexMatrix (Q * D * Q.inverse ());
+        }
+      else
+        error ("xpow: matrix diagonalization failed");
+    }
+
+  return retval;
+}
+
+// -*- 5 -*-
+octave_value
+xpow (const FloatMatrix& a, float b)
+{
+  octave_value retval;
+
+  octave_idx_type nr = a.rows ();
+  octave_idx_type nc = a.cols ();
+
+  if (nr == 0 || nc == 0 || nr != nc)
+    error ("for A^b, A must be a square matrix");
+  else
+    {
+      if (static_cast<int> (b) == b)
+        {
+          int btmp = static_cast<int> (b);
+          if (btmp == 0)
+            {
+              retval = FloatDiagMatrix (nr, nr, 1.0);
+            }
+          else
+            {
+              // Too much copying?
+              // FIXME -- we shouldn't do this if the exponent is
+              // large...
+
+              FloatMatrix atmp;
+              if (btmp < 0)
+                {
+                  btmp = -btmp;
+
+                  octave_idx_type info;
+                  float rcond = 0.0;
+                  MatrixType mattype (a);
+
+                  atmp = a.inverse (mattype, info, rcond, 1);
+
+                  if (info == -1)
+                    warning ("inverse: matrix singular to machine\
+ precision, rcond = %g", rcond);
+                }
+              else
+                atmp = a;
+
+              FloatMatrix result (atmp);
+
+              btmp--;
+
+              while (btmp > 0)
+                {
+                  if (btmp & 1)
+                    result = result * atmp;
+
+                  btmp >>= 1;
+
+                  if (btmp > 0)
+                    atmp = atmp * atmp;
+                }
+
+              retval = result;
+            }
+        }
+      else
+        {
+          FloatEIG a_eig (a);
+
+          if (! error_state)
+            {
+              FloatComplexColumnVector lambda (a_eig.eigenvalues ());
+              FloatComplexMatrix Q (a_eig.eigenvectors ());
+
+              for (octave_idx_type i = 0; i < nr; i++)
+                lambda(i) = std::pow (lambda(i), b);
+
+              FloatComplexDiagMatrix D (lambda);
+
+              retval = FloatComplexMatrix (Q * D * Q.inverse ());
+            }
+          else
+            error ("xpow: matrix diagonalization failed");
+        }
+    }
+
+  return retval;
+}
+
+// -*- 5d -*-
+octave_value
+xpow (const FloatDiagMatrix& a, float b)
+{
+  octave_value retval;
+
+  octave_idx_type nr = a.rows ();
+  octave_idx_type nc = a.cols ();
+
+  if (nr == 0 || nc == 0 || nr != nc)
+    error ("for A^b, A must be a square matrix");
+  else
+    {
+      if (static_cast<int> (b) == b)
+        {
+          FloatDiagMatrix r (nr, nc);
+          for (octave_idx_type i = 0; i < nc; i++)
+            r.dgelem (i) = std::pow (a.dgelem (i), b);
+          retval = r;
+        }
+      else
+        {
+          FloatComplexDiagMatrix r (nr, nc);
+          for (octave_idx_type i = 0; i < nc; i++)
+            r.dgelem (i) = std::pow (static_cast<FloatComplex> (a.dgelem (i)), b);
+          retval = r;
+        }
+    }
+
+  return retval;
+}
+
+// -*- 6 -*-
+octave_value
+xpow (const FloatMatrix& a, const FloatComplex& b)
+{
+  octave_value retval;
+
+  octave_idx_type nr = a.rows ();
+  octave_idx_type nc = a.cols ();
+
+  if (nr == 0 || nc == 0 || nr != nc)
+    error ("for A^b, A must be a square matrix");
+  else
+    {
+      FloatEIG a_eig (a);
+
+      if (! error_state)
+        {
+          FloatComplexColumnVector lambda (a_eig.eigenvalues ());
+          FloatComplexMatrix Q (a_eig.eigenvectors ());
+
+          for (octave_idx_type i = 0; i < nr; i++)
+            lambda(i) = std::pow (lambda(i), b);
+
+          FloatComplexDiagMatrix D (lambda);
+
+          retval = FloatComplexMatrix (Q * D * Q.inverse ());
+        }
+      else
+        error ("xpow: matrix diagonalization failed");
+    }
+
+  return retval;
+}
+
+// -*- 7 -*-
+octave_value
+xpow (const FloatComplex& a, float b)
+{
+  FloatComplex result;
+
+  if (xisint (b))
+    result = std::pow (a, static_cast<int> (b));
+  else
+    result = std::pow (a, b);
+
+  return result;
+}
+
+// -*- 8 -*-
+octave_value
+xpow (const FloatComplex& a, const FloatMatrix& b)
+{
+  octave_value retval;
+
+  octave_idx_type nr = b.rows ();
+  octave_idx_type nc = b.cols ();
+
+  if (nr == 0 || nc == 0 || nr != nc)
+    error ("for x^A, A must be a square matrix");
+  else
+    {
+      FloatEIG b_eig (b);
+
+      if (! error_state)
+        {
+          FloatComplexColumnVector lambda (b_eig.eigenvalues ());
+          FloatComplexMatrix Q (b_eig.eigenvectors ());
+
+          for (octave_idx_type i = 0; i < nr; i++)
+            {
+              FloatComplex elt = lambda(i);
+              if (std::imag (elt) == 0.0)
+                lambda(i) = std::pow (a, std::real (elt));
+              else
+                lambda(i) = std::pow (a, elt);
+            }
+          FloatComplexDiagMatrix D (lambda);
+
+          retval = FloatComplexMatrix (Q * D * Q.inverse ());
+        }
+      else
+        error ("xpow: matrix diagonalization failed");
+    }
+
+  return retval;
+}
+
+// -*- 9 -*-
+octave_value
+xpow (const FloatComplex& a, const FloatComplex& b)
+{
+  FloatComplex result;
+  result = std::pow (a, b);
+  return result;
+}
+
+// -*- 10 -*-
+octave_value
+xpow (const FloatComplex& a, const FloatComplexMatrix& b)
+{
+  octave_value retval;
+
+  octave_idx_type nr = b.rows ();
+  octave_idx_type nc = b.cols ();
+
+  if (nr == 0 || nc == 0 || nr != nc)
+    error ("for x^A, A must be a square matrix");
+  else
+    {
+      FloatEIG b_eig (b);
+
+      if (! error_state)
+        {
+          FloatComplexColumnVector lambda (b_eig.eigenvalues ());
+          FloatComplexMatrix Q (b_eig.eigenvectors ());
+
+          for (octave_idx_type i = 0; i < nr; i++)
+            {
+              FloatComplex elt = lambda(i);
+              if (std::imag (elt) == 0.0)
+                lambda(i) = std::pow (a, std::real (elt));
+              else
+                lambda(i) = std::pow (a, elt);
+            }
+          FloatComplexDiagMatrix D (lambda);
+
+          retval = FloatComplexMatrix (Q * D * Q.inverse ());
+        }
+      else
+        error ("xpow: matrix diagonalization failed");
+    }
+
+  return retval;
+}
+
+// -*- 11 -*-
+octave_value
+xpow (const FloatComplexMatrix& a, float b)
+{
+  octave_value retval;
+
+  octave_idx_type nr = a.rows ();
+  octave_idx_type nc = a.cols ();
+
+  if (nr == 0 || nc == 0 || nr != nc)
+    error ("for A^b, A must be a square matrix");
+  else
+    {
+      if (static_cast<int> (b) == b)
+        {
+          int btmp = static_cast<int> (b);
+          if (btmp == 0)
+            {
+              retval = FloatDiagMatrix (nr, nr, 1.0);
+            }
+          else
+            {
+              // Too much copying?
+              // FIXME -- we shouldn't do this if the exponent is
+              // large...
+
+              FloatComplexMatrix atmp;
+              if (btmp < 0)
+                {
+                  btmp = -btmp;
+
+                  octave_idx_type info;
+                  float rcond = 0.0;
+                  MatrixType mattype (a);
+
+                  atmp = a.inverse (mattype, info, rcond, 1);
+
+                  if (info == -1)
+                    warning ("inverse: matrix singular to machine\
+ precision, rcond = %g", rcond);
+                }
+              else
+                atmp = a;
+
+              FloatComplexMatrix result (atmp);
+
+              btmp--;
+
+              while (btmp > 0)
+                {
+                  if (btmp & 1)
+                    result = result * atmp;
+
+                  btmp >>= 1;
+
+                  if (btmp > 0)
+                    atmp = atmp * atmp;
+                }
+
+              retval = result;
+            }
+        }
+      else
+        {
+          FloatEIG a_eig (a);
+
+          if (! error_state)
+            {
+              FloatComplexColumnVector lambda (a_eig.eigenvalues ());
+              FloatComplexMatrix Q (a_eig.eigenvectors ());
+
+              for (octave_idx_type i = 0; i < nr; i++)
+                lambda(i) = std::pow (lambda(i), b);
+
+              FloatComplexDiagMatrix D (lambda);
+
+              retval = FloatComplexMatrix (Q * D * Q.inverse ());
+            }
+          else
+            error ("xpow: matrix diagonalization failed");
+        }
+    }
+
+  return retval;
+}
+
+// -*- 12 -*-
+octave_value
+xpow (const FloatComplexMatrix& a, const FloatComplex& b)
+{
+  octave_value retval;
+
+  octave_idx_type nr = a.rows ();
+  octave_idx_type nc = a.cols ();
+
+  if (nr == 0 || nc == 0 || nr != nc)
+    error ("for A^b, A must be a square matrix");
+  else
+    {
+      FloatEIG a_eig (a);
+
+      if (! error_state)
+        {
+          FloatComplexColumnVector lambda (a_eig.eigenvalues ());
+          FloatComplexMatrix Q (a_eig.eigenvectors ());
+
+          for (octave_idx_type i = 0; i < nr; i++)
+            lambda(i) = std::pow (lambda(i), b);
+
+          FloatComplexDiagMatrix D (lambda);
+
+          retval = FloatComplexMatrix (Q * D * Q.inverse ());
+        }
+      else
+        error ("xpow: matrix diagonalization failed");
+    }
+
+  return retval;
+}
+
+// -*- 12d -*-
+octave_value
+xpow (const FloatComplexDiagMatrix& a, const FloatComplex& b)
+{
+  octave_value retval;
+
+  octave_idx_type nr = a.rows ();
+  octave_idx_type nc = a.cols ();
+
+  if (nr == 0 || nc == 0 || nr != nc)
+    error ("for A^b, A must be a square matrix");
+  else
+    {
+      FloatComplexDiagMatrix r (nr, nc);
+      for (octave_idx_type i = 0; i < nc; i++)
+        r(i, i) = std::pow (a(i, i), b);
+      retval = r;
+    }
+
+  return retval;
+}
+
+// mixed
+octave_value
+xpow (const FloatComplexDiagMatrix& a, float b)
+{
+  return xpow (a, static_cast<FloatComplex> (b));
+}
+
+octave_value
+xpow (const FloatDiagMatrix& a, const FloatComplex& b)
+{
+  return xpow (FloatComplexDiagMatrix (a), b);
+}
+
+// Safer pow functions that work elementwise for matrices.
+//
+//       op2 \ op1:   s   m   cs   cm
+//            +--   +---+---+----+----+
+//   scalar   |     | * | 3 |  * |  9 |
+//                  +---+---+----+----+
+//   matrix         | 1 | 4 |  7 | 10 |
+//                  +---+---+----+----+
+//   complex_scalar | * | 5 |  * | 11 |
+//                  +---+---+----+----+
+//   complex_matrix | 2 | 6 |  8 | 12 |
+//                  +---+---+----+----+
+//
+//   * -> not needed.
+
+// FIXME -- these functions need to be fixed so that things
+// like
+//
+//   a = -1; b = [ 0, 0.5, 1 ]; r = a .^ b
+//
+// and
+//
+//   a = -1; b = [ 0, 0.5, 1 ]; for i = 1:3, r(i) = a .^ b(i), end
+//
+// produce identical results.  Also, it would be nice if -1^0.5
+// produced a pure imaginary result instead of a complex number with a
+// small real part.  But perhaps that's really a problem with the math
+// library...
+
+// -*- 1 -*-
+octave_value
+elem_xpow (float a, const FloatMatrix& b)
+{
+  octave_value retval;
+
+  octave_idx_type nr = b.rows ();
+  octave_idx_type nc = b.cols ();
+
+  float d1, d2;
+
+  if (a < 0.0 && ! b.all_integers (d1, d2))
+    {
+      FloatComplex atmp (a);
+      FloatComplexMatrix result (nr, nc);
+
+      for (octave_idx_type j = 0; j < nc; j++)
+        for (octave_idx_type i = 0; i < nr; i++)
+          {
+            octave_quit ();
+            result (i, j) = std::pow (atmp, b (i, j));
+          }
+
+      retval = result;
+    }
+  else
+    {
+      FloatMatrix result (nr, nc);
+
+      for (octave_idx_type j = 0; j < nc; j++)
+        for (octave_idx_type i = 0; i < nr; i++)
+          {
+            octave_quit ();
+            result (i, j) = std::pow (a, b (i, j));
+          }
+
+      retval = result;
+    }
+
+  return retval;
+}
+
+// -*- 2 -*-
+octave_value
+elem_xpow (float a, const FloatComplexMatrix& b)
+{
+  octave_idx_type nr = b.rows ();
+  octave_idx_type nc = b.cols ();
+
+  FloatComplexMatrix result (nr, nc);
+  FloatComplex atmp (a);
+
+  for (octave_idx_type j = 0; j < nc; j++)
+    for (octave_idx_type i = 0; i < nr; i++)
+      {
+        octave_quit ();
+        result (i, j) = std::pow (atmp, b (i, j));
+      }
+
+  return result;
+}
+
+// -*- 3 -*-
+octave_value
+elem_xpow (const FloatMatrix& a, float b)
+{
+  octave_value retval;
+
+  octave_idx_type nr = a.rows ();
+  octave_idx_type nc = a.cols ();
+
+  if (! xisint (b) && a.any_element_is_negative ())
+    {
+      FloatComplexMatrix result (nr, nc);
+
+      for (octave_idx_type j = 0; j < nc; j++)
+        for (octave_idx_type i = 0; i < nr; i++)
+          {
+            octave_quit ();
+
+            FloatComplex atmp (a (i, j));
+
+            result (i, j) = std::pow (atmp, b);
+          }
+
+      retval = result;
+    }
+  else
+    {
+      FloatMatrix result (nr, nc);
+
+      for (octave_idx_type j = 0; j < nc; j++)
+        for (octave_idx_type i = 0; i < nr; i++)
+          {
+            octave_quit ();
+            result (i, j) = std::pow (a (i, j), b);
+          }
+
+      retval = result;
+    }
+
+  return retval;
+}
+
+// -*- 4 -*-
+octave_value
+elem_xpow (const FloatMatrix& a, const FloatMatrix& b)
+{
+  octave_value retval;
+
+  octave_idx_type nr = a.rows ();
+  octave_idx_type nc = a.cols ();
+
+  octave_idx_type b_nr = b.rows ();
+  octave_idx_type b_nc = b.cols ();
+
+  if (nr != b_nr || nc != b_nc)
+    {
+      gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc);
+      return octave_value ();
+    }
+
+  int convert_to_complex = 0;
+  for (octave_idx_type j = 0; j < nc; j++)
+    for (octave_idx_type i = 0; i < nr; i++)
+      {
+        octave_quit ();
+        float atmp = a (i, j);
+        float btmp = b (i, j);
+        if (atmp < 0.0 && static_cast<int> (btmp) != btmp)
+          {
+            convert_to_complex = 1;
+            goto done;
+          }
+      }
+
+done:
+
+  if (convert_to_complex)
+    {
+      FloatComplexMatrix complex_result (nr, nc);
+
+      for (octave_idx_type j = 0; j < nc; j++)
+        for (octave_idx_type i = 0; i < nr; i++)
+          {
+            octave_quit ();
+            FloatComplex atmp (a (i, j));
+            FloatComplex btmp (b (i, j));
+            complex_result (i, j) = std::pow (atmp, btmp);
+          }
+
+      retval = complex_result;
+    }
+  else
+    {
+      FloatMatrix result (nr, nc);
+
+      for (octave_idx_type j = 0; j < nc; j++)
+        for (octave_idx_type i = 0; i < nr; i++)
+          {
+            octave_quit ();
+            result (i, j) = std::pow (a (i, j), b (i, j));
+          }
+
+      retval = result;
+    }
+
+  return retval;
+}
+
+// -*- 5 -*-
+octave_value
+elem_xpow (const FloatMatrix& a, const FloatComplex& b)
+{
+  octave_idx_type nr = a.rows ();
+  octave_idx_type nc = a.cols ();
+
+  FloatComplexMatrix result (nr, nc);
+
+  for (octave_idx_type j = 0; j < nc; j++)
+    for (octave_idx_type i = 0; i < nr; i++)
+      {
+        octave_quit ();
+        result (i, j) = std::pow (FloatComplex (a (i, j)), b);
+      }
+
+  return result;
+}
+
+// -*- 6 -*-
+octave_value
+elem_xpow (const FloatMatrix& a, const FloatComplexMatrix& b)
+{
+  octave_idx_type nr = a.rows ();
+  octave_idx_type nc = a.cols ();
+
+  octave_idx_type b_nr = b.rows ();
+  octave_idx_type b_nc = b.cols ();
+
+  if (nr != b_nr || nc != b_nc)
+    {
+      gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc);
+      return octave_value ();
+    }
+
+  FloatComplexMatrix result (nr, nc);
+
+  for (octave_idx_type j = 0; j < nc; j++)
+    for (octave_idx_type i = 0; i < nr; i++)
+      {
+        octave_quit ();
+        result (i, j) = std::pow (FloatComplex (a (i, j)), b (i, j));
+      }
+
+  return result;
+}
+
+// -*- 7 -*-
+octave_value
+elem_xpow (const FloatComplex& a, const FloatMatrix& b)
+{
+  octave_idx_type nr = b.rows ();
+  octave_idx_type nc = b.cols ();
+
+  FloatComplexMatrix result (nr, nc);
+
+  for (octave_idx_type j = 0; j < nc; j++)
+    for (octave_idx_type i = 0; i < nr; i++)
+      {
+        octave_quit ();
+        float btmp = b (i, j);
+        if (xisint (btmp))
+          result (i, j) = std::pow (a, static_cast<int> (btmp));
+        else
+          result (i, j) = std::pow (a, btmp);
+      }
+
+  return result;
+}
+
+// -*- 8 -*-
+octave_value
+elem_xpow (const FloatComplex& a, const FloatComplexMatrix& b)
+{
+  octave_idx_type nr = b.rows ();
+  octave_idx_type nc = b.cols ();
+
+  FloatComplexMatrix result (nr, nc);
+
+  for (octave_idx_type j = 0; j < nc; j++)
+    for (octave_idx_type i = 0; i < nr; i++)
+      {
+        octave_quit ();
+        result (i, j) = std::pow (a, b (i, j));
+      }
+
+  return result;
+}
+
+// -*- 9 -*-
+octave_value
+elem_xpow (const FloatComplexMatrix& a, float b)
+{
+  octave_idx_type nr = a.rows ();
+  octave_idx_type nc = a.cols ();
+
+  FloatComplexMatrix result (nr, nc);
+
+  if (xisint (b))
+    {
+      for (octave_idx_type j = 0; j < nc; j++)
+        for (octave_idx_type i = 0; i < nr; i++)
+          {
+            octave_quit ();
+            result (i, j) = std::pow (a (i, j), static_cast<int> (b));
+          }
+    }
+  else
+    {
+      for (octave_idx_type j = 0; j < nc; j++)
+        for (octave_idx_type i = 0; i < nr; i++)
+          {
+            octave_quit ();
+            result (i, j) = std::pow (a (i, j), b);
+          }
+    }
+
+  return result;
+}
+
+// -*- 10 -*-
+octave_value
+elem_xpow (const FloatComplexMatrix& a, const FloatMatrix& b)
+{
+  octave_idx_type nr = a.rows ();
+  octave_idx_type nc = a.cols ();
+
+  octave_idx_type b_nr = b.rows ();
+  octave_idx_type b_nc = b.cols ();
+
+  if (nr != b_nr || nc != b_nc)
+    {
+      gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc);
+      return octave_value ();
+    }
+
+  FloatComplexMatrix result (nr, nc);
+
+  for (octave_idx_type j = 0; j < nc; j++)
+    for (octave_idx_type i = 0; i < nr; i++)
+      {
+        octave_quit ();
+        float btmp = b (i, j);
+        if (xisint (btmp))
+          result (i, j) = std::pow (a (i, j), static_cast<int> (btmp));
+        else
+          result (i, j) = std::pow (a (i, j), btmp);
+      }
+
+  return result;
+}
+
+// -*- 11 -*-
+octave_value
+elem_xpow (const FloatComplexMatrix& a, const FloatComplex& b)
+{
+  octave_idx_type nr = a.rows ();
+  octave_idx_type nc = a.cols ();
+
+  FloatComplexMatrix result (nr, nc);
+
+  for (octave_idx_type j = 0; j < nc; j++)
+    for (octave_idx_type i = 0; i < nr; i++)
+      {
+        octave_quit ();
+        result (i, j) = std::pow (a (i, j), b);
+      }
+
+  return result;
+}
+
+// -*- 12 -*-
+octave_value
+elem_xpow (const FloatComplexMatrix& a, const FloatComplexMatrix& b)
+{
+  octave_idx_type nr = a.rows ();
+  octave_idx_type nc = a.cols ();
+
+  octave_idx_type b_nr = b.rows ();
+  octave_idx_type b_nc = b.cols ();
+
+  if (nr != b_nr || nc != b_nc)
+    {
+      gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc);
+      return octave_value ();
+    }
+
+  FloatComplexMatrix result (nr, nc);
+
+  for (octave_idx_type j = 0; j < nc; j++)
+    for (octave_idx_type i = 0; i < nr; i++)
+      {
+        octave_quit ();
+        result (i, j) = std::pow (a (i, j), b (i, j));
+      }
+
+  return result;
+}
+
+// Safer pow functions that work elementwise for N-d arrays.
+//
+//       op2 \ op1:   s   nd  cs   cnd
+//            +--   +---+---+----+----+
+//   scalar   |     | * | 3 |  * |  9 |
+//                  +---+---+----+----+
+//   N_d            | 1 | 4 |  7 | 10 |
+//                  +---+---+----+----+
+//   complex_scalar | * | 5 |  * | 11 |
+//                  +---+---+----+----+
+//   complex_N_d    | 2 | 6 |  8 | 12 |
+//                  +---+---+----+----+
+//
+//   * -> not needed.
+
+// FIXME -- these functions need to be fixed so that things
+// like
+//
+//   a = -1; b = [ 0, 0.5, 1 ]; r = a .^ b
+//
+// and
+//
+//   a = -1; b = [ 0, 0.5, 1 ]; for i = 1:3, r(i) = a .^ b(i), end
+//
+// produce identical results.  Also, it would be nice if -1^0.5
+// produced a pure imaginary result instead of a complex number with a
+// small real part.  But perhaps that's really a problem with the math
+// library...
+
+// -*- 1 -*-
+octave_value
+elem_xpow (float a, const FloatNDArray& b)
+{
+  octave_value retval;
+
+  if (a < 0.0 && ! b.all_integers ())
+    {
+      FloatComplex atmp (a);
+      FloatComplexNDArray result (b.dims ());
+      for (octave_idx_type i = 0; i < b.length (); i++)
+        {
+          octave_quit ();
+          result(i) = std::pow (atmp, b(i));
+        }
+
+      retval = result;
+    }
+  else
+    {
+      FloatNDArray result (b.dims ());
+      for (octave_idx_type i = 0; i < b.length (); i++)
+        {
+          octave_quit ();
+          result (i) = std::pow (a, b(i));
+        }
+
+      retval = result;
+    }
+
+  return retval;
+}
+
+// -*- 2 -*-
+octave_value
+elem_xpow (float a, const FloatComplexNDArray& b)
+{
+  FloatComplexNDArray result (b.dims ());
+
+  for (octave_idx_type i = 0; i < b.length (); i++)
+    {
+      octave_quit ();
+      result(i) = std::pow (a, b(i));
+    }
+
+  return result;
+}
+
+// -*- 3 -*-
+octave_value
+elem_xpow (const FloatNDArray& a, float b)
+{
+  octave_value retval;
+
+  if (! xisint (b))
+    {
+      if (a.any_element_is_negative ())
+        {
+          FloatComplexNDArray result (a.dims ());
+
+          for (octave_idx_type i = 0; i < a.length (); i++)
+            {
+              octave_quit ();
+
+              FloatComplex atmp (a (i));
+
+              result(i) = std::pow (atmp, b);
+            }
+
+          retval = result;
+        }
+      else
+        {
+          FloatNDArray result (a.dims ());
+          for (octave_idx_type i = 0; i < a.length (); i++)
+            {
+              octave_quit ();
+              result(i) = std::pow (a(i), b);
+            }
+
+          retval = result;
+        }
+    }
+  else
+    {
+      NoAlias<FloatNDArray> result (a.dims ());
+
+      int ib = static_cast<int> (b);
+      if (ib == 2)
+        {
+          for (octave_idx_type i = 0; i < a.length (); i++)
+            result(i) = a(i) * a(i);
+        }
+      else if (ib == 3)
+        {
+          for (octave_idx_type i = 0; i < a.length (); i++)
+            result(i) = a(i) * a(i) * a(i);
+        }
+      else if (ib == -1)
+        {
+          for (octave_idx_type i = 0; i < a.length (); i++)
+            result(i) = 1.0f / a(i);
+        }
+      else
+        {
+          for (octave_idx_type i = 0; i < a.length (); i++)
+            {
+              octave_quit ();
+              result(i) = std::pow (a(i), ib);
+            }
+        }
+
+      retval = result;
+    }
+
+  return retval;
+}
+
+// -*- 4 -*-
+octave_value
+elem_xpow (const FloatNDArray& a, const FloatNDArray& b)
+{
+  octave_value retval;
+
+  dim_vector a_dims = a.dims ();
+  dim_vector b_dims = b.dims ();
+
+  if (a_dims != b_dims)
+    {
+      if (is_valid_bsxfun ("operator .^", a_dims, b_dims))
+        {
+          //Potentially complex results
+          FloatNDArray xa = octave_value_extract<FloatNDArray> (a);
+          FloatNDArray xb = octave_value_extract<FloatNDArray> (b);
+          if (! xb.all_integers () && xa.any_element_is_negative ())
+            return octave_value (bsxfun_pow (FloatComplexNDArray (xa), xb));
+          else
+            return octave_value (bsxfun_pow (xa, xb));
+        }
+      else
+        {
+          gripe_nonconformant ("operator .^", a_dims, b_dims);
+          return octave_value ();
+        }
+    }
+
+  int len = a.length ();
+
+  bool convert_to_complex = false;
+
+  for (octave_idx_type i = 0; i < len; i++)
+    {
+      octave_quit ();
+      float atmp = a(i);
+      float btmp = b(i);
+      if (atmp < 0.0 && static_cast<int> (btmp) != btmp)
+        {
+          convert_to_complex = true;
+          goto done;
+        }
+    }
+
+done:
+
+  if (convert_to_complex)
+    {
+      FloatComplexNDArray complex_result (a_dims);
+
+      for (octave_idx_type i = 0; i < len; i++)
+        {
+          octave_quit ();
+          FloatComplex atmp (a(i));
+          complex_result(i) = std::pow (atmp, b(i));
+        }
+
+      retval = complex_result;
+    }
+  else
+    {
+      FloatNDArray result (a_dims);
+
+      for (octave_idx_type i = 0; i < len; i++)
+        {
+          octave_quit ();
+          result(i) = std::pow (a(i), b(i));
+        }
+
+      retval = result;
+    }
+
+  return retval;
+}
+
+// -*- 5 -*-
+octave_value
+elem_xpow (const FloatNDArray& a, const FloatComplex& b)
+{
+  FloatComplexNDArray result (a.dims ());
+
+  for (octave_idx_type i = 0; i < a.length (); i++)
+    {
+      octave_quit ();
+      result(i) = std::pow (a(i), b);
+    }
+
+  return result;
+}
+
+// -*- 6 -*-
+octave_value
+elem_xpow (const FloatNDArray& a, const FloatComplexNDArray& b)
+{
+  dim_vector a_dims = a.dims ();
+  dim_vector b_dims = b.dims ();
+
+  if (a_dims != b_dims)
+    {
+      if (is_valid_bsxfun ("operator .^", a_dims, b_dims))
+        {
+          return bsxfun_pow (a, b);
+        }
+      else
+        {
+          gripe_nonconformant ("operator .^", a_dims, b_dims);
+          return octave_value ();
+        }
+    }
+
+  FloatComplexNDArray result (a_dims);
+
+  for (octave_idx_type i = 0; i < a.length (); i++)
+    {
+      octave_quit ();
+      result(i) = std::pow (a(i), b(i));
+    }
+
+  return result;
+}
+
+// -*- 7 -*-
+octave_value
+elem_xpow (const FloatComplex& a, const FloatNDArray& b)
+{
+  FloatComplexNDArray result (b.dims ());
+
+  for (octave_idx_type i = 0; i < b.length (); i++)
+    {
+      octave_quit ();
+      float btmp = b(i);
+      if (xisint (btmp))
+        result(i) = std::pow (a, static_cast<int> (btmp));
+      else
+        result(i) = std::pow (a, btmp);
+    }
+
+  return result;
+}
+
+// -*- 8 -*-
+octave_value
+elem_xpow (const FloatComplex& a, const FloatComplexNDArray& b)
+{
+  FloatComplexNDArray result (b.dims ());
+
+  for (octave_idx_type i = 0; i < b.length (); i++)
+    {
+      octave_quit ();
+      result(i) = std::pow (a, b(i));
+    }
+
+  return result;
+}
+
+// -*- 9 -*-
+octave_value
+elem_xpow (const FloatComplexNDArray& a, float b)
+{
+  FloatComplexNDArray result (a.dims ());
+
+  if (xisint (b))
+    {
+      if (b == -1)
+        {
+          for (octave_idx_type i = 0; i < a.length (); i++)
+            result.xelem (i) = 1.0f / a(i);
+        }
+      else
+        {
+          for (octave_idx_type i = 0; i < a.length (); i++)
+            {
+              octave_quit ();
+              result(i) = std::pow (a(i), static_cast<int> (b));
+            }
+        }
+    }
+  else
+    {
+      for (octave_idx_type i = 0; i < a.length (); i++)
+        {
+          octave_quit ();
+          result(i) = std::pow (a(i), b);
+        }
+    }
+
+  return result;
+}
+
+// -*- 10 -*-
+octave_value
+elem_xpow (const FloatComplexNDArray& a, const FloatNDArray& b)
+{
+  dim_vector a_dims = a.dims ();
+  dim_vector b_dims = b.dims ();
+
+  if (a_dims != b_dims)
+    {
+      if (is_valid_bsxfun ("operator .^", a_dims, b_dims))
+        {
+          return bsxfun_pow (a, b);
+        }
+      else
+        {
+          gripe_nonconformant ("operator .^", a_dims, b_dims);
+          return octave_value ();
+        }
+    }
+
+  FloatComplexNDArray result (a_dims);
+
+  for (octave_idx_type i = 0; i < a.length (); i++)
+    {
+      octave_quit ();
+      float btmp = b(i);
+      if (xisint (btmp))
+        result(i) = std::pow (a(i), static_cast<int> (btmp));
+      else
+        result(i) = std::pow (a(i), btmp);
+    }
+
+  return result;
+}
+
+// -*- 11 -*-
+octave_value
+elem_xpow (const FloatComplexNDArray& a, const FloatComplex& b)
+{
+  FloatComplexNDArray result (a.dims ());
+
+  for (octave_idx_type i = 0; i < a.length (); i++)
+    {
+      octave_quit ();
+      result(i) = std::pow (a(i), b);
+    }
+
+  return result;
+}
+
+// -*- 12 -*-
+octave_value
+elem_xpow (const FloatComplexNDArray& a, const FloatComplexNDArray& b)
+{
+  dim_vector a_dims = a.dims ();
+  dim_vector b_dims = b.dims ();
+
+  if (a_dims != b_dims)
+    {
+      if (is_valid_bsxfun ("operator .^", a_dims, b_dims))
+        {
+          return bsxfun_pow (a, b);
+        }
+      else
+        {
+          gripe_nonconformant ("operator .^", a_dims, b_dims);
+          return octave_value ();
+        }
+    }
+
+  FloatComplexNDArray result (a_dims);
+
+  for (octave_idx_type i = 0; i < a.length (); i++)
+    {
+      octave_quit ();
+      result(i) = std::pow (a(i), b(i));
+    }
+
+  return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/xpow.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,158 @@
+/*
+
+Copyright (C) 1993-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if !defined (octave_xpow_h)
+#define octave_xpow_h 1
+
+#include "oct-cmplx.h"
+
+class Matrix;
+class ComplexMatrix;
+class FloatMatrix;
+class FloatComplexMatrix;
+class DiagMatrix;
+class ComplexDiagMatrix;
+class FloatDiagMatrix;
+class FloatComplexDiagMatrix;
+class PermMatrix;
+class NDArray;
+class FloatNDArray;
+class ComplexNDArray;
+class FloatComplexNDArray;
+class octave_value;
+class Range;
+
+extern OCTINTERP_API octave_value xpow (double a, double b);
+extern OCTINTERP_API octave_value xpow (double a, const Matrix& b);
+extern OCTINTERP_API octave_value xpow (double a, const Complex& b);
+extern OCTINTERP_API octave_value xpow (double a, const ComplexMatrix& b);
+
+extern OCTINTERP_API octave_value xpow (const Matrix& a, double b);
+extern OCTINTERP_API octave_value xpow (const Matrix& a, const Complex& b);
+
+extern OCTINTERP_API octave_value xpow (const DiagMatrix& a, double b);
+extern OCTINTERP_API octave_value xpow (const DiagMatrix& a, const Complex& b);
+
+extern OCTINTERP_API octave_value xpow (const PermMatrix& a, double b);
+
+extern OCTINTERP_API octave_value xpow (const Complex& a, double b);
+extern OCTINTERP_API octave_value xpow (const Complex& a, const Matrix& b);
+extern OCTINTERP_API octave_value xpow (const Complex& a, const Complex& b);
+extern OCTINTERP_API octave_value xpow (const Complex& a, const ComplexMatrix& b);
+
+extern OCTINTERP_API octave_value xpow (const ComplexMatrix& a, double b);
+extern OCTINTERP_API octave_value xpow (const ComplexMatrix& a, const Complex& b);
+
+extern OCTINTERP_API octave_value xpow (const ComplexDiagMatrix& a, double b);
+extern OCTINTERP_API octave_value xpow (const ComplexDiagMatrix& a, const Complex& b);
+
+extern OCTINTERP_API octave_value elem_xpow (double a, const Matrix& b);
+extern OCTINTERP_API octave_value elem_xpow (double a, const ComplexMatrix& b);
+extern OCTINTERP_API octave_value elem_xpow (double a, const Range& r);
+
+extern OCTINTERP_API octave_value elem_xpow (const Matrix& a, double b);
+extern OCTINTERP_API octave_value elem_xpow (const Matrix& a, const Matrix& b);
+extern OCTINTERP_API octave_value elem_xpow (const Matrix& a, const Complex& b);
+extern OCTINTERP_API octave_value elem_xpow (const Matrix& a, const ComplexMatrix& b);
+
+extern OCTINTERP_API octave_value elem_xpow (const Complex& a, const Matrix& b);
+extern OCTINTERP_API octave_value elem_xpow (const Complex& a, const ComplexMatrix& b);
+extern OCTINTERP_API octave_value elem_xpow (const Complex& a, const Range& r);
+
+extern OCTINTERP_API octave_value elem_xpow (const ComplexMatrix& a, double b);
+extern OCTINTERP_API octave_value elem_xpow (const ComplexMatrix& a, const Matrix& b);
+extern OCTINTERP_API octave_value elem_xpow (const ComplexMatrix& a, const Complex& b);
+extern OCTINTERP_API octave_value elem_xpow (const ComplexMatrix& a, const ComplexMatrix& b);
+
+
+extern OCTINTERP_API octave_value elem_xpow (double a, const NDArray& b);
+extern OCTINTERP_API octave_value elem_xpow (double a, const ComplexNDArray& b);
+
+extern OCTINTERP_API octave_value elem_xpow (const NDArray& a, double b);
+extern OCTINTERP_API octave_value elem_xpow (const NDArray& a, const NDArray& b);
+extern OCTINTERP_API octave_value elem_xpow (const NDArray& a, const Complex& b);
+extern OCTINTERP_API octave_value elem_xpow (const NDArray& a, const ComplexNDArray& b);
+
+extern OCTINTERP_API octave_value elem_xpow (const Complex& a, const NDArray& b);
+extern OCTINTERP_API octave_value elem_xpow (const Complex& a, const ComplexNDArray& b);
+
+extern OCTINTERP_API octave_value elem_xpow (const ComplexNDArray& a, double b);
+extern OCTINTERP_API octave_value elem_xpow (const ComplexNDArray& a, const NDArray& b);
+extern OCTINTERP_API octave_value elem_xpow (const ComplexNDArray& a, const Complex& b);
+extern OCTINTERP_API octave_value elem_xpow (const ComplexNDArray& a, const ComplexNDArray& b);
+
+extern OCTINTERP_API octave_value xpow (float a, float b);
+extern OCTINTERP_API octave_value xpow (float a, const FloatMatrix& b);
+extern OCTINTERP_API octave_value xpow (float a, const FloatComplex& b);
+extern OCTINTERP_API octave_value xpow (float a, const FloatComplexMatrix& b);
+
+extern OCTINTERP_API octave_value xpow (const FloatMatrix& a, float b);
+extern OCTINTERP_API octave_value xpow (const FloatMatrix& a, const FloatComplex& b);
+
+extern OCTINTERP_API octave_value xpow (const FloatDiagMatrix& a, float b);
+extern OCTINTERP_API octave_value xpow (const FloatDiagMatrix& a, const FloatComplex& b);
+
+extern OCTINTERP_API octave_value xpow (const FloatComplex& a, float b);
+extern OCTINTERP_API octave_value xpow (const FloatComplex& a, const FloatMatrix& b);
+extern OCTINTERP_API octave_value xpow (const FloatComplex& a, const FloatComplex& b);
+extern OCTINTERP_API octave_value xpow (const FloatComplex& a, const FloatComplexMatrix& b);
+
+extern OCTINTERP_API octave_value xpow (const FloatComplexMatrix& a, float b);
+extern OCTINTERP_API octave_value xpow (const FloatComplexMatrix& a, const FloatComplex& b);
+
+extern OCTINTERP_API octave_value xpow (const FloatComplexDiagMatrix& a, float b);
+extern OCTINTERP_API octave_value xpow (const FloatComplexDiagMatrix& a, const FloatComplex& b);
+
+extern OCTINTERP_API octave_value elem_xpow (float a, const FloatMatrix& b);
+extern OCTINTERP_API octave_value elem_xpow (float a, const FloatComplexMatrix& b);
+
+extern OCTINTERP_API octave_value elem_xpow (const FloatMatrix& a, float b);
+extern OCTINTERP_API octave_value elem_xpow (const FloatMatrix& a, const FloatMatrix& b);
+extern OCTINTERP_API octave_value elem_xpow (const FloatMatrix& a, const FloatComplex& b);
+extern OCTINTERP_API octave_value elem_xpow (const FloatMatrix& a, const FloatComplexMatrix& b);
+
+extern OCTINTERP_API octave_value elem_xpow (const FloatComplex& a, const FloatMatrix& b);
+extern OCTINTERP_API octave_value elem_xpow (const FloatComplex& a, const FloatComplexMatrix& b);
+
+extern OCTINTERP_API octave_value elem_xpow (const FloatComplexMatrix& a, float b);
+extern OCTINTERP_API octave_value elem_xpow (const FloatComplexMatrix& a, const FloatMatrix& b);
+extern OCTINTERP_API octave_value elem_xpow (const FloatComplexMatrix& a, const FloatComplex& b);
+extern OCTINTERP_API octave_value elem_xpow (const FloatComplexMatrix& a, const FloatComplexMatrix& b);
+
+
+extern OCTINTERP_API octave_value elem_xpow (float a, const FloatNDArray& b);
+extern OCTINTERP_API octave_value elem_xpow (float a, const FloatComplexNDArray& b);
+
+extern OCTINTERP_API octave_value elem_xpow (const FloatNDArray& a, float b);
+extern OCTINTERP_API octave_value elem_xpow (const FloatNDArray& a, const FloatNDArray& b);
+extern OCTINTERP_API octave_value elem_xpow (const FloatNDArray& a, const FloatComplex& b);
+extern OCTINTERP_API octave_value elem_xpow (const FloatNDArray& a, const FloatComplexNDArray& b);
+
+extern OCTINTERP_API octave_value elem_xpow (const FloatComplex& a, const FloatNDArray& b);
+extern OCTINTERP_API octave_value elem_xpow (const FloatComplex& a, const FloatComplexNDArray& b);
+
+extern OCTINTERP_API octave_value elem_xpow (const FloatComplexNDArray& a, float b);
+extern OCTINTERP_API octave_value elem_xpow (const FloatComplexNDArray& a, const FloatNDArray& b);
+extern OCTINTERP_API octave_value elem_xpow (const FloatComplexNDArray& a, const FloatComplex& b);
+extern OCTINTERP_API octave_value elem_xpow (const FloatComplexNDArray& a, const FloatComplexNDArray& b);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/zfstream.cc	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,625 @@
+/*
+
+Copyright (C) 2005-2012 Ludwig Schwardt, Kevin Ruland
+
+
+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/>.
+
+*/
+
+/*
+
+ This file is adapted from the zlib 1.2.2 contrib/iostream3 code,
+ written by
+
+   Ludwig Schwardt <schwardt@sun.ac.za>
+   original version by Kevin Ruland <kevin@rodin.wustl.edu>
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <iostream>
+
+#include "zfstream.h"
+
+#ifdef HAVE_ZLIB
+
+#include <cstring>          // for strcpy, strcat, strlen (mode strings)
+#include <cstdio>           // for BUFSIZ
+
+// Internal buffer sizes (default and "unbuffered" versions)
+#define STASHED_CHARACTERS 16
+#define BIGBUFSIZE (256 * 1024 + STASHED_CHARACTERS)
+#define SMALLBUFSIZE 1
+
+/*****************************************************************************/
+
+// Default constructor
+gzfilebuf::gzfilebuf ()
+: file(0), io_mode(std::ios_base::openmode(0)), own_fd(false),
+  buffer(0), buffer_size(BIGBUFSIZE), own_buffer(true)
+{
+  // No buffers to start with
+  this->disable_buffer ();
+}
+
+// Destructor
+gzfilebuf::~gzfilebuf ()
+{
+  // Sync output buffer and close only if responsible for file
+  // (i.e. attached streams should be left open at this stage)
+  this->sync ();
+  if (own_fd)
+    this->close ();
+  // Make sure internal buffer is deallocated
+  this->disable_buffer ();
+}
+
+// Set compression level and strategy
+int
+gzfilebuf::setcompression (int comp_level,
+                           int comp_strategy)
+{
+  return gzsetparams (file, comp_level, comp_strategy);
+}
+
+// Open gzipped file
+gzfilebuf*
+gzfilebuf::open (const char *name,
+                 std::ios_base::openmode mode)
+{
+  // Fail if file already open
+  if (this->is_open ())
+    return 0;
+  // Don't support simultaneous read/write access (yet)
+  if ((mode & std::ios_base::in) && (mode & std::ios_base::out))
+    return 0;
+
+  // Build mode string for gzopen and check it [27.8.1.3.2]
+  char char_mode[6] = "\0\0\0\0\0";
+  if (! this->open_mode (mode, char_mode))
+    return 0;
+
+  // Attempt to open file
+  if ((file = gzopen (name, char_mode)) == 0)
+    return 0;
+
+  // On success, allocate internal buffer and set flags
+  this->enable_buffer ();
+  io_mode = mode;
+  own_fd = true;
+  return this;
+}
+
+// Attach to gzipped file
+gzfilebuf*
+gzfilebuf::attach (int fd,
+                   std::ios_base::openmode mode)
+{
+  // Fail if file already open
+  if (this->is_open ())
+    return 0;
+  // Don't support simultaneous read/write access (yet)
+  if ((mode & std::ios_base::in) && (mode & std::ios_base::out))
+    return 0;
+
+  // Build mode string for gzdopen and check it [27.8.1.3.2]
+  char char_mode[6] = "\0\0\0\0\0";
+  if (! this->open_mode (mode, char_mode))
+    return 0;
+
+  // Attempt to attach to file
+  if ((file = gzdopen (fd, char_mode)) == 0)
+    return 0;
+
+  // On success, allocate internal buffer and set flags
+  this->enable_buffer ();
+  io_mode = mode;
+  own_fd = false;
+  return this;
+}
+
+// Close gzipped file
+gzfilebuf*
+gzfilebuf::close ()
+{
+  // Fail immediately if no file is open
+  if (! this->is_open ())
+    return 0;
+  // Assume success
+  gzfilebuf* retval = this;
+  // Attempt to sync and close gzipped file
+  if (this->sync () == -1)
+    retval = 0;
+  if (gzclose (file) < 0)
+    retval = 0;
+  // File is now gone anyway (postcondition [27.8.1.3.8])
+  file = 0;
+  own_fd = false;
+  // Destroy internal buffer if it exists
+  this->disable_buffer ();
+  return retval;
+}
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+// Convert int open mode to mode string
+bool
+gzfilebuf::open_mode (std::ios_base::openmode mode,
+                      char* c_mode) const
+{
+  // FIXME -- do we need testb?
+  // bool testb = mode & std::ios_base::binary;
+  bool testi = mode & std::ios_base::in;
+  bool testo = mode & std::ios_base::out;
+  bool testt = mode & std::ios_base::trunc;
+  bool testa = mode & std::ios_base::app;
+
+  // Check for valid flag combinations - see [27.8.1.3.2] (Table 92)
+  // Original zfstream hardcoded the compression level to maximum here...
+  // Double the time for less than 1% size improvement seems
+  // excessive though - keeping it at the default level
+  // To change back, just append "9" to the next three mode strings
+  if (!testi && testo && !testt && !testa)
+    strcpy (c_mode, "w");
+  if (!testi && testo && !testt && testa)
+    strcpy (c_mode, "a");
+  if (!testi && testo && testt && !testa)
+    strcpy (c_mode, "w");
+  if (testi && !testo && !testt && !testa)
+    strcpy (c_mode, "r");
+  // No read/write mode yet
+//  if (testi && testo && !testt && !testa)
+//    strcpy(c_mode, "r+");
+//  if (testi && testo && testt && !testa)
+//    strcpy(c_mode, "w+");
+
+  // Mode string should be empty for invalid combination of flags
+  if (strlen (c_mode) == 0)
+    return false;
+
+  strcat (c_mode, "b");
+
+  return true;
+}
+
+// Determine number of characters in internal get buffer
+std::streamsize
+gzfilebuf::showmanyc ()
+{
+  // Calls to underflow will fail if file not opened for reading
+  if (! this->is_open () || !(io_mode & std::ios_base::in))
+    return -1;
+  // Make sure get area is in use
+  if (this->gptr () && (this->gptr () < this->egptr ()))
+    return std::streamsize (this->egptr () - this->gptr ());
+  else
+    return 0;
+}
+
+// Puts back a character to the stream in two cases. Firstly, when there
+// is no putback position available, and secondly when the character putback
+// differs from the one in the file. We can only support the first case
+// with gzipped files.
+gzfilebuf::int_type
+gzfilebuf::pbackfail (gzfilebuf::int_type c)
+{
+  if (this->is_open ())
+    {
+      if (gzseek (file, this->gptr () - this->egptr () - 1, SEEK_CUR) < 0)
+        return traits_type::eof ();
+
+      // Invalidates contents of the buffer
+      enable_buffer ();
+
+      // Attempt to fill internal buffer from gzipped file
+      // (buffer must be guaranteed to exist...)
+      int bytes_read = gzread (file, buffer, buffer_size);
+      // Indicates error or EOF
+      if (bytes_read <= 0)
+        {
+          // Reset get area
+          this->setg (buffer, buffer, buffer);
+          return traits_type::eof ();
+        }
+
+      // Make all bytes read from file available as get area
+      this->setg (buffer, buffer, buffer + bytes_read);
+
+      // If next character in get area differs from putback character
+      // flag a failure
+      gzfilebuf::int_type ret = traits_type::to_int_type (*(this->gptr ()));
+      if (ret != c)
+        return traits_type::eof ();
+      else
+        return ret;
+    }
+  else
+    return traits_type::eof ();
+}
+
+// Fill get area from gzipped file
+gzfilebuf::int_type
+gzfilebuf::underflow ()
+{
+  // If something is left in the get area by chance, return it
+  // (this shouldn't normally happen, as underflow is only supposed
+  // to be called when gptr >= egptr, but it serves as error check)
+  if (this->gptr () && (this->gptr () < this->egptr ()))
+    return traits_type::to_int_type (*(this->gptr ()));
+
+  // If the file hasn't been opened for reading, produce error
+  if (! this->is_open () || !(io_mode & std::ios_base::in))
+    return traits_type::eof ();
+
+  // Copy the final characters to the front of the buffer
+  int stash = 0;
+  if (this->eback () && buffer && buffer_size > STASHED_CHARACTERS)
+    {
+      char_type *ptr1 = buffer;
+      char_type *ptr2 = this->egptr () - STASHED_CHARACTERS + 1;
+      if (ptr2 > this->eback ())
+        while (stash++ <= STASHED_CHARACTERS)
+          *ptr1++ = *ptr2++;
+    }
+
+  // Attempt to fill internal buffer from gzipped file
+  // (buffer must be guaranteed to exist...)
+  int bytes_read = gzread (file, buffer + stash, buffer_size - stash);
+
+  // Indicates error or EOF
+  if (bytes_read <= 0)
+  {
+    // Reset get area
+    this->setg (buffer, buffer, buffer);
+    return traits_type::eof ();
+  }
+  // Make all bytes read from file plus the stash available as get area
+  this->setg (buffer, buffer + stash, buffer + bytes_read + stash);
+
+  // Return next character in get area
+  return traits_type::to_int_type (*(this->gptr ()));
+}
+
+// Write put area to gzipped file
+gzfilebuf::int_type
+gzfilebuf::overflow (int_type c)
+{
+  // Determine whether put area is in use
+  if (this->pbase ())
+  {
+    // Double-check pointer range
+    if (this->pptr () > this->epptr () || this->pptr () < this->pbase ())
+      return traits_type::eof ();
+    // Add extra character to buffer if not EOF
+    if (! traits_type::eq_int_type (c, traits_type::eof ()))
+    {
+      *(this->pptr ()) = traits_type::to_char_type (c);
+      this->pbump (1);
+    }
+    // Number of characters to write to file
+    int bytes_to_write = this->pptr () - this->pbase ();
+    // Overflow doesn't fail if nothing is to be written
+    if (bytes_to_write > 0)
+    {
+      // If the file hasn't been opened for writing, produce error
+      if (! this->is_open () || !(io_mode & std::ios_base::out))
+        return traits_type::eof ();
+      // If gzipped file won't accept all bytes written to it, fail
+      if (gzwrite (file, this->pbase (), bytes_to_write) != bytes_to_write)
+        return traits_type::eof ();
+      // Reset next pointer to point to pbase on success
+      this->pbump (-bytes_to_write);
+    }
+  }
+  // Write extra character to file if not EOF
+  else if (! traits_type::eq_int_type (c, traits_type::eof ()))
+  {
+    // If the file hasn't been opened for writing, produce error
+    if (! this->is_open () || !(io_mode & std::ios_base::out))
+      return traits_type::eof ();
+    // Impromptu char buffer (allows "unbuffered" output)
+    char_type last_char = traits_type::to_char_type (c);
+    // If gzipped file won't accept this character, fail
+    if (gzwrite (file, &last_char, 1) != 1)
+      return traits_type::eof ();
+  }
+
+  // If you got here, you have succeeded (even if c was EOF)
+  // The return value should therefore be non-EOF
+  if (traits_type::eq_int_type (c, traits_type::eof ()))
+    return traits_type::not_eof (c);
+  else
+    return c;
+}
+
+// Assign new buffer
+std::streambuf*
+gzfilebuf::setbuf (char_type* p,
+                   std::streamsize n)
+{
+  // First make sure stuff is sync'ed, for safety
+  if (this->sync () == -1)
+    return 0;
+  // If buffering is turned off on purpose via setbuf(0,0), still allocate one...
+  // "Unbuffered" only really refers to put [27.8.1.4.10], while get needs at
+  // least a buffer of size 1 (very inefficient though, therefore make it bigger?)
+  // This follows from [27.5.2.4.3]/12 (gptr needs to point at something, it seems)
+  if (!p || !n)
+  {
+    // Replace existing buffer (if any) with small internal buffer
+    this->disable_buffer ();
+    buffer = 0;
+    buffer_size = 0;
+    own_buffer = true;
+    this->enable_buffer ();
+  }
+  else
+  {
+    // Replace existing buffer (if any) with external buffer
+    this->disable_buffer ();
+    buffer = p;
+    buffer_size = n;
+    own_buffer = false;
+    this->enable_buffer ();
+  }
+  return this;
+}
+
+// Write put area to gzipped file (i.e. ensures that put area is empty)
+int
+gzfilebuf::sync ()
+{
+  return traits_type::eq_int_type (this->overflow (), traits_type::eof ()) ? -1 : 0;
+}
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+// Allocate internal buffer
+void
+gzfilebuf::enable_buffer ()
+{
+  // If internal buffer required, allocate one
+  if (own_buffer && !buffer)
+  {
+    // Check for buffered vs. "unbuffered"
+    if (buffer_size > 0)
+    {
+      // Allocate internal buffer
+      buffer = new char_type [buffer_size];
+      // Get area starts empty and will be expanded by underflow as need arises
+      this->setg (buffer, buffer, buffer);
+      // Setup entire internal buffer as put area.
+      // The one-past-end pointer actually points to the last element of the buffer,
+      // so that overflow(c) can safely add the extra character c to the sequence.
+      // These pointers remain in place for the duration of the buffer
+      this->setp (buffer, buffer + buffer_size - 1);
+    }
+    else
+    {
+      // Even in "unbuffered" case, (small?) get buffer is still required
+      buffer_size = SMALLBUFSIZE;
+      buffer = new char_type [buffer_size];
+      this->setg (buffer, buffer, buffer);
+      // "Unbuffered" means no put buffer
+      this->setp (0, 0);
+    }
+  }
+  else
+  {
+    // If buffer already allocated, reset buffer pointers just to make sure no
+    // stale chars are lying around
+    this->setg (buffer, buffer, buffer);
+    this->setp (buffer, buffer + buffer_size - 1);
+  }
+}
+
+// Destroy internal buffer
+void
+gzfilebuf::disable_buffer ()
+{
+  // If internal buffer exists, deallocate it
+  if (own_buffer && buffer)
+  {
+    // Preserve unbuffered status by zeroing size
+    if (! this->pbase ())
+      buffer_size = 0;
+    delete[] buffer;
+    buffer = 0;
+    this->setg (0, 0, 0);
+    this->setp (0, 0);
+  }
+  else
+  {
+    // Reset buffer pointers to initial state if external buffer exists
+    this->setg (buffer, buffer, buffer);
+    if (buffer)
+      this->setp (buffer, buffer + buffer_size - 1);
+    else
+      this->setp (0, 0);
+  }
+}
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+// Seek functions
+gzfilebuf::pos_type
+gzfilebuf::seekoff (off_type off, std::ios_base::seekdir way,
+                   std::ios_base::openmode)
+{
+  pos_type ret = pos_type (off_type (-1));
+
+  if (this->is_open ())
+    {
+      off_type computed_off = off;
+
+      if ((io_mode & std::ios_base::in) && way == std::ios_base::cur)
+        computed_off += this->gptr () - this->egptr ();
+
+      if (way == std::ios_base::beg)
+        ret = pos_type (gzseek (file, computed_off, SEEK_SET));
+      else if (way == std::ios_base::cur)
+        ret = pos_type (gzseek (file, computed_off, SEEK_CUR));
+      else
+        // Can't seek from end of a gzipped file, so this will give -1
+        ret = pos_type (gzseek (file, computed_off, SEEK_END));
+
+      if (io_mode & std::ios_base::in)
+        // Invalidates contents of the buffer
+        enable_buffer ();
+      else
+        // flush contents of buffer to file
+        overflow ();
+    }
+
+  return ret;
+}
+
+gzfilebuf::pos_type
+gzfilebuf::seekpos (pos_type sp, std::ios_base::openmode)
+{
+  pos_type ret = pos_type (off_type (-1));
+
+  if (this->is_open ())
+    {
+      ret = pos_type (gzseek (file, sp, SEEK_SET));
+
+      if (io_mode & std::ios_base::in)
+        // Invalidates contents of the buffer
+        enable_buffer ();
+      else
+        // flush contents of buffer to file
+        overflow ();
+    }
+
+  return ret;
+}
+
+/*****************************************************************************/
+
+// Default constructor initializes stream buffer
+gzifstream::gzifstream ()
+: std::istream (0), sb ()
+{ this->init (&sb); }
+
+// Initialize stream buffer and open file
+gzifstream::gzifstream (const char* name,
+                        std::ios_base::openmode mode)
+: std::istream (0), sb ()
+{
+  this->init (&sb);
+  this->open (name, mode);
+}
+
+// Initialize stream buffer and attach to file
+gzifstream::gzifstream (int fd,
+                        std::ios_base::openmode mode)
+: std::istream (0), sb ()
+{
+  this->init (&sb);
+  this->attach (fd, mode);
+}
+
+// Open file and go into fail() state if unsuccessful
+void
+gzifstream::open (const char* name,
+                  std::ios_base::openmode mode)
+{
+  if (! sb.open (name, mode | std::ios_base::in))
+    this->setstate (std::ios_base::failbit);
+  else
+    this->clear ();
+}
+
+// Attach to file and go into fail() state if unsuccessful
+void
+gzifstream::attach (int fd,
+                    std::ios_base::openmode mode)
+{
+  if (! sb.attach (fd, mode | std::ios_base::in))
+    this->setstate (std::ios_base::failbit);
+  else
+    this->clear ();
+}
+
+// Close file
+void
+gzifstream::close ()
+{
+  if (! sb.close ())
+    this->setstate (std::ios_base::failbit);
+}
+
+/*****************************************************************************/
+
+// Default constructor initializes stream buffer
+gzofstream::gzofstream ()
+: std::ostream (0), sb ()
+{ this->init (&sb); }
+
+// Initialize stream buffer and open file
+gzofstream::gzofstream (const char* name,
+                        std::ios_base::openmode mode)
+: std::ostream (0), sb ()
+{
+  this->init (&sb);
+  this->open (name, mode);
+}
+
+// Initialize stream buffer and attach to file
+gzofstream::gzofstream (int fd,
+                        std::ios_base::openmode mode)
+: std::ostream (0), sb ()
+{
+  this->init (&sb);
+  this->attach (fd, mode);
+}
+
+// Open file and go into fail() state if unsuccessful
+void
+gzofstream::open (const char* name,
+                  std::ios_base::openmode mode)
+{
+  if (! sb.open (name, mode | std::ios_base::out))
+    this->setstate (std::ios_base::failbit);
+  else
+    this->clear ();
+}
+
+// Attach to file and go into fail() state if unsuccessful
+void
+gzofstream::attach (int fd,
+                    std::ios_base::openmode mode)
+{
+  if (! sb.attach (fd, mode | std::ios_base::out))
+    this->setstate (std::ios_base::failbit);
+  else
+    this->clear ();
+}
+
+// Close file
+void
+gzofstream::close ()
+{
+  if (! sb.close ())
+    this->setstate (std::ios_base::failbit);
+}
+
+#endif // HAVE_ZLIB
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/interp-core/zfstream.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,515 @@
+/*
+
+Copyright (C) 2005-2012 Ludwig Schwardt, Kevin Ruland
+
+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/>.
+
+*/
+
+/*
+
+ This file is adapted from the zlib 1.2.2 contrib/iostream3 code,
+ written by
+
+   Ludwig Schwardt <schwardt@sun.ac.za>
+   original version by Kevin Ruland <kevin@rodin.wustl.edu>
+
+*/
+
+#ifndef ZFSTREAM_H
+#define ZFSTREAM_H
+
+#ifdef HAVE_ZLIB
+
+#include <iosfwd>
+
+#include "zlib.h"
+
+/*****************************************************************************/
+
+/**
+ *  @brief  Gzipped file stream buffer class.
+ *
+ *  This class implements basic_filebuf for gzipped files. It doesn't yet support
+ *  seeking (allowed by zlib but slow/limited), putback and read/write access
+ *  (tricky). Otherwise, it attempts to be a drop-in replacement for the standard
+ *  file streambuf.
+*/
+class gzfilebuf : public std::streambuf
+{
+public:
+  //  Default constructor.
+  gzfilebuf ();
+
+  //  Destructor.
+  virtual
+  ~gzfilebuf ();
+
+  /**
+   *  @brief  Set compression level and strategy on the fly.
+   *  @param  comp_level  Compression level (see zlib.h for allowed values)
+   *  @param  comp_strategy  Compression strategy (see zlib.h for allowed values)
+   *  @return  Z_OK on success, Z_STREAM_ERROR otherwise.
+   *
+   *  Unfortunately, these parameters cannot be modified separately, as the
+   *  previous zfstream version assumed. Since the strategy is seldom changed,
+   *  it can default and setcompression(level) then becomes like the old
+   *  setcompressionlevel(level).
+  */
+  int
+  setcompression (int comp_level,
+                  int comp_strategy = Z_DEFAULT_STRATEGY);
+
+  /**
+   *  @brief  Check if file is open.
+   *  @return  True if file is open.
+  */
+  bool
+  is_open () const { return (file != 0); }
+
+  /**
+   *  @brief  Open gzipped file.
+   *  @param  name  File name.
+   *  @param  mode  Open mode flags.
+   *  @return  @c this on success, NULL on failure.
+  */
+  gzfilebuf*
+  open (const char* name,
+        std::ios_base::openmode mode);
+
+  /**
+   *  @brief  Attach to already open gzipped file.
+   *  @param  fd  File descriptor.
+   *  @param  mode  Open mode flags.
+   *  @return  @c this on success, NULL on failure.
+  */
+  gzfilebuf*
+  attach (int fd,
+          std::ios_base::openmode mode);
+
+  /**
+   *  @brief  Close gzipped file.
+   *  @return  @c this on success, NULL on failure.
+  */
+  gzfilebuf*
+  close ();
+
+protected:
+  /**
+   *  @brief  Convert ios open mode int to mode string used by zlib.
+   *  @return  True if valid mode flag combination.
+  */
+  bool
+  open_mode (std::ios_base::openmode mode,
+             char* c_mode) const;
+
+  /**
+   *  @brief  Number of characters available in stream buffer.
+   *  @return  Number of characters.
+   *
+   *  This indicates number of characters in get area of stream buffer.
+   *  These characters can be read without accessing the gzipped file.
+  */
+  virtual std::streamsize
+  showmanyc ();
+
+  /**
+   *  @brief  Fill get area from gzipped file.
+   *  @return  First character in get area on success, EOF on error.
+   *
+   *  This actually reads characters from gzipped file to stream
+   *  buffer. Always buffered.
+  */
+  virtual int_type
+  underflow ();
+
+  /**
+   *  @brief  Write put area to gzipped file.
+   *  @param  c  Extra character to add to buffer contents.
+   *  @return  Non-EOF on success, EOF on error.
+   *
+   *  This actually writes characters in stream buffer to
+   *  gzipped file. With unbuffered output this is done one
+   *  character at a time.
+  */
+  virtual int_type
+  overflow (int_type c = traits_type::eof ());
+
+  /**
+   *  @brief  Installs external stream buffer.
+   *  @param  p  Pointer to char buffer.
+   *  @param  n  Size of external buffer.
+   *  @return  @c this on success, NULL on failure.
+   *
+   *  Call setbuf(0,0) to enable unbuffered output.
+  */
+  virtual std::streambuf*
+  setbuf (char_type* p,
+          std::streamsize n);
+
+  /**
+   *  @brief  Flush stream buffer to file.
+   *  @return  0 on success, -1 on error.
+   *
+   *  This calls underflow(EOF) to do the job.
+  */
+  virtual int
+  sync ();
+
+  /**
+   *  @brief  Alters the stream positions.
+   *
+   *  Each derived class provides its own appropriate behavior.
+   */
+  virtual pos_type
+  seekoff (off_type off, std::ios_base::seekdir way,
+           std::ios_base::openmode mode =
+           std::ios_base::in|std::ios_base::out);
+
+  /**
+   *  @brief  Alters the stream positions.
+   *
+   *  Each derived class provides its own appropriate behavior.
+   */
+  virtual pos_type
+  seekpos (pos_type sp, std::ios_base::openmode mode =
+           std::ios_base::in|std::ios_base::out);
+
+  virtual int_type
+  pbackfail (int_type c = traits_type::eof ());
+
+//
+// Some future enhancements
+//
+//  virtual int_type uflow();
+//  virtual int_type pbackfail(int_type c = traits_type::eof());
+
+private:
+
+  // No copying!
+
+  gzfilebuf (const gzfilebuf&);
+
+  gzfilebuf& operator = (const gzfilebuf&);
+
+  /**
+   *  @brief  Allocate internal buffer.
+   *
+   *  This function is safe to call multiple times. It will ensure
+   *  that a proper internal buffer exists if it is required. If the
+   *  buffer already exists or is external, the buffer pointers will be
+   *  reset to their original state.
+  */
+  void
+  enable_buffer ();
+
+  /**
+   *  @brief  Destroy internal buffer.
+   *
+   *  This function is safe to call multiple times. It will ensure
+   *  that the internal buffer is deallocated if it exists. In any
+   *  case, it will also reset the buffer pointers.
+  */
+  void
+  disable_buffer ();
+
+  /**
+   *  Underlying file pointer.
+  */
+  gzFile file;
+
+  /**
+   *  Mode in which file was opened.
+  */
+  std::ios_base::openmode io_mode;
+
+  /**
+   *  @brief  True if this object owns file descriptor.
+   *
+   *  This makes the class responsible for closing the file
+   *  upon destruction.
+  */
+  bool own_fd;
+
+  /**
+   *  @brief  Stream buffer.
+   *
+   *  For simplicity this remains allocated on the free store for the
+   *  entire life span of the gzfilebuf object, unless replaced by setbuf.
+  */
+  char_type* buffer;
+
+  /**
+   *  @brief  Stream buffer size.
+   *
+   *  Defaults to system default buffer size (typically 8192 bytes).
+   *  Modified by setbuf.
+  */
+  std::streamsize buffer_size;
+
+  /**
+   *  @brief  True if this object owns stream buffer.
+   *
+   *  This makes the class responsible for deleting the buffer
+   *  upon destruction.
+  */
+  bool own_buffer;
+};
+
+/*****************************************************************************/
+
+/**
+ *  @brief  Gzipped file input stream class.
+ *
+ *  This class implements ifstream for gzipped files. Seeking and putback
+ *  is not supported yet.
+*/
+class gzifstream : public std::istream
+{
+public:
+  //  Default constructor
+  gzifstream ();
+
+  /**
+   *  @brief  Construct stream on gzipped file to be opened.
+   *  @param  name  File name.
+   *  @param  mode  Open mode flags (forced to contain ios::in).
+  */
+  explicit
+  gzifstream (const char* name,
+              std::ios_base::openmode mode = std::ios_base::in);
+
+  /**
+   *  @brief  Construct stream on already open gzipped file.
+   *  @param  fd    File descriptor.
+   *  @param  mode  Open mode flags (forced to contain ios::in).
+  */
+  explicit
+  gzifstream (int fd,
+              std::ios_base::openmode mode = std::ios_base::in);
+
+  /**
+   *  Obtain underlying stream buffer.
+  */
+  gzfilebuf*
+  rdbuf () const
+  { return const_cast<gzfilebuf*>(&sb); }
+
+  /**
+   *  @brief  Check if file is open.
+   *  @return  True if file is open.
+  */
+  bool
+  is_open () { return sb.is_open (); }
+
+  /**
+   *  @brief  Open gzipped file.
+   *  @param  name  File name.
+   *  @param  mode  Open mode flags (forced to contain ios::in).
+   *
+   *  Stream will be in state good() if file opens successfully;
+   *  otherwise in state fail(). This differs from the behavior of
+   *  ifstream, which never sets the state to good() and therefore
+   *  won't allow you to reuse the stream for a second file unless
+   *  you manually clear() the state. The choice is a matter of
+   *  convenience.
+  */
+  void
+  open (const char* name,
+        std::ios_base::openmode mode = std::ios_base::in);
+
+  /**
+   *  @brief  Attach to already open gzipped file.
+   *  @param  fd  File descriptor.
+   *  @param  mode  Open mode flags (forced to contain ios::in).
+   *
+   *  Stream will be in state good() if attach succeeded; otherwise
+   *  in state fail().
+  */
+  void
+  attach (int fd,
+          std::ios_base::openmode mode = std::ios_base::in);
+
+  /**
+   *  @brief  Close gzipped file.
+   *
+   *  Stream will be in state fail() if close failed.
+  */
+  void
+  close ();
+
+private:
+  /**
+   *  Underlying stream buffer.
+  */
+  gzfilebuf sb;
+};
+
+/*****************************************************************************/
+
+/**
+ *  @brief  Gzipped file output stream class.
+ *
+ *  This class implements ofstream for gzipped files. Seeking and putback
+ *  is not supported yet.
+*/
+class gzofstream : public std::ostream
+{
+public:
+  //  Default constructor
+  gzofstream ();
+
+  /**
+   *  @brief  Construct stream on gzipped file to be opened.
+   *  @param  name  File name.
+   *  @param  mode  Open mode flags (forced to contain ios::out).
+  */
+  explicit
+  gzofstream (const char* name,
+              std::ios_base::openmode mode = std::ios_base::out);
+
+  /**
+   *  @brief  Construct stream on already open gzipped file.
+   *  @param  fd    File descriptor.
+   *  @param  mode  Open mode flags (forced to contain ios::out).
+  */
+  explicit
+  gzofstream (int fd,
+              std::ios_base::openmode mode = std::ios_base::out);
+
+  /**
+   *  Obtain underlying stream buffer.
+  */
+  gzfilebuf*
+  rdbuf () const
+  { return const_cast<gzfilebuf*>(&sb); }
+
+  /**
+   *  @brief  Check if file is open.
+   *  @return  True if file is open.
+  */
+  bool
+  is_open () { return sb.is_open (); }
+
+  /**
+   *  @brief  Open gzipped file.
+   *  @param  name  File name.
+   *  @param  mode  Open mode flags (forced to contain ios::out).
+   *
+   *  Stream will be in state good() if file opens successfully;
+   *  otherwise in state fail(). This differs from the behavior of
+   *  ofstream, which never sets the state to good() and therefore
+   *  won't allow you to reuse the stream for a second file unless
+   *  you manually clear() the state. The choice is a matter of
+   *  convenience.
+  */
+  void
+  open (const char* name,
+        std::ios_base::openmode mode = std::ios_base::out);
+
+  /**
+   *  @brief  Attach to already open gzipped file.
+   *  @param  fd  File descriptor.
+   *  @param  mode  Open mode flags (forced to contain ios::out).
+   *
+   *  Stream will be in state good() if attach succeeded; otherwise
+   *  in state fail().
+  */
+  void
+  attach (int fd,
+          std::ios_base::openmode mode = std::ios_base::out);
+
+  /**
+   *  @brief  Close gzipped file.
+   *
+   *  Stream will be in state fail() if close failed.
+  */
+  void
+  close ();
+
+private:
+  /**
+   *  Underlying stream buffer.
+  */
+  gzfilebuf sb;
+};
+
+/*****************************************************************************/
+
+/**
+ *  @brief  Gzipped file output stream manipulator class.
+ *
+ *  This class defines a two-argument manipulator for gzofstream. It is used
+ *  as base for the setcompression(int,int) manipulator.
+*/
+template<typename T1, typename T2>
+  class gzomanip2
+  {
+  public:
+    // Allows insertor to peek at internals
+    template <typename Ta, typename Tb>
+      friend gzofstream&
+      operator<<(gzofstream&,
+                 const gzomanip2<Ta,Tb>&);
+
+    // Constructor
+    gzomanip2 (gzofstream& (*f)(gzofstream&, T1, T2),
+               T1 v1,
+               T2 v2);
+  private:
+    // Underlying manipulator function
+    gzofstream&
+    (*func)(gzofstream&, T1, T2);
+
+    // Arguments for manipulator function
+    T1 val1;
+    T2 val2;
+  };
+
+/*****************************************************************************/
+
+// Manipulator function thunks through to stream buffer
+inline gzofstream&
+setcompression (gzofstream &gzs, int l, int s = Z_DEFAULT_STRATEGY)
+{
+  (gzs.rdbuf ())->setcompression (l, s);
+  return gzs;
+}
+
+// Manipulator constructor stores arguments
+template<typename T1, typename T2>
+  inline
+  gzomanip2<T1,T2>::gzomanip2 (gzofstream &(*f)(gzofstream &, T1, T2),
+                               T1 v1,
+                               T2 v2)
+  : func(f), val1(v1), val2(v2)
+  { }
+
+// Insertor applies underlying manipulator function to stream
+template<typename T1, typename T2>
+  inline gzofstream&
+  operator<<(gzofstream& s, const gzomanip2<T1,T2>& m)
+  { return (*m.func)(s, m.val1, m.val2); }
+
+// Insert this onto stream to simplify setting of compression level
+inline gzomanip2<int,int>
+setcompression (int l, int s = Z_DEFAULT_STRATEGY)
+{ return gzomanip2<int,int>(&setcompression, l, s); }
+
+#endif // HAVE_ZLIB
+
+#endif // ZFSTREAM_H
--- a/src/interpfcn/module.mk	Fri Aug 03 10:14:57 2012 -0500
+++ b/src/interpfcn/module.mk	Fri Aug 03 13:18:21 2012 -0700
@@ -1,5 +1,7 @@
 EXTRA_DIST += \
-  interpfcn/module.mk
+  interpfcn/module.mk \
+  interpfcn/defaults.in.h \
+  interpfcn/graphics.in.h
 
 INTERPFCN_INCLUDES = \
   interpfcn/data.h \
@@ -63,3 +65,9 @@
 	$(AWK) -v emit_graphics_props=1 -f $(srcdir)/genprops.awk $< > $@-t
 	mv $@-t $@
 
+## FIXME: Do these rules work correctly after transplant to interpfcn/ dir?
+__fltk_uigetfile__.lo __fltk_uigetfile__.o: \
+  AM_CXXFLAGS := $(filter-out $(DLL_CXXDEFS), $(AM_CXXFLAGS) $(GRAPHICS_CFLAGS))
+
+__init_fltk__.lo __init_fltk__.o: \
+  AM_CXXFLAGS := $(filter-out $(DLL_CXXDEFS), $(AM_CXXFLAGS) $(GRAPHICS_CFLAGS))
--- a/src/jit-ir.cc	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,649 +0,0 @@
-/*
-
-Copyright (C) 2012 Max Brister <max@2bass.com>
-
-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/>.
-
-*/
-
-// defines required by llvm
-#define __STDC_LIMIT_MACROS
-#define __STDC_CONSTANT_MACROS
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifdef HAVE_LLVM
-
-#include "jit-ir.h"
-
-#include <llvm/BasicBlock.h>
-#include <llvm/Instructions.h>
-
-#include "error.h"
-#include "pt-jit.h"
-
-// -------------------- jit_use --------------------
-jit_block *
-jit_use::user_parent (void) const
-{
-  return muser->parent ();
-}
-
-// -------------------- jit_value --------------------
-jit_value::~jit_value (void)
-{}
-
-jit_block *
-jit_value::first_use_block (void)
-{
-  jit_use *use = first_use ();
-  while (use)
-    {
-      if (! isa<jit_error_check> (use->user ()))
-        return use->user_parent ();
-
-      use = use->next ();
-    }
-
-  return 0;
-}
-
-void
-jit_value::replace_with (jit_value *value)
-{
-  while (first_use ())
-    {
-      jit_instruction *user = first_use ()->user ();
-      size_t idx = first_use ()->index ();
-      user->stash_argument (idx, value);
-    }
-}
-
-#define JIT_METH(clname)                                \
-  void                                                  \
-  jit_ ## clname::accept (jit_ir_walker& walker)        \
-  {                                                     \
-    walker.visit (*this);                               \
-  }
-
-JIT_VISIT_IR_NOTEMPLATE
-#undef JIT_METH
-
-std::ostream&
-operator<< (std::ostream& os, const jit_value& value)
-{
-  return value.short_print (os);
-}
-
-std::ostream&
-jit_print (std::ostream& os, jit_value *avalue)
-{
-  if (avalue)
-    return avalue->print (os);
-  return os << "NULL";
-}
-
-// -------------------- jit_instruction --------------------
-void
-jit_instruction::remove (void)
-{
-  if (mparent)
-    mparent->remove (mlocation);
-  resize_arguments (0);
-}
-
-llvm::BasicBlock *
-jit_instruction::parent_llvm (void) const
-{
-  return mparent->to_llvm ();
-}
-
-std::ostream&
-jit_instruction::short_print (std::ostream& os) const
-{
-  if (type ())
-    jit_print (os, type ()) << ": ";
-  return os << "#" << mid;
-}
-
-void
-jit_instruction::do_construct_ssa (size_t start, size_t end)
-{
-  for (size_t i = start; i < end; ++i)
-    {
-      jit_value *arg = argument (i);
-      jit_variable *var = dynamic_cast<jit_variable *> (arg);
-      if (var && var->has_top ())
-        stash_argument (i, var->top ());
-    }
-}
-
-// -------------------- jit_block --------------------
-void
-jit_block::replace_with (jit_value *value)
-{
-  assert (isa<jit_block> (value));
-  jit_block *block = static_cast<jit_block *> (value);
-
-  jit_value::replace_with (block);
-
-  while (ILIST_T::first_use ())
-    {
-      jit_phi_incomming *incomming = ILIST_T::first_use ();
-      incomming->stash_value (block);
-    }
-}
-
-void
-jit_block::replace_in_phi (jit_block *ablock, jit_block *with)
-{
-  jit_phi_incomming *node = ILIST_T::first_use ();
-  while (node)
-    {
-      jit_phi_incomming *prev = node;
-      node = node->next ();
-
-      if (prev->user_parent () == ablock)
-        prev->stash_value (with);
-    }
-}
-
-jit_block *
-jit_block::maybe_merge ()
-{
-  if (successor_count () == 1 && successor (0) != this
-      && (successor (0)->use_count () == 1 || instructions.size () == 1))
-    {
-      jit_block *to_merge = successor (0);
-      merge (*to_merge);
-      return to_merge;
-    }
-
-  return 0;
-}
-
-void
-jit_block::merge (jit_block& block)
-{
-  // the merge block will contain a new terminator
-  jit_terminator *old_term = terminator ();
-  if (old_term)
-    old_term->remove ();
-
-  bool was_empty = end () == begin ();
-  iterator merge_begin = end ();
-  if (! was_empty)
-    --merge_begin;
-
-  instructions.splice (end (), block.instructions);
-  if (was_empty)
-    merge_begin = begin ();
-  else
-    ++merge_begin;
-
-  // now merge_begin points to the start of the new instructions, we must
-  // update their parent information
-  for (iterator iter = merge_begin; iter != end (); ++iter)
-    {
-      jit_instruction *instr = *iter;
-      instr->stash_parent (this, iter);
-    }
-
-  block.replace_with (this);
-}
-
-jit_instruction *
-jit_block::prepend (jit_instruction *instr)
-{
-  instructions.push_front (instr);
-  instr->stash_parent (this, instructions.begin ());
-  return instr;
-}
-
-jit_instruction *
-jit_block::prepend_after_phi (jit_instruction *instr)
-{
-  // FIXME: Make this O(1)
-  for (iterator iter = begin (); iter != end (); ++iter)
-    {
-      jit_instruction *temp = *iter;
-      if (! isa<jit_phi> (temp))
-        {
-          insert_before (iter, instr);
-          return instr;
-        }
-    }
-
-  return append (instr);
-}
-
-void
-jit_block::internal_append (jit_instruction *instr)
-{
-  instructions.push_back (instr);
-  instr->stash_parent (this, --instructions.end ());
-}
-
-jit_instruction *
-jit_block::insert_before (iterator loc, jit_instruction *instr)
-{
-  iterator iloc = instructions.insert (loc, instr);
-  instr->stash_parent (this, iloc);
-  return instr;
-}
-
-jit_instruction *
-jit_block::insert_after (iterator loc, jit_instruction *instr)
-{
-  ++loc;
-  iterator iloc = instructions.insert (loc, instr);
-  instr->stash_parent (this, iloc);
-  return instr;
-}
-
-jit_terminator *
-jit_block::terminator (void) const
-{
-  assert (this);
-  if (instructions.empty ())
-    return 0;
-
-  jit_instruction *last = instructions.back ();
-  return dynamic_cast<jit_terminator *> (last);
-}
-
-bool
-jit_block::branch_alive (jit_block *asucc) const
-{
-  return terminator ()->alive (asucc);
-}
-
-jit_block *
-jit_block::successor (size_t i) const
-{
-  jit_terminator *term = terminator ();
-  return term->successor (i);
-}
-
-size_t
-jit_block::successor_count (void) const
-{
-  jit_terminator *term = terminator ();
-  return term ? term->successor_count () : 0;
-}
-
-llvm::BasicBlock *
-jit_block::to_llvm (void) const
-{
-  return llvm::cast<llvm::BasicBlock> (llvm_value);
-}
-
-std::ostream&
-jit_block::print_dom (std::ostream& os) const
-{
-  short_print (os);
-  os << ":\n";
-  os << "  mid: " << mid << std::endl;
-  os << "  predecessors: ";
-  for (jit_use *use = first_use (); use; use = use->next ())
-    os << *use->user_parent () << " ";
-  os << std::endl;
-
-  os << "  successors: ";
-  for (size_t i = 0; i < successor_count (); ++i)
-    os << *successor (i) << " ";
-  os << std::endl;
-
-  os << "  idom: ";
-  if (idom)
-    os << *idom;
-  else
-    os << "NULL";
-  os << std::endl;
-  os << "  df: ";
-  for (df_iterator iter = df_begin (); iter != df_end (); ++iter)
-    os << **iter << " ";
-  os << std::endl;
-
-  os << "  dom_succ: ";
-  for (size_t i = 0; i < dom_succ.size (); ++i)
-    os << *dom_succ[i] << " ";
-
-  return os << std::endl;
-}
-
-void
-jit_block::compute_df (size_t avisit_count)
-{
-  if (visited (avisit_count))
-    return;
-
-  if (use_count () >= 2)
-    {
-      for (jit_use *use = first_use (); use; use = use->next ())
-        {
-          jit_block *runner = use->user_parent ();
-          while (runner != idom)
-            {
-              runner->mdf.insert (this);
-              runner = runner->idom;
-            }
-        }
-    }
-
-  for (size_t i = 0; i < successor_count (); ++i)
-    successor (i)->compute_df (avisit_count);
-}
-
-bool
-jit_block::update_idom (size_t avisit_count)
-{
-  if (visited (avisit_count) || ! use_count ())
-    return false;
-
-  bool changed = false;
-  for (jit_use *use = first_use (); use; use = use->next ())
-    {
-      jit_block *pred = use->user_parent ();
-      changed = pred->update_idom (avisit_count) || changed;
-    }
-
-  jit_use *use = first_use ();
-  jit_block *new_idom = use->user_parent ();
-  use = use->next ();
-
-  for (; use; use = use->next ())
-    {
-      jit_block *pred = use->user_parent ();
-      jit_block *pidom = pred->idom;
-      if (pidom)
-        new_idom = idom_intersect (pidom, new_idom);
-    }
-
-  if (idom != new_idom)
-    {
-      idom = new_idom;
-      return true;
-    }
-
-  return changed;
-}
-
-void
-jit_block::pop_all (void)
-{
-  for (iterator iter = begin (); iter != end (); ++iter)
-    {
-      jit_instruction *instr = *iter;
-      instr->pop_variable ();
-    }
-}
-
-jit_block *
-jit_block::maybe_split (jit_convert& convert, jit_block *asuccessor)
-{
-  if (successor_count () > 1)
-    {
-      jit_terminator *term = terminator ();
-      size_t idx = term->successor_index (asuccessor);
-      jit_block *split = convert.create<jit_block> ("phi_split", mvisit_count);
-
-      // try to place splits where they make sense
-      if (id () < asuccessor->id ())
-        convert.insert_before (asuccessor, split);
-      else
-        convert.insert_after (this, split);
-
-      term->stash_argument (idx, split);
-      jit_branch *br = split->append (convert.create<jit_branch> (asuccessor));
-      replace_in_phi (asuccessor, split);
-
-      if (alive ())
-        {
-          split->mark_alive ();
-          br->infer ();
-        }
-
-      return split;
-    }
-
-  return this;
-}
-
-void
-jit_block::create_dom_tree (size_t avisit_count)
-{
-  if (visited (avisit_count))
-    return;
-
-  if (idom != this)
-    idom->dom_succ.push_back (this);
-
-  for (size_t i = 0; i < successor_count (); ++i)
-    successor (i)->create_dom_tree (avisit_count);
-}
-
-jit_block *
-jit_block::idom_intersect (jit_block *i, jit_block *j)
-{
-  while (i && j && i != j)
-    {
-      while (i && i->id () > j->id ())
-        i = i->idom;
-
-      while (i && j && j->id () > i->id ())
-        j = j->idom;
-    }
-
-  return i ? i : j;
-}
-
-// -------------------- jit_phi_incomming --------------------
-
-jit_block *
-jit_phi_incomming::user_parent (void) const
-{ return muser->parent (); }
-
-// -------------------- jit_phi --------------------
-bool
-jit_phi::prune (void)
-{
-  jit_block *p = parent ();
-  size_t new_idx = 0;
-  jit_value *unique = argument (1);
-
-  for (size_t i = 0; i < argument_count (); ++i)
-    {
-      jit_block *inc = incomming (i);
-      if (inc->branch_alive (p))
-        {
-          if (unique != argument (i))
-            unique = 0;
-
-          if (new_idx != i)
-            {
-              stash_argument (new_idx, argument (i));
-              mincomming[new_idx].stash_value (inc);
-            }
-
-          ++new_idx;
-        }
-    }
-
-  if (new_idx != argument_count ())
-    {
-      resize_arguments (new_idx);
-      mincomming.resize (new_idx);
-    }
-
-  assert (argument_count () > 0);
-  if (unique)
-    {
-      replace_with (unique);
-      return true;
-    }
-
-  return false;
-}
-
-bool
-jit_phi::infer (void)
-{
-  jit_block *p = parent ();
-  if (! p->alive ())
-    return false;
-
-  jit_type *infered = 0;
-  for (size_t i = 0; i < argument_count (); ++i)
-    {
-      jit_block *inc = incomming (i);
-      if (inc->branch_alive (p))
-        infered = jit_typeinfo::join (infered, argument_type (i));
-    }
-
-  if (infered != type ())
-    {
-      stash_type (infered);
-      return true;
-    }
-
-  return false;
-}
-
-llvm::PHINode *
-jit_phi::to_llvm (void) const
-{
-  return llvm::cast<llvm::PHINode> (jit_value::to_llvm ());
-}
-
-// -------------------- jit_terminator --------------------
-size_t
-jit_terminator::successor_index (const jit_block *asuccessor) const
-{
-  size_t scount = successor_count ();
-  for (size_t i = 0; i < scount; ++i)
-    if (successor (i) == asuccessor)
-      return i;
-
-  panic_impossible ();
-}
-
-bool
-jit_terminator::infer (void)
-{
-  if (! parent ()->alive ())
-    return false;
-
-  bool changed = false;
-  for (size_t i = 0; i < malive.size (); ++i)
-    if (! malive[i] && check_alive (i))
-      {
-        changed = true;
-        malive[i] = true;
-        successor (i)->mark_alive ();
-      }
-
-  return changed;
-}
-
-llvm::TerminatorInst *
-jit_terminator::to_llvm (void) const
-{
-  return llvm::cast<llvm::TerminatorInst> (jit_value::to_llvm ());
-}
-
-// -------------------- jit_call --------------------
-bool
-jit_call::infer (void)
-{
-  // FIXME: explain algorithm
-  for (size_t i = 0; i < argument_count (); ++i)
-    {
-      already_infered[i] = argument_type (i);
-      if (! already_infered[i])
-        return false;
-    }
-
-  jit_type *infered = moperation.result (already_infered);
-  if (! infered && use_count ())
-    {
-      std::stringstream ss;
-      ss << "Missing overload in type inference for ";
-      print (ss, 0);
-      throw jit_fail_exception (ss.str ());
-    }
-
-  if (infered != type ())
-    {
-      stash_type (infered);
-      return true;
-    }
-
-  return false;
-}
-
-// -------------------- jit_magic_end --------------------
-jit_magic_end::jit_magic_end (const std::vector<context>& full_context)
-{
-  // for now we only support end in 1 dimensional indexing
-  resize_arguments (full_context.size ());
-
-  size_t i;
-  std::vector<context>::const_iterator iter;
-  for (iter = full_context.begin (), i = 0; iter != full_context.end (); ++iter,
-         ++i)
-    {
-      if (iter->count != 1)
-        throw jit_fail_exception ("end is only supported in linear contexts");
-      stash_argument (i, iter->value);
-    }
-}
-
-const jit_function&
-jit_magic_end::overload () const
-{
-  jit_value *ctx = resolve_context ();
-  if (ctx)
-    return jit_typeinfo::end (ctx->type ());
-
-  static jit_function null_ret;
-  return null_ret;
-}
-
-jit_value *
-jit_magic_end::resolve_context (void) const
-{
-  // FIXME: We need to have a way of marking functions so we can skip them here
-  return argument_count () ? argument (0) : 0;
-}
-
-bool
-jit_magic_end::infer (void)
-{
-  jit_type *new_type = overload ().result ();
-  if (new_type != type ())
-    {
-      stash_type (new_type);
-      return true;
-    }
-
-  return false;
-}
-
-#endif
--- a/src/jit-ir.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1302 +0,0 @@
-/*
-
-Copyright (C) 2012 Max Brister <max@2bass.com>
-
-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/>.
-
-*/
-
-#if !defined (octave_jit_ir_h)
-#define octave_jit_ir_h 1
-
-#ifdef HAVE_LLVM
-
-#include <list>
-#include <stack>
-#include <set>
-
-#include "jit-typeinfo.h"
-
-// The low level octave jit ir
-// this ir is close to llvm, but contains information for doing type inference.
-// We convert the octave parse tree to this IR directly.
-
-#define JIT_VISIT_IR_NOTEMPLATE                 \
-  JIT_METH(block);                              \
-  JIT_METH(branch);                             \
-  JIT_METH(cond_branch);                        \
-  JIT_METH(call);                               \
-  JIT_METH(extract_argument);                   \
-  JIT_METH(store_argument);                     \
-  JIT_METH(phi);                                \
-  JIT_METH(variable);                           \
-  JIT_METH(error_check);                        \
-  JIT_METH(assign)                              \
-  JIT_METH(argument)                            \
-  JIT_METH(magic_end)
-
-#define JIT_VISIT_IR_CONST                      \
-  JIT_METH(const_bool);                         \
-  JIT_METH(const_scalar);                       \
-  JIT_METH(const_complex);                      \
-  JIT_METH(const_index);                        \
-  JIT_METH(const_string);                       \
-  JIT_METH(const_range)
-
-#define JIT_VISIT_IR_CLASSES                    \
-  JIT_VISIT_IR_NOTEMPLATE                       \
-  JIT_VISIT_IR_CONST
-
-// forward declare all ir classes
-#define JIT_METH(cname)                         \
-  class jit_ ## cname;
-
-JIT_VISIT_IR_NOTEMPLATE
-
-#undef JIT_METH
-
-class jit_convert;
-
-// ABCs which aren't included in  JIT_VISIT_IR_ALL
-class jit_instruction;
-class jit_terminator;
-
-template <typename T, jit_type *(*EXTRACT_T)(void), typename PASS_T = T,
-          bool QUOTE=false>
-class jit_const;
-
-typedef jit_const<bool, jit_typeinfo::get_bool> jit_const_bool;
-typedef jit_const<double, jit_typeinfo::get_scalar> jit_const_scalar;
-typedef jit_const<Complex, jit_typeinfo::get_complex> jit_const_complex;
-typedef jit_const<octave_idx_type, jit_typeinfo::get_index> jit_const_index;
-
-typedef jit_const<std::string, jit_typeinfo::get_string, const std::string&,
-                  true> jit_const_string;
-typedef jit_const<jit_range, jit_typeinfo::get_range, const jit_range&>
-jit_const_range;
-
-class jit_ir_walker;
-class jit_use;
-
-class
-jit_value : public jit_internal_list<jit_value, jit_use>
-{
-public:
-  jit_value (void) : llvm_value (0), ty (0), mlast_use (0),
-                     min_worklist (false) {}
-
-  virtual ~jit_value (void);
-
-  bool in_worklist (void) const
-  {
-    return min_worklist;
-  }
-
-  void stash_in_worklist (bool ain_worklist)
-  {
-    min_worklist = ain_worklist;
-  }
-
-  // The block of the first use which is not a jit_error_check
-  // So this is not necessarily first_use ()->parent ().
-  jit_block *first_use_block (void);
-
-  // replace all uses with
-  virtual void replace_with (jit_value *value);
-
-  jit_type *type (void) const { return ty; }
-
-  llvm::Type *type_llvm (void) const
-  {
-    return ty ? ty->to_llvm () : 0;
-  }
-
-  const std::string& type_name (void) const
-  {
-    return ty->name ();
-  }
-
-  void stash_type (jit_type *new_ty) { ty = new_ty; }
-
-  std::string print_string (void)
-  {
-    std::stringstream ss;
-    print (ss);
-    return ss.str ();
-  }
-
-  jit_instruction *last_use (void) const { return mlast_use; }
-
-  void stash_last_use (jit_instruction *alast_use)
-  {
-    mlast_use = alast_use;
-  }
-
-  virtual bool needs_release (void) const { return false; }
-
-  virtual std::ostream& print (std::ostream& os, size_t indent = 0) const = 0;
-
-  virtual std::ostream& short_print (std::ostream& os) const
-  { return print (os); }
-
-  virtual void accept (jit_ir_walker& walker) = 0;
-
-  bool has_llvm (void) const
-  {
-    return llvm_value;
-  }
-
-  llvm::Value *to_llvm (void) const
-  {
-    assert (llvm_value);
-    return llvm_value;
-  }
-
-  void stash_llvm (llvm::Value *compiled)
-  {
-    llvm_value = compiled;
-  }
-
-protected:
-  std::ostream& print_indent (std::ostream& os, size_t indent = 0) const
-  {
-    for (size_t i = 0; i < indent * 8; ++i)
-      os << " ";
-    return os;
-  }
-
-  llvm::Value *llvm_value;
-private:
-  jit_type *ty;
-  jit_instruction *mlast_use;
-  bool min_worklist;
-};
-
-std::ostream& operator<< (std::ostream& os, const jit_value& value);
-std::ostream& jit_print (std::ostream& os, jit_value *avalue);
-
-class
-jit_use : public jit_internal_node<jit_value, jit_use>
-{
-public:
-  jit_use (void) : muser (0), mindex (0) {}
-
-  // we should really have a move operator, but not until c++11 :(
-  jit_use (const jit_use& use) : muser (0), mindex (0)
-  {
-    *this = use;
-  }
-
-  jit_use& operator= (const jit_use& use)
-  {
-    stash_value (use.value (), use.user (), use.index ());
-    return *this;
-  }
-
-  size_t index (void) const { return mindex; }
-
-  jit_instruction *user (void) const { return muser; }
-
-  jit_block *user_parent (void) const;
-
-  std::list<jit_block *> user_parent_location (void) const;
-
-  void stash_value (jit_value *avalue, jit_instruction *auser = 0,
-                    size_t aindex = -1)
-  {
-    jit_internal_node::stash_value (avalue);
-    mindex = aindex;
-    muser = auser;
-  }
-private:
-  jit_instruction *muser;
-  size_t mindex;
-};
-
-class
-jit_instruction : public jit_value
-{
-public:
-  // FIXME: this code could be so much pretier with varadic templates...
-  jit_instruction (void) : mid (next_id ()), mparent (0)
-  {}
-
-  jit_instruction (size_t nargs) : mid (next_id ()), mparent (0)
-  {
-    already_infered.reserve (nargs);
-    marguments.reserve (nargs);
-  }
-
-#define STASH_ARG(i) stash_argument (i, arg ## i);
-#define JIT_INSTRUCTION_CTOR(N)                                         \
-  jit_instruction (OCT_MAKE_DECL_LIST (jit_value *, arg, N))            \
-  : already_infered (N), marguments (N), mid (next_id ()), mparent (0)  \
-  {                                                                     \
-    OCT_ITERATE_MACRO (STASH_ARG, N);                                   \
-  }
-
-  JIT_INSTRUCTION_CTOR(1)
-  JIT_INSTRUCTION_CTOR(2)
-  JIT_INSTRUCTION_CTOR(3)
-  JIT_INSTRUCTION_CTOR(4)
-
-#undef STASH_ARG
-#undef JIT_INSTRUCTION_CTOR
-
-  jit_instruction (const std::vector<jit_value *>& aarguments)
-  : already_infered (aarguments.size ()), marguments (aarguments.size ()),
-    mid (next_id ()), mparent (0)
-  {
-    for (size_t i = 0; i < aarguments.size (); ++i)
-      stash_argument (i, aarguments[i]);
-  }
-
-  static void reset_ids (void)
-  {
-    next_id (true);
-  }
-
-  jit_value *argument (size_t i) const
-  {
-    return marguments[i].value ();
-  }
-
-  llvm::Value *argument_llvm (size_t i) const
-  {
-    assert (argument (i));
-    return argument (i)->to_llvm ();
-  }
-
-  jit_type *argument_type (size_t i) const
-  {
-    return argument (i)->type ();
-  }
-
-  llvm::Type *argument_type_llvm (size_t i) const
-  {
-    assert (argument (i));
-    return argument_type (i)->to_llvm ();
-  }
-
-  std::ostream& print_argument (std::ostream& os, size_t i) const
-  {
-    if (argument (i))
-      return argument (i)->short_print (os);
-    else
-      return os << "NULL";
-  }
-
-  void stash_argument (size_t i, jit_value *arg)
-  {
-    marguments[i].stash_value (arg, this, i);
-  }
-
-  void push_argument (jit_value *arg)
-  {
-    marguments.push_back (jit_use ());
-    stash_argument (marguments.size () - 1, arg);
-    already_infered.push_back (0);
-  }
-
-  size_t argument_count (void) const
-  {
-    return marguments.size ();
-  }
-
-  void resize_arguments (size_t acount, jit_value *adefault = 0)
-  {
-    size_t old = marguments.size ();
-    marguments.resize (acount);
-    already_infered.resize (acount);
-
-    if (adefault)
-      for (size_t i = old; i < acount; ++i)
-        stash_argument (i, adefault);
-  }
-
-  const std::vector<jit_use>& arguments (void) const { return marguments; }
-
-  // argument types which have been infered already
-  const std::vector<jit_type *>& argument_types (void) const
-  { return already_infered; }
-
-  virtual void push_variable (void) {}
-
-  virtual void pop_variable (void) {}
-
-  virtual void construct_ssa (void)
-  {
-    do_construct_ssa (0, argument_count ());
-  }
-
-  virtual bool infer (void) { return false; }
-
-  void remove (void);
-
-  virtual std::ostream& short_print (std::ostream& os) const;
-
-  jit_block *parent (void) const { return mparent; }
-
-  std::list<jit_instruction *>::iterator location (void) const
-  {
-    return mlocation;
-  }
-
-  llvm::BasicBlock *parent_llvm (void) const;
-
-  void stash_parent (jit_block *aparent,
-                     std::list<jit_instruction *>::iterator alocation)
-  {
-    mparent = aparent;
-    mlocation = alocation;
-  }
-
-  size_t id (void) const { return mid; }
-protected:
-
-  // Do SSA replacement on arguments in [start, end)
-  void do_construct_ssa (size_t start, size_t end);
-
-  std::vector<jit_type *> already_infered;
-private:
-  static size_t next_id (bool reset = false)
-  {
-    static size_t ret = 0;
-    if (reset)
-      return ret = 0;
-
-    return ret++;
-  }
-
-  std::vector<jit_use> marguments;
-
-  size_t mid;
-  jit_block *mparent;
-  std::list<jit_instruction *>::iterator mlocation;
-};
-
-// defnie accept methods for subclasses
-#define JIT_VALUE_ACCEPT                        \
-  virtual void accept (jit_ir_walker& walker);
-
-// for use as a dummy argument during conversion to LLVM
-class
-jit_argument : public jit_value
-{
-public:
-  jit_argument (jit_type *atype, llvm::Value *avalue)
-  {
-    stash_type (atype);
-    stash_llvm (avalue);
-  }
-
-  virtual std::ostream& print (std::ostream& os, size_t indent = 0) const
-  {
-    print_indent (os, indent);
-    return jit_print (os, type ()) << ": DUMMY";
-  }
-
-  JIT_VALUE_ACCEPT;
-};
-
-template <typename T, jit_type *(*EXTRACT_T)(void), typename PASS_T,
-          bool QUOTE>
-class
-jit_const : public jit_value
-{
-public:
-  typedef PASS_T pass_t;
-
-  jit_const (PASS_T avalue) : mvalue (avalue)
-  {
-    stash_type (EXTRACT_T ());
-  }
-
-  PASS_T value (void) const { return mvalue; }
-
-  virtual std::ostream& print (std::ostream& os, size_t indent = 0) const
-  {
-    print_indent (os, indent);
-    jit_print (os, type ()) << ": ";
-    if (QUOTE)
-      os << "\"";
-    os << mvalue;
-    if (QUOTE)
-      os << "\"";
-    return os;
-  }
-
-  JIT_VALUE_ACCEPT;
-private:
-  T mvalue;
-};
-
-class jit_phi_incomming;
-
-class
-jit_block : public jit_value, public jit_internal_list<jit_block,
-                                                       jit_phi_incomming>
-{
-  typedef jit_internal_list<jit_block, jit_phi_incomming> ILIST_T;
-public:
-  typedef std::list<jit_instruction *> instruction_list;
-  typedef instruction_list::iterator iterator;
-  typedef instruction_list::const_iterator const_iterator;
-
-  typedef std::set<jit_block *> df_set;
-  typedef df_set::const_iterator df_iterator;
-
-  static const size_t NO_ID = static_cast<size_t> (-1);
-
-  jit_block (const std::string& aname, size_t avisit_count = 0)
-    : mvisit_count (avisit_count), mid (NO_ID), idom (0), mname (aname),
-      malive (false)
-  {}
-
-  virtual void replace_with (jit_value *value);
-
-  void replace_in_phi (jit_block *ablock, jit_block *with);
-
-  // we have a new internal list, but we want to stay compatable with jit_value
-  jit_use *first_use (void) const { return jit_value::first_use (); }
-
-  size_t use_count (void) const { return jit_value::use_count (); }
-
-  // if a block is alive, then it might be visited during execution
-  bool alive (void) const { return malive; }
-
-  void mark_alive (void) { malive = true; }
-
-  // If we can merge with a successor, do so and return the now empty block
-  jit_block *maybe_merge ();
-
-  // merge another block into this block, leaving the merge block empty
-  void merge (jit_block& merge);
-
-  const std::string& name (void) const { return mname; }
-
-  jit_instruction *prepend (jit_instruction *instr);
-
-  jit_instruction *prepend_after_phi (jit_instruction *instr);
-
-  template <typename T>
-  T *append (T *instr)
-  {
-    internal_append (instr);
-    return instr;
-  }
-
-  jit_instruction *insert_before (iterator loc, jit_instruction *instr);
-
-  jit_instruction *insert_before (jit_instruction *loc, jit_instruction *instr)
-  {
-    return insert_before (loc->location (), instr);
-  }
-
-  jit_instruction *insert_after (iterator loc, jit_instruction *instr);
-
-  jit_instruction *insert_after (jit_instruction *loc, jit_instruction *instr)
-  {
-    return insert_after (loc->location (), instr);
-  }
-
-  iterator remove (iterator iter)
-  {
-    jit_instruction *instr = *iter;
-    iter = instructions.erase (iter);
-    instr->stash_parent (0, instructions.end ());
-    return iter;
-  }
-
-  jit_terminator *terminator (void) const;
-
-  // is the jump from pred alive?
-  bool branch_alive (jit_block *asucc) const;
-
-  jit_block *successor (size_t i) const;
-
-  size_t successor_count (void) const;
-
-  iterator begin (void) { return instructions.begin (); }
-
-  const_iterator begin (void) const { return instructions.begin (); }
-
-  iterator end (void) { return instructions.end (); }
-
-  const_iterator end (void) const { return instructions.end (); }
-
-  iterator phi_begin (void);
-
-  iterator phi_end (void);
-
-  iterator nonphi_begin (void);
-
-  // must label before id is valid
-  size_t id (void) const { return mid; }
-
-  // dominance frontier
-  const df_set& df (void) const { return mdf; }
-
-  df_iterator df_begin (void) const { return mdf.begin (); }
-
-  df_iterator df_end (void) const { return mdf.end (); }
-
-  // label with a RPO walk
-  void label (void)
-  {
-    size_t number = 0;
-    label (mvisit_count, number);
-  }
-
-  void label (size_t avisit_count, size_t& number)
-  {
-    if (visited (avisit_count))
-      return;
-
-    for (jit_use *use = first_use (); use; use = use->next ())
-      {
-        jit_block *pred = use->user_parent ();
-        pred->label (avisit_count, number);
-      }
-
-    mid = number++;
-  }
-
-  // See for idom computation algorithm
-  // Cooper, Keith D.; Harvey, Timothy J; and Kennedy, Ken (2001).
-  // "A Simple, Fast Dominance Algorithm"
-  void compute_idom (jit_block *entry_block)
-  {
-    bool changed;
-    entry_block->idom = entry_block;
-    do
-      changed = update_idom (mvisit_count);
-    while (changed);
-  }
-
-  // compute dominance frontier
-  void compute_df (void)
-  {
-    compute_df (mvisit_count);
-  }
-
-  void create_dom_tree (void)
-  {
-    create_dom_tree (mvisit_count);
-  }
-
-  jit_block *dom_successor (size_t idx) const
-  {
-    return dom_succ[idx];
-  }
-
-  size_t dom_successor_count (void) const
-  {
-    return dom_succ.size ();
-  }
-
-  // call pop_varaible on all instructions
-  void pop_all (void);
-
-  virtual std::ostream& print (std::ostream& os, size_t indent = 0) const
-  {
-    print_indent (os, indent);
-    short_print (os) << ":        %pred = ";
-    for (jit_use *use = first_use (); use; use = use->next ())
-      {
-        jit_block *pred = use->user_parent ();
-        os << *pred;
-        if (use->next ())
-          os << ", ";
-      }
-    os << std::endl;
-
-    for (const_iterator iter = begin (); iter != end (); ++iter)
-      {
-        jit_instruction *instr = *iter;
-        instr->print (os, indent + 1) << std::endl;
-      }
-    return os;
-  }
-
-  // ...
-  jit_block *maybe_split (jit_convert& convert, jit_block *asuccessor);
-
-  jit_block *maybe_split (jit_convert& convert, jit_block& asuccessor)
-  {
-    return maybe_split (convert, &asuccessor);
-  }
-
-  // print dominator infomration
-  std::ostream& print_dom (std::ostream& os) const;
-
-  virtual std::ostream& short_print (std::ostream& os) const
-  {
-    os << mname;
-    if (mid != NO_ID)
-      os << mid;
-    return os;
-  }
-
-  llvm::BasicBlock *to_llvm (void) const;
-
-  std::list<jit_block *>::iterator location (void) const
-  { return mlocation; }
-
-  void stash_location (std::list<jit_block *>::iterator alocation)
-  { mlocation = alocation; }
-
-  // used to prevent visiting the same node twice in the graph
-  size_t visit_count (void) const { return mvisit_count; }
-
-  // check if this node has been visited yet at the given visit count. If we
-  // have not been visited yet, mark us as visited.
-  bool visited (size_t avisit_count)
-  {
-    if (mvisit_count <= avisit_count)
-      {
-        mvisit_count = avisit_count + 1;
-        return false;
-      }
-
-    return true;
-  }
-
-  JIT_VALUE_ACCEPT;
-private:
-  void internal_append (jit_instruction *instr);
-
-  void compute_df (size_t avisit_count);
-
-  bool update_idom (size_t avisit_count);
-
-  void create_dom_tree (size_t avisit_count);
-
-  static jit_block *idom_intersect (jit_block *i, jit_block *j);
-
-  size_t mvisit_count;
-  size_t mid;
-  jit_block *idom;
-  df_set mdf;
-  std::vector<jit_block *> dom_succ;
-  std::string mname;
-  instruction_list instructions;
-  bool malive;
-  std::list<jit_block *>::iterator mlocation;
-};
-
-// keeps track of phi functions that use a block on incomming edges
-class
-jit_phi_incomming : public jit_internal_node<jit_block, jit_phi_incomming>
-{
-public:
-  jit_phi_incomming (void) : muser (0) {}
-
-  jit_phi_incomming (jit_phi *auser) : muser (auser) {}
-
-  jit_phi_incomming (const jit_phi_incomming& use) : jit_internal_node ()
-  {
-    *this = use;
-  }
-
-  jit_phi_incomming& operator= (const jit_phi_incomming& use)
-  {
-    stash_value (use.value ());
-    muser = use.muser;
-    return *this;
-  }
-
-  jit_phi *user (void) const { return muser; }
-
-  jit_block *user_parent (void) const;
-private:
-  jit_phi *muser;
-};
-
-// A non-ssa variable
-class
-jit_variable : public jit_value
-{
-public:
-  jit_variable (const std::string& aname) : mname (aname), mlast_use (0) {}
-
-  const std::string &name (void) const { return mname; }
-
-  // manipulate the value_stack, for use during SSA construction. The top of the
-  // value stack represents the current value for this variable
-  bool has_top (void) const
-  {
-    return ! value_stack.empty ();
-  }
-
-  jit_value *top (void) const
-  {
-    return value_stack.top ();
-  }
-
-  void push (jit_instruction *v)
-  {
-    value_stack.push (v);
-    mlast_use = v;
-  }
-
-  void pop (void)
-  {
-    value_stack.pop ();
-  }
-
-  jit_instruction *last_use (void) const
-  {
-    return mlast_use;
-  }
-
-  void stash_last_use (jit_instruction *instr)
-  {
-    mlast_use = instr;
-  }
-
-  // blocks in which we are used
-  void use_blocks (jit_block::df_set& result)
-  {
-    jit_use *use = first_use ();
-    while (use)
-      {
-        result.insert (use->user_parent ());
-        use = use->next ();
-      }
-  }
-
-  virtual std::ostream& print (std::ostream& os, size_t indent = 0) const
-  {
-    return print_indent (os, indent) << mname;
-  }
-
-  JIT_VALUE_ACCEPT;
-private:
-  std::string mname;
-  std::stack<jit_value *> value_stack;
-  jit_instruction *mlast_use;
-};
-
-class
-jit_assign_base : public jit_instruction
-{
-public:
-  jit_assign_base (jit_variable *adest) : jit_instruction (), mdest (adest) {}
-
-  jit_assign_base (jit_variable *adest, size_t npred) : jit_instruction (npred),
-                                                        mdest (adest) {}
-
-  jit_assign_base (jit_variable *adest, jit_value *arg0, jit_value *arg1)
-    : jit_instruction (arg0, arg1), mdest (adest) {}
-
-  jit_variable *dest (void) const { return mdest; }
-
-  virtual void push_variable (void)
-  {
-    mdest->push (this);
-  }
-
-  virtual void pop_variable (void)
-  {
-    mdest->pop ();
-  }
-
-  virtual std::ostream& short_print (std::ostream& os) const
-  {
-    if (type ())
-      jit_print (os, type ()) << ": ";
-
-    dest ()->short_print (os);
-    return os << "#" << id ();
-  }
-private:
-  jit_variable *mdest;
-};
-
-class
-jit_assign : public jit_assign_base
-{
-public:
-  jit_assign (jit_variable *adest, jit_value *asrc)
-    : jit_assign_base (adest, adest, asrc), martificial (false) {}
-
-  jit_value *overwrite (void) const
-  {
-    return argument (0);
-  }
-
-  jit_value *src (void) const
-  {
-    return argument (1);
-  }
-
-  // variables don't get modified in an SSA, but COW requires we modify
-  // variables. An artificial assign is for when a variable gets modified. We
-  // need an assign in the SSA, but the reference counts shouldn't be updated.
-  bool artificial (void) const { return martificial; }
-
-  void mark_artificial (void) { martificial = true; }
-
-  virtual bool infer (void)
-  {
-    jit_type *stype = src ()->type ();
-    if (stype != type())
-      {
-        stash_type (stype);
-        return true;
-      }
-
-    return false;
-  }
-
-  virtual std::ostream& print (std::ostream& os, size_t indent = 0) const
-  {
-    print_indent (os, indent) << *this << " = " << *src ();
-
-    if (artificial ())
-      os << " [artificial]";
-
-    return os;
-  }
-
-  JIT_VALUE_ACCEPT;
-private:
-  bool martificial;
-};
-
-class
-jit_phi : public jit_assign_base
-{
-public:
-  jit_phi (jit_variable *adest, size_t npred)
-    : jit_assign_base (adest, npred)
-  {
-    mincomming.reserve (npred);
-  }
-
-  // removes arguments form dead incomming jumps
-  bool prune (void);
-
-  void add_incomming (jit_block *from, jit_value *value)
-  {
-    push_argument (value);
-    mincomming.push_back (jit_phi_incomming (this));
-    mincomming[mincomming.size () - 1].stash_value (from);
-  }
-
-  jit_block *incomming (size_t i) const
-  {
-    return mincomming[i].value ();
-  }
-
-  llvm::BasicBlock *incomming_llvm (size_t i) const
-  {
-    return incomming (i)->to_llvm ();
-  }
-
-  virtual void construct_ssa (void) {}
-
-  virtual bool infer (void);
-
-  virtual std::ostream& print (std::ostream& os, size_t indent = 0) const
-  {
-    std::stringstream ss;
-    print_indent (ss, indent);
-    short_print (ss) << " phi ";
-    std::string ss_str = ss.str ();
-    std::string indent_str (ss_str.size (), ' ');
-    os << ss_str;
-
-    for (size_t i = 0; i < argument_count (); ++i)
-      {
-        if (i > 0)
-          os << indent_str;
-        os << "| ";
-
-        os << *incomming (i) << " -> ";
-        os << *argument (i);
-
-        if (i + 1 < argument_count ())
-          os << std::endl;
-      }
-
-    return os;
-  }
-
-  llvm::PHINode *to_llvm (void) const;
-
-  JIT_VALUE_ACCEPT;
-private:
-  std::vector<jit_phi_incomming> mincomming;
-};
-
-class
-jit_terminator : public jit_instruction
-{
-public:
-#define JIT_TERMINATOR_CONST(N)                                         \
-  jit_terminator (size_t asuccessor_count,                              \
-                  OCT_MAKE_DECL_LIST (jit_value *, arg, N))             \
-    : jit_instruction (OCT_MAKE_ARG_LIST (arg, N)),                     \
-      malive (asuccessor_count, false) {}
-
-  JIT_TERMINATOR_CONST (1)
-  JIT_TERMINATOR_CONST (2)
-  JIT_TERMINATOR_CONST (3)
-
-#undef JIT_TERMINATOR_CONST
-
-  jit_block *successor (size_t idx = 0) const
-  {
-    return static_cast<jit_block *> (argument (idx));
-  }
-
-  llvm::BasicBlock *successor_llvm (size_t idx = 0) const
-  {
-    return successor (idx)->to_llvm ();
-  }
-
-  size_t successor_index (const jit_block *asuccessor) const;
-
-  std::ostream& print_successor (std::ostream& os, size_t idx = 0) const
-  {
-    if (alive (idx))
-      os << "[live] ";
-    else
-      os << "[dead] ";
-
-    return successor (idx)->short_print (os);
-  }
-
-  // Check if the jump to successor is live
-  bool alive (const jit_block *asuccessor) const
-  {
-    return alive (successor_index (asuccessor));
-  }
-
-  bool alive (size_t idx) const { return malive[idx]; }
-
-  bool alive (int idx) const { return malive[idx]; }
-
-  size_t successor_count (void) const { return malive.size (); }
-
-  virtual bool infer (void);
-
-  llvm::TerminatorInst *to_llvm (void) const;
-protected:
-  virtual bool check_alive (size_t) const { return true; }
-private:
-  std::vector<bool> malive;
-};
-
-class
-jit_branch : public jit_terminator
-{
-public:
-  jit_branch (jit_block *succ) : jit_terminator (1, succ) {}
-
-  virtual size_t successor_count (void) const { return 1; }
-
-  virtual std::ostream& print (std::ostream& os, size_t indent = 0) const
-  {
-    print_indent (os, indent) << "branch: ";
-    return print_successor (os);
-  }
-
-  JIT_VALUE_ACCEPT;
-};
-
-class
-jit_cond_branch : public jit_terminator
-{
-public:
-  jit_cond_branch (jit_value *c, jit_block *ctrue, jit_block *cfalse)
-    : jit_terminator (2, ctrue, cfalse, c) {}
-
-  jit_value *cond (void) const { return argument (2); }
-
-  std::ostream& print_cond (std::ostream& os) const
-  {
-    return cond ()->short_print (os);
-  }
-
-  llvm::Value *cond_llvm (void) const
-  {
-    return cond ()->to_llvm ();
-  }
-
-  virtual size_t successor_count (void) const { return 2; }
-
-  virtual std::ostream& print (std::ostream& os, size_t indent = 0) const
-  {
-    print_indent (os, indent) << "cond_branch: ";
-    print_cond (os) << ", ";
-    print_successor (os, 0) << ", ";
-    return print_successor (os, 1);
-  }
-
-  JIT_VALUE_ACCEPT;
-};
-
-class
-jit_call : public jit_instruction
-{
-public:
-#define JIT_CALL_CONST(N)                                               \
-  jit_call (const jit_operation& aoperation,                            \
-            OCT_MAKE_DECL_LIST (jit_value *, arg, N))                   \
-    : jit_instruction (OCT_MAKE_ARG_LIST (arg, N)), moperation (aoperation) {} \
-                                                                        \
-  jit_call (const jit_operation& (*aoperation) (void),                  \
-            OCT_MAKE_DECL_LIST (jit_value *, arg, N))                   \
-    : jit_instruction (OCT_MAKE_ARG_LIST (arg, N)), moperation (aoperation ()) \
-  {}
-
-  JIT_CALL_CONST (1)
-  JIT_CALL_CONST (2)
-  JIT_CALL_CONST (3)
-  JIT_CALL_CONST (4)
-
-#undef JIT_CALL_CONST
-
-  jit_call (const jit_operation& aoperation,
-            const std::vector<jit_value *>& args)
-  : jit_instruction (args), moperation (aoperation)
-  {}
-
-  const jit_operation& operation (void) const { return moperation; }
-
-  bool can_error (void) const
-  {
-    return overload ().can_error ();
-  }
-
-  const jit_function& overload (void) const
-  {
-    return moperation.overload (argument_types ());
-  }
-
-  virtual bool needs_release (void) const
-  {
-    return type () && jit_typeinfo::get_release (type ()).valid ();
-  }
-
-  virtual std::ostream& print (std::ostream& os, size_t indent = 0) const
-  {
-    print_indent (os, indent);
-
-    if (use_count ())
-      short_print (os) << " = ";
-    os << "call " << moperation.name () << " (";
-
-    for (size_t i = 0; i < argument_count (); ++i)
-      {
-        print_argument (os, i);
-        if (i + 1 < argument_count ())
-          os << ", ";
-      }
-    return os << ")";
-  }
-
-  virtual bool infer (void);
-
-  JIT_VALUE_ACCEPT;
-private:
-  const jit_operation& moperation;
-};
-
-// FIXME: This is just ugly...
-// checks error_state, if error_state is false then goto the normal branche,
-// otherwise goto the error branch
-class
-jit_error_check : public jit_terminator
-{
-public:
-  jit_error_check (jit_call *acheck_for, jit_block *normal, jit_block *error)
-    : jit_terminator (2, error, normal, acheck_for) {}
-
-  jit_call *check_for (void) const
-  {
-    return static_cast<jit_call *> (argument (2));
-  }
-
-  virtual std::ostream& print (std::ostream& os, size_t indent = 0) const
-  {
-    print_indent (os, indent) << "error_check " << *check_for () << ", ";
-    print_successor (os, 1) << ", ";
-    return print_successor (os, 0);
-  }
-
-  JIT_VALUE_ACCEPT;
-protected:
-  virtual bool check_alive (size_t idx) const
-  {
-    return idx == 1 ? true : check_for ()->can_error ();
-  }
-};
-
-// for now only handles the 1D case
-class
-jit_magic_end : public jit_instruction
-{
-public:
-  class
-  context
-  {
-  public:
-    context (void) : value (0), index (0), count (0)
-    {}
-
-    context (jit_value *avalue, size_t aindex, size_t acount)
-      : value (avalue), index (aindex), count (acount)
-    {}
-
-    jit_value *value;
-    size_t index;
-    size_t count;
-  };
-
-  jit_magic_end (const std::vector<context>& full_context);
-
-  const jit_function& overload () const;
-
-  jit_value *resolve_context (void) const;
-
-  virtual bool infer (void);
-
-  virtual std::ostream& short_print (std::ostream& os) const
-  {
-    return os << "magic_end";
-  }
-
-  virtual std::ostream& print (std::ostream& os, size_t indent = 0) const
-  {
-    return short_print (print_indent (os, indent));
-  }
-
-  JIT_VALUE_ACCEPT;
-};
-
-class
-jit_extract_argument : public jit_assign_base
-{
-public:
-  jit_extract_argument (jit_type *atype, jit_variable *adest)
-    : jit_assign_base (adest)
-  {
-    stash_type (atype);
-  }
-
-  const std::string& name (void) const
-  {
-    return dest ()->name ();
-  }
-
-  const jit_function& overload (void) const
-  {
-    return jit_typeinfo::cast (type (), jit_typeinfo::get_any ());
-  }
-
-  virtual std::ostream& print (std::ostream& os, size_t indent = 0) const
-  {
-    print_indent (os, indent);
-
-    return short_print (os) << " = extract " << name ();
-  }
-
-  JIT_VALUE_ACCEPT;
-};
-
-class
-jit_store_argument : public jit_instruction
-{
-public:
-  jit_store_argument (jit_variable *var)
-  : jit_instruction (var), dest (var)
-  {}
-
-  const std::string& name (void) const
-  {
-    return dest->name ();
-  }
-
-  const jit_function& overload (void) const
-  {
-    return jit_typeinfo::cast (jit_typeinfo::get_any (), result_type ());
-  }
-
-  jit_value *result (void) const
-  {
-    return argument (0);
-  }
-
-  jit_type *result_type (void) const
-  {
-    return result ()->type ();
-  }
-
-  llvm::Value *result_llvm (void) const
-  {
-    return result ()->to_llvm ();
-  }
-
-  virtual std::ostream& print (std::ostream& os, size_t indent = 0) const
-  {
-    jit_value *res = result ();
-    print_indent (os, indent) << "store ";
-    dest->short_print (os);
-
-    if (! isa<jit_variable> (res))
-      {
-        os << " = ";
-        res->short_print (os);
-      }
-
-    return os;
-  }
-
-  JIT_VALUE_ACCEPT;
-private:
-  jit_variable *dest;
-};
-
-class
-jit_ir_walker
-{
-public:
-  virtual ~jit_ir_walker () {}
-
-#define JIT_METH(clname) \
-  virtual void visit (jit_ ## clname&) = 0;
-
-  JIT_VISIT_IR_CLASSES;
-
-#undef JIT_METH
-};
-
-template <typename T, jit_type *(*EXTRACT_T)(void), typename PASS_T, bool QUOTE>
-void
-jit_const<T, EXTRACT_T, PASS_T, QUOTE>::accept (jit_ir_walker& walker)
-{
-  walker.visit (*this);
-}
-
-#undef JIT_VALUE_ACCEPT
-
-#endif
-#endif
--- a/src/jit-typeinfo.cc	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2071 +0,0 @@
-/*
-
-Copyright (C) 2012 Max Brister <max@2bass.com>
-
-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/>.
-
-*/
-
-// defines required by llvm
-#define __STDC_LIMIT_MACROS
-#define __STDC_CONSTANT_MACROS
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifdef HAVE_LLVM
-
-#include "jit-typeinfo.h"
-
-#include <llvm/Analysis/Verifier.h>
-#include <llvm/GlobalVariable.h>
-#include <llvm/ExecutionEngine/ExecutionEngine.h>
-#include <llvm/LLVMContext.h>
-#include <llvm/Function.h>
-#include <llvm/Instructions.h>
-#include <llvm/Intrinsics.h>
-#include <llvm/Support/IRBuilder.h>
-#include <llvm/Support/raw_os_ostream.h>
-
-#include "jit-ir.h"
-#include "ov.h"
-#include "ov-builtin.h"
-#include "ov-complex.h"
-#include "ov-scalar.h"
-#include "pager.h"
-
-static llvm::LLVMContext& context = llvm::getGlobalContext ();
-
-jit_typeinfo *jit_typeinfo::instance = 0;
-
-std::ostream& jit_print (std::ostream& os, jit_type *atype)
-{
-  if (! atype)
-    return os << "null";
-  return os << atype->name ();
-}
-
-// function that jit code calls
-extern "C" void
-octave_jit_print_any (const char *name, octave_base_value *obv)
-{
-  obv->print_with_name (octave_stdout, name, true);
-}
-
-extern "C" void
-octave_jit_print_scalar (const char *name, double value)
-{
-  // FIXME: We should avoid allocating a new octave_scalar each time
-  octave_value ov (value);
-  ov.print_with_name (octave_stdout, name);
-}
-
-extern "C" octave_base_value*
-octave_jit_binary_any_any (octave_value::binary_op op, octave_base_value *lhs,
-                           octave_base_value *rhs)
-{
-  octave_value olhs (lhs, true);
-  octave_value orhs (rhs, true);
-  octave_value result = do_binary_op (op, olhs, orhs);
-  octave_base_value *rep = result.internal_rep ();
-  rep->grab ();
-  return rep;
-}
-
-extern "C" octave_idx_type
-octave_jit_compute_nelem (double base, double limit, double inc)
-{
-  Range rng = Range (base, limit, inc);
-  return rng.nelem ();
-}
-
-extern "C" void
-octave_jit_release_any (octave_base_value *obv)
-{
-  obv->release ();
-}
-
-extern "C" void
-octave_jit_release_matrix (jit_matrix *m)
-{
-  delete m->array;
-}
-
-extern "C" octave_base_value *
-octave_jit_grab_any (octave_base_value *obv)
-{
-  obv->grab ();
-  return obv;
-}
-
-extern "C" void
-octave_jit_grab_matrix (jit_matrix *result, jit_matrix *m)
-{
-  *result = *m->array;
-}
-
-extern "C" octave_base_value *
-octave_jit_cast_any_matrix (jit_matrix *m)
-{
-  octave_value ret (*m->array);
-  octave_base_value *rep = ret.internal_rep ();
-  rep->grab ();
-  delete m->array;
-
-  return rep;
-}
-
-extern "C" void
-octave_jit_cast_matrix_any (jit_matrix *ret, octave_base_value *obv)
-{
-  NDArray m = obv->array_value ();
-  *ret = m;
-  obv->release ();
-}
-
-extern "C" octave_base_value *
-octave_jit_cast_any_range (jit_range *rng)
-{
-  Range temp (*rng);
-  octave_value ret (temp);
-  octave_base_value *rep = ret.internal_rep ();
-  rep->grab ();
-
-  return rep;
-}
-extern "C" void
-octave_jit_cast_range_any (jit_range *ret, octave_base_value *obv)
-{
-
-  jit_range r (obv->range_value ());
-  *ret = r;
-  obv->release ();
-}
-
-extern "C" double
-octave_jit_cast_scalar_any (octave_base_value *obv)
-{
-  double ret = obv->double_value ();
-  obv->release ();
-  return ret;
-}
-
-extern "C" octave_base_value *
-octave_jit_cast_any_scalar (double value)
-{
-  return new octave_scalar (value);
-}
-
-extern "C" Complex
-octave_jit_cast_complex_any (octave_base_value *obv)
-{
-  Complex ret = obv->complex_value ();
-  obv->release ();
-  return ret;
-}
-
-extern "C" octave_base_value *
-octave_jit_cast_any_complex (Complex c)
-{
-  if (c.imag () == 0)
-    return new octave_scalar (c.real ());
-  else
-    return new octave_complex (c);
-}
-
-extern "C" void
-octave_jit_gripe_nan_to_logical_conversion (void)
-{
-  try
-    {
-      gripe_nan_to_logical_conversion ();
-    }
-  catch (const octave_execution_exception&)
-    {
-      gripe_library_execution_error ();
-    }
-}
-
-extern "C" void
-octave_jit_ginvalid_index (void)
-{
-  try
-    {
-      gripe_invalid_index ();
-    }
-  catch (const octave_execution_exception&)
-    {
-      gripe_library_execution_error ();
-    }
-}
-
-extern "C" void
-octave_jit_gindex_range (int nd, int dim, octave_idx_type iext,
-                         octave_idx_type ext)
-{
-  try
-    {
-      gripe_index_out_of_range (nd, dim, iext, ext);
-    }
-  catch (const octave_execution_exception&)
-    {
-      gripe_library_execution_error ();
-    }
-}
-
-extern "C" void
-octave_jit_paren_subsasgn_impl (jit_matrix *ret, jit_matrix *mat,
-                                octave_idx_type index, double value)
-{
-  NDArray *array = mat->array;
-  if (array->nelem () < index)
-    array->resize1 (index);
-
-  double *data = array->fortran_vec ();
-  data[index - 1] = value;
-
-  mat->update ();
-  *ret = *mat;
-}
-
-static void
-make_indices (double *indices, octave_idx_type idx_count,
-              Array<idx_vector>& result)
-{
-  result.resize (dim_vector (1, idx_count));
-  for (octave_idx_type i = 0; i < idx_count; ++i)
-    result(i) = idx_vector (indices[i]);
-}
-
-extern "C" double
-octave_jit_paren_scalar (jit_matrix *mat, double *indicies,
-                         octave_idx_type idx_count)
-{
-  // FIXME: Replace this with a more optimal version
-  try
-    {
-      Array<idx_vector> idx;
-      make_indices (indicies, idx_count, idx);
-
-      Array<double> ret = mat->array->index (idx);
-      return ret.xelem (0);
-    }
-  catch (const octave_execution_exception&)
-    {
-      gripe_library_execution_error ();
-      return 0;
-    }
-}
-
-extern "C" void
-octave_jit_paren_scalar_subsasgn (jit_matrix *ret, jit_matrix *mat,
-                                  double *indices, octave_idx_type idx_count,
-                                  double value)
-{
-  // FIXME: Replace this with a more optimal version
-  try
-    {
-      Array<idx_vector> idx;
-      make_indices (indices, idx_count, idx);
-
-      Matrix temp (1, 1);
-      temp.xelem(0) = value;
-      mat->array->assign (idx, temp);
-      ret->update (mat->array);
-    }
-  catch (const octave_execution_exception&)
-    {
-      gripe_library_execution_error ();
-    }
-}
-
-extern "C" void
-octave_jit_paren_subsasgn_matrix_range (jit_matrix *result, jit_matrix *mat,
-                                        jit_range *index, double value)
-{
-  NDArray *array = mat->array;
-  bool done = false;
-
-  // optimize for the simple case (no resizing and no errors)
-  if (*array->jit_ref_count () == 1
-      && index->all_elements_are_ints ())
-    {
-      // this code is similar to idx_vector::fill, but we avoid allocating an
-      // idx_vector and its associated rep
-      octave_idx_type start = static_cast<octave_idx_type> (index->base) - 1;
-      octave_idx_type step = static_cast<octave_idx_type> (index->inc);
-      octave_idx_type nelem = index->nelem;
-      octave_idx_type final = start + nelem * step;
-      if (step < 0)
-        {
-          step = -step;
-          std::swap (final, start);
-        }
-
-      if (start >= 0 && final < mat->slice_len)
-        {
-          done = true;
-
-          double *data = array->jit_slice_data ();
-          if (step == 1)
-            std::fill (data + start, data + start + nelem, value);
-          else
-            {
-              for (octave_idx_type i = start; i < final; i += step)
-                data[i] = value;
-            }
-        }
-    }
-
-  if (! done)
-    {
-      idx_vector idx (*index);
-      NDArray avalue (dim_vector (1, 1));
-      avalue.xelem (0) = value;
-      array->assign (idx, avalue);
-    }
-
-  result->update (array);
-}
-
-extern "C" Complex
-octave_jit_complex_div (Complex lhs, Complex rhs)
-{
-  // see src/OPERATORS/op-cs-cs.cc
-  if (rhs == 0.0)
-    gripe_divide_by_zero ();
-
-  return lhs / rhs;
-}
-
-// FIXME: CP form src/xpow.cc
-static inline int
-xisint (double x)
-{
-  return (D_NINT (x) == x
-          && ((x >= 0 && x < INT_MAX)
-              || (x <= 0 && x > INT_MIN)));
-}
-
-extern "C" Complex
-octave_jit_pow_scalar_scalar (double lhs, double rhs)
-{
-  // FIXME: almost CP from src/xpow.cc
-  if (lhs < 0.0 && ! xisint (rhs))
-    return std::pow (Complex (lhs), rhs);
-  return std::pow (lhs, rhs);
-}
-
-extern "C" Complex
-octave_jit_pow_complex_complex (Complex lhs, Complex rhs)
-{
-  if (lhs.imag () == 0 && rhs.imag () == 0)
-    return octave_jit_pow_scalar_scalar (lhs.real (), rhs.real ());
-  return std::pow (lhs, rhs);
-}
-
-extern "C" Complex
-octave_jit_pow_complex_scalar (Complex lhs, double rhs)
-{
-  if (lhs.imag () == 0)
-    return octave_jit_pow_scalar_scalar (lhs.real (), rhs);
-  return std::pow (lhs, rhs);
-}
-
-extern "C" Complex
-octave_jit_pow_scalar_complex (double lhs, Complex rhs)
-{
-  if (rhs.imag () == 0)
-    return octave_jit_pow_scalar_scalar (lhs, rhs.real ());
-  return std::pow (lhs, rhs);
-}
-
-extern "C" void
-octave_jit_print_matrix (jit_matrix *m)
-{
-  std::cout << *m << std::endl;
-}
-
-static void
-gripe_bad_result (void)
-{
-  error ("incorrect type information given to the JIT compiler");
-}
-
-// FIXME: Add support for multiple outputs
-extern "C" octave_base_value *
-octave_jit_call (octave_builtin::fcn fn, size_t nargin,
-                 octave_base_value **argin, jit_type *result_type)
-{
-  octave_value_list ovl (nargin);
-  for (size_t i = 0; i < nargin; ++i)
-    ovl.xelem (i) = octave_value (argin[i]);
-
-  ovl = fn (ovl, 1);
-
-  // These type checks are not strictly required, but I'm guessing that
-  // incorrect types will be entered on occasion. This will be very difficult to
-  // debug unless we do the sanity check here.
-  if (result_type)
-    {
-      if (ovl.length () != 1)
-        {
-          gripe_bad_result ();
-          return 0;
-        }
-
-      octave_value& result = ovl.xelem (0);
-      jit_type *jtype = jit_typeinfo::join (jit_typeinfo::type_of (result),
-                                            result_type);
-      if (jtype != result_type)
-        {
-          gripe_bad_result ();
-          return 0;
-        }
-
-      octave_base_value *ret = result.internal_rep ();
-      ret->grab ();
-      return ret;
-    }
-
-  if (! (ovl.length () == 0
-         || (ovl.length () == 1 && ovl.xelem (0).is_undefined ())))
-    gripe_bad_result ();
-
-  return 0;
-}
-
-// -------------------- jit_range --------------------
-bool
-jit_range::all_elements_are_ints () const
-{
-  Range r (*this);
-  return r.all_elements_are_ints ();
-}
-
-std::ostream&
-operator<< (std::ostream& os, const jit_range& rng)
-{
-  return os << "Range[" << rng.base << ", " << rng.limit << ", " << rng.inc
-            << ", " << rng.nelem << "]";
-}
-
-// -------------------- jit_matrix --------------------
-
-std::ostream&
-operator<< (std::ostream& os, const jit_matrix& mat)
-{
-  return os << "Matrix[" << mat.ref_count << ", " << mat.slice_data << ", "
-            << mat.slice_len << ", " << mat.dimensions << ", "
-            << mat.array << "]";
-}
-
-// -------------------- jit_type --------------------
-jit_type::jit_type (const std::string& aname, jit_type *aparent,
-                    llvm::Type *allvm_type, int aid) :
-  mname (aname), mparent (aparent), llvm_type (allvm_type), mid (aid),
-  mdepth (aparent ? aparent->mdepth + 1 : 0)
-{
-  std::memset (msret, 0, sizeof (msret));
-  std::memset (mpointer_arg, 0, sizeof (mpointer_arg));
-  std::memset (mpack, 0, sizeof (mpack));
-  std::memset (munpack, 0, sizeof (munpack));
-
-  for (size_t i = 0; i < jit_convention::length; ++i)
-    mpacked_type[i] = llvm_type;
-}
-
-llvm::Type *
-jit_type::to_llvm_arg (void) const
-{
-  return llvm_type ? llvm_type->getPointerTo () : 0;
-}
-
-// -------------------- jit_function --------------------
-jit_function::jit_function () : module (0), llvm_function (0), mresult (0),
-                                call_conv (jit_convention::length),
-                                mcan_error (false)
-{}
-
-jit_function::jit_function (llvm::Module *amodule,
-                            jit_convention::type acall_conv,
-                            const llvm::Twine& aname, jit_type *aresult,
-                            const std::vector<jit_type *>& aargs)
-  : module (amodule), mresult (aresult), args (aargs), call_conv (acall_conv),
-    mcan_error (false)
-{
-  llvm::SmallVector<llvm::Type *, 15> llvm_args;
-
-  llvm::Type *rtype = llvm::Type::getVoidTy (context);
-  if (mresult)
-    {
-      rtype = mresult->packed_type (call_conv);
-      if (sret ())
-        {
-          llvm_args.push_back (rtype->getPointerTo ());
-          rtype = llvm::Type::getVoidTy (context);
-        }
-    }
-
-  for (std::vector<jit_type *>::const_iterator iter = args.begin ();
-       iter != args.end (); ++iter)
-    {
-      jit_type *ty = *iter;
-      assert (ty);
-      llvm::Type *argty = ty->packed_type (call_conv);
-      if (ty->pointer_arg (call_conv))
-        argty = argty->getPointerTo ();
-
-      llvm_args.push_back (argty);
-    }
-
-  // we mark all functinos as external linkage because this prevents llvm
-  // from getting rid of always inline functions
-  llvm::FunctionType *ft = llvm::FunctionType::get (rtype, llvm_args, false);
-  llvm_function = llvm::Function::Create (ft, llvm::Function::ExternalLinkage,
-                                          aname, module);
-  if (call_conv == jit_convention::internal)
-    llvm_function->addFnAttr (llvm::Attribute::AlwaysInline);
-}
-
-jit_function::jit_function (const jit_function& fn, jit_type *aresult,
-                            const std::vector<jit_type *>& aargs)
-  : module (fn.module), llvm_function (fn.llvm_function), mresult (aresult),
-    args (aargs), call_conv (fn.call_conv), mcan_error (fn.mcan_error)
-{
-}
-
-jit_function::jit_function (const jit_function& fn)
-  : module (fn.module), llvm_function (fn.llvm_function), mresult (fn.mresult),
-    args (fn.args), call_conv (fn.call_conv), mcan_error (fn.mcan_error)
-{}
-
-std::string
-jit_function::name (void) const
-{
-  return llvm_function->getName ();
-}
-
-llvm::BasicBlock *
-jit_function::new_block (const std::string& aname,
-                         llvm::BasicBlock *insert_before)
-{
-  return llvm::BasicBlock::Create (context, aname, llvm_function,
-                                   insert_before);
-}
-
-llvm::Value *
-jit_function::call (llvm::IRBuilderD& builder,
-                    const std::vector<jit_value *>& in_args) const
-{
-  if (! valid ())
-    throw jit_fail_exception ("Call not implemented");
-
-  assert (in_args.size () == args.size ());
-  std::vector<llvm::Value *> llvm_args (args.size ());
-  for (size_t i = 0; i < in_args.size (); ++i)
-    llvm_args[i] = in_args[i]->to_llvm ();
-
-  return call (builder, llvm_args);
-}
-
-llvm::Value *
-jit_function::call (llvm::IRBuilderD& builder,
-                    const std::vector<llvm::Value *>& in_args) const
-{
-  if (! valid ())
-    throw jit_fail_exception ("Call not implemented");
-
-  assert (in_args.size () == args.size ());
-  llvm::Function *stacksave
-    = llvm::Intrinsic::getDeclaration (module, llvm::Intrinsic::stacksave);
-  llvm::SmallVector<llvm::Value *, 10> llvm_args;
-  llvm_args.reserve (in_args.size () + sret ());
-
-  llvm::Value *sret_mem = 0;
-  llvm::Value *saved_stack = 0;
-  if (sret ())
-    {
-      saved_stack = builder.CreateCall (stacksave);
-      sret_mem = builder.CreateAlloca (mresult->packed_type (call_conv));
-      llvm_args.push_back (sret_mem);
-    }
-
-  for (size_t i = 0; i < in_args.size (); ++i)
-    {
-      llvm::Value *arg = in_args[i];
-      jit_type::convert_fn convert = args[i]->pack (call_conv);
-      if (convert)
-        arg = convert (builder, arg);
-
-      if (args[i]->pointer_arg (call_conv))
-        {
-          if (! saved_stack)
-            saved_stack = builder.CreateCall (stacksave);
-
-          arg = builder.CreateAlloca (args[i]->to_llvm ());
-          builder.CreateStore (in_args[i], arg);
-        }
-
-      llvm_args.push_back (arg);
-    }
-
-  llvm::Value *ret = builder.CreateCall (llvm_function, llvm_args);
-  if (sret_mem)
-    ret = builder.CreateLoad (sret_mem);
-
-  if (mresult)
-    {
-      jit_type::convert_fn unpack = mresult->unpack (call_conv);
-      if (unpack)
-        ret = unpack (builder, ret);
-    }
-
-  if (saved_stack)
-    {
-      llvm::Function *stackrestore
-        = llvm::Intrinsic::getDeclaration (module,
-                                           llvm::Intrinsic::stackrestore);
-      builder.CreateCall (stackrestore, saved_stack);
-    }
-
-  return ret;
-}
-
-llvm::Value *
-jit_function::argument (llvm::IRBuilderD& builder, size_t idx) const
-{
-  assert (idx < args.size ());
-
-  // FIXME: We should be treating arguments like a list, not a vector. Shouldn't
-  // matter much for now, as the number of arguments shouldn't be much bigger
-  // than 4
-  llvm::Function::arg_iterator iter = llvm_function->arg_begin ();
-  if (sret ())
-    ++iter;
-
-  for (size_t i = 0; i < idx; ++i, ++iter);
-
-  if (args[idx]->pointer_arg (call_conv))
-    return builder.CreateLoad (iter);
-
-  return iter;
-}
-
-void
-jit_function::do_return (llvm::IRBuilderD& builder, llvm::Value *rval)
-{
-  assert (! rval == ! mresult);
-
-  if (rval)
-    {
-      jit_type::convert_fn convert = mresult->pack (call_conv);
-      if (convert)
-        rval = convert (builder, rval);
-
-      if (sret ())
-        builder.CreateStore (rval, llvm_function->arg_begin ());
-      else
-        builder.CreateRet (rval);
-    }
-  else
-    builder.CreateRetVoid ();
-
-  llvm::verifyFunction (*llvm_function);
-}
-
-void
-jit_function::do_add_mapping (llvm::ExecutionEngine *engine, void *fn)
-{
-  assert (valid ());
-  engine->addGlobalMapping (llvm_function, fn);
-}
-
-std::ostream&
-operator<< (std::ostream& os, const jit_function& fn)
-{
-  llvm::Function *lfn = fn.to_llvm ();
-  os << "jit_function: cc=" << fn.call_conv;
-  llvm::raw_os_ostream llvm_out (os);
-  lfn->print (llvm_out);
-  llvm_out.flush ();
-  return os;
-}
-
-// -------------------- jit_operation --------------------
-jit_operation::~jit_operation (void)
-{
-  for (generated_map::iterator iter = generated.begin ();
-       iter != generated.end (); ++iter)
-    {
-      delete iter->first;
-      delete iter->second;
-    }
-}
-
-void
-jit_operation::add_overload (const jit_function& func,
-                            const std::vector<jit_type*>& args)
-{
-  if (args.size () >= overloads.size ())
-    overloads.resize (args.size () + 1);
-
-  Array<jit_function>& over = overloads[args.size ()];
-  dim_vector dv (over.dims ());
-  Array<octave_idx_type> idx = to_idx (args);
-  bool must_resize = false;
-
-  if (dv.length () != idx.numel ())
-    {
-      dv.resize (idx.numel ());
-      must_resize = true;
-    }
-
-  for (octave_idx_type i = 0; i < dv.length (); ++i)
-    if (dv(i) <= idx(i))
-      {
-        must_resize = true;
-        dv(i) = idx(i) + 1;
-      }
-
-  if (must_resize)
-    over.resize (dv);
-
-  over(idx) = func;
-}
-
-const jit_function&
-jit_operation::overload (const std::vector<jit_type*>& types) const
-{
-  static jit_function null_overload;
-  for (size_t i  =0; i < types.size (); ++i)
-    if (! types[i])
-      return null_overload;
-
-  if (types.size () >= overloads.size ())
-    return do_generate (types);
-
-  const Array<jit_function>& over = overloads[types.size ()];
-  dim_vector dv (over.dims ());
-  Array<octave_idx_type> idx = to_idx (types);
-  for (octave_idx_type i = 0; i < dv.length (); ++i)
-    if (idx(i) >= dv(i))
-      return do_generate (types);
-
-  const jit_function& ret = over(idx);
-  if (! ret.valid ())
-    return do_generate (types);
-
-  return ret;
-}
-
-Array<octave_idx_type>
-jit_operation::to_idx (const std::vector<jit_type*>& types) const
-{
-  octave_idx_type numel = types.size ();
-  if (numel == 1)
-    numel = 2;
-
-  Array<octave_idx_type> idx (dim_vector (1, numel));
-  for (octave_idx_type i = 0; i < static_cast<octave_idx_type> (types.size ());
-       ++i)
-    idx(i) = types[i]->type_id ();
-
-  if (types.size () == 1)
-    {
-      idx(1) = idx(0);
-      idx(0) = 0;
-    }
-
-  return idx;
-}
-
-const jit_function&
-jit_operation::do_generate (const signature_vec& types) const
-{
-  static jit_function null_overload;
-  generated_map::const_iterator find = generated.find (&types);
-  if (find != generated.end ())
-    {
-      if (find->second)
-        return *find->second;
-      else
-        return null_overload;
-    }
-
-  jit_function *ret = generate (types);
-  generated[new signature_vec (types)] = ret;
-  return ret ? *ret : null_overload;
-}
-
-jit_function *
-jit_operation::generate (const signature_vec& types) const
-{
-  return 0;
-}
-
-bool
-jit_operation::signature_cmp
-::operator() (const signature_vec *lhs, const signature_vec *rhs)
-{
-  const signature_vec& l = *lhs;
-  const signature_vec& r = *rhs;
-
-  if (l.size () < r.size ())
-    return true;
-  else if (l.size () > r.size ())
-    return false;
-
-  for (size_t i = 0; i < l.size (); ++i)
-    {
-      if (l[i]->type_id () < r[i]->type_id ())
-        return true;
-      else if (l[i]->type_id () > r[i]->type_id ())
-        return false;
-    }
-
-  return false;
-}
-
-// -------------------- jit_index_operation --------------------
-jit_function *
-jit_index_operation::generate (const signature_vec& types) const
-{
-  if (types.size () > 2 && types[0] == jit_typeinfo::get_matrix ())
-    {
-      // indexing a matrix with scalars
-      jit_type *scalar = jit_typeinfo::get_scalar ();
-      for (size_t i = 1; i < types.size (); ++i)
-        if (types[i] != scalar)
-          return 0;
-
-      return generate_matrix (types);
-    }
-
-  return 0;
-}
-
-llvm::Value *
-jit_index_operation::create_arg_array (llvm::IRBuilderD& builder,
-                                       const jit_function &fn, size_t start_idx,
-                                       size_t end_idx) const
-{
-  size_t n = end_idx - start_idx;
-  llvm::Type *scalar_t = jit_typeinfo::get_scalar_llvm ();
-  llvm::ArrayType *array_t = llvm::ArrayType::get (scalar_t, n);
-  llvm::Value *array = llvm::UndefValue::get (array_t);
-  for (size_t i = start_idx; i < end_idx; ++i)
-    {
-      llvm::Value *idx = fn.argument (builder, i);
-      array = builder.CreateInsertValue (array, idx, i - start_idx);
-    }
-
-  llvm::Value *array_mem = builder.CreateAlloca (array_t);
-  builder.CreateStore (array, array_mem);
-  return builder.CreateBitCast (array_mem, scalar_t->getPointerTo ());
-}
-
-// -------------------- jit_paren_subsref --------------------
-jit_function *
-jit_paren_subsref::generate_matrix (const signature_vec& types) const
-{
-  std::stringstream ss;
-  ss << "jit_paren_subsref_matrix_scalar" << (types.size () - 1);
-
-  jit_type *scalar = jit_typeinfo::get_scalar ();
-  jit_function *fn = new jit_function (module, jit_convention::internal,
-                                       ss.str (), scalar, types);
-  fn->mark_can_error ();
-  llvm::BasicBlock *body = fn->new_block ();
-  llvm::IRBuilder<> builder (body);
-
-  llvm::Value *array = create_arg_array (builder, *fn, 1, types.size ());
-  jit_type *index = jit_typeinfo::get_index ();
-  llvm::Value *nelem = llvm::ConstantInt::get (index->to_llvm (),
-                                               types.size () - 1);
-  llvm::Value *mat = fn->argument (builder, 0);
-  llvm::Value *ret = paren_scalar.call (builder, mat, array, nelem);
-  fn->do_return (builder, ret);
-  return fn;
-}
-
-void
-jit_paren_subsref::do_initialize (void)
-{
-  std::vector<jit_type *> types (3);
-  types[0] = jit_typeinfo::get_matrix ();
-  types[1] = jit_typeinfo::get_scalar_ptr ();
-  types[2] = jit_typeinfo::get_index ();
-
-  jit_type *scalar = jit_typeinfo::get_scalar ();
-  paren_scalar = jit_function (module, jit_convention::external,
-                               "octave_jit_paren_scalar", scalar, types);
-  paren_scalar.add_mapping (engine, &octave_jit_paren_scalar);
-  paren_scalar.mark_can_error ();
-}
-
-// -------------------- jit_paren_subsasgn --------------------
-jit_function *
-jit_paren_subsasgn::generate_matrix (const signature_vec& types) const
-{
-  std::stringstream ss;
-  ss << "jit_paren_subsasgn_matrix_scalar" << (types.size () - 2);
-
-  jit_type *matrix = jit_typeinfo::get_matrix ();
-  jit_function *fn = new jit_function (module, jit_convention::internal,
-                                       ss.str (), matrix, types);
-  fn->mark_can_error ();
-  llvm::BasicBlock *body = fn->new_block ();
-  llvm::IRBuilder<> builder (body);
-
-  llvm::Value *array = create_arg_array (builder, *fn, 1, types.size () - 1);
-  jit_type *index = jit_typeinfo::get_index ();
-  llvm::Value *nelem = llvm::ConstantInt::get (index->to_llvm (),
-                                               types.size () - 2);
-
-  llvm::Value *mat = fn->argument (builder, 0);
-  llvm::Value *value = fn->argument (builder, types.size () - 1);
-  llvm::Value *ret = paren_scalar.call (builder, mat, array, nelem, value);
-  fn->do_return (builder, ret);
-  return fn;
-}
-
-void
-jit_paren_subsasgn::do_initialize (void)
-{
-  if (paren_scalar.valid ())
-    return;
-
-  jit_type *matrix = jit_typeinfo::get_matrix ();
-  std::vector<jit_type *> types (4);
-  types[0] = matrix;
-  types[1] = jit_typeinfo::get_scalar_ptr ();
-  types[2] = jit_typeinfo::get_index ();
-  types[3] = jit_typeinfo::get_scalar ();
-
-  paren_scalar = jit_function (module, jit_convention::external,
-                               "octave_jit_paren_scalar", matrix, types);
-  paren_scalar.add_mapping (engine, &octave_jit_paren_scalar_subsasgn);
-  paren_scalar.mark_can_error ();
-}
-
-// -------------------- jit_typeinfo --------------------
-void
-jit_typeinfo::initialize (llvm::Module *m, llvm::ExecutionEngine *e)
-{
-  new jit_typeinfo (m, e);
-}
-
-jit_typeinfo::jit_typeinfo (llvm::Module *m, llvm::ExecutionEngine *e)
-  : module (m), engine (e), next_id (0),
-    builder (*new llvm::IRBuilderD (context))
-{
-  instance = this;
-
-  // FIXME: We should be registering types like in octave_value_typeinfo
-  llvm::Type *any_t = llvm::StructType::create (context, "octave_base_value");
-  any_t = any_t->getPointerTo ();
-
-  llvm::Type *scalar_t = llvm::Type::getDoubleTy (context);
-  llvm::Type *bool_t = llvm::Type::getInt1Ty (context);
-  llvm::Type *string_t = llvm::Type::getInt8Ty (context);
-  string_t = string_t->getPointerTo ();
-  llvm::Type *index_t = llvm::Type::getIntNTy (context,
-                                               sizeof(octave_idx_type) * 8);
-
-  llvm::StructType *range_t = llvm::StructType::create (context, "range");
-  std::vector<llvm::Type *> range_contents (4, scalar_t);
-  range_contents[3] = index_t;
-  range_t->setBody (range_contents);
-
-  llvm::Type *refcount_t = llvm::Type::getIntNTy (context, sizeof(int) * 8);
-
-  llvm::StructType *matrix_t = llvm::StructType::create (context, "matrix");
-  llvm::Type *matrix_contents[5];
-  matrix_contents[0] = refcount_t->getPointerTo ();
-  matrix_contents[1] = scalar_t->getPointerTo ();
-  matrix_contents[2] = index_t;
-  matrix_contents[3] = index_t->getPointerTo ();
-  matrix_contents[4] = string_t;
-  matrix_t->setBody (llvm::makeArrayRef (matrix_contents, 5));
-
-  llvm::Type *complex_t = llvm::VectorType::get (scalar_t, 2);
-
-  // complex_ret is what is passed to C functions in order to get calling
-  // convention right
-  complex_ret = llvm::StructType::create (context, "complex_ret");
-  llvm::Type *complex_ret_contents[] = {scalar_t, scalar_t};
-  complex_ret->setBody (complex_ret_contents);
-
-  // create types
-  any = new_type ("any", 0, any_t);
-  matrix = new_type ("matrix", any, matrix_t);
-  complex = new_type ("complex", any, complex_t);
-  scalar = new_type ("scalar", complex, scalar_t);
-  scalar_ptr = new_type ("scalar_ptr", 0, scalar_t->getPointerTo ());
-  range = new_type ("range", any, range_t);
-  string = new_type ("string", any, string_t);
-  boolean = new_type ("bool", any, bool_t);
-  index = new_type ("index", any, index_t);
-
-  create_int (8);
-  create_int (16);
-  create_int (32);
-  create_int (64);
-
-  casts.resize (next_id + 1);
-  identities.resize (next_id + 1);
-
-  // specify calling conventions
-  // FIXME: We should detect architecture and do something sane based on that
-  // here we assume x86 or x86_64
-  matrix->mark_sret ();
-  matrix->mark_pointer_arg ();
-
-  range->mark_sret ();
-  range->mark_pointer_arg ();
-
-  complex->set_pack (jit_convention::external, &jit_typeinfo::pack_complex);
-  complex->set_unpack (jit_convention::external, &jit_typeinfo::unpack_complex);
-  complex->set_packed_type (jit_convention::external, complex_ret);
-
-  if (sizeof (void *) == 4)
-    complex->mark_sret ();
-
-  paren_subsref_fn.initialize (module, engine);
-  paren_subsasgn_fn.initialize (module, engine);
-
-  // bind global variables
-  lerror_state = new llvm::GlobalVariable (*module, bool_t, false,
-                                           llvm::GlobalValue::ExternalLinkage,
-                                           0, "error_state");
-  engine->addGlobalMapping (lerror_state,
-                            reinterpret_cast<void *> (&error_state));
-
-  // any with anything is an any op
-  jit_function fn;
-  jit_type *binary_op_type = intN (sizeof (octave_value::binary_op) * 8);
-  llvm::Type *llvm_bo_type = binary_op_type->to_llvm ();
-  jit_function any_binary = create_function (jit_convention::external,
-                                             "octave_jit_binary_any_any",
-                                             any, binary_op_type, any, any);
-  any_binary.add_mapping (engine, &octave_jit_binary_any_any);
-  any_binary.mark_can_error ();
-  binary_ops.resize (octave_value::num_binary_ops);
-  for (size_t i = 0; i < octave_value::num_binary_ops; ++i)
-    {
-      octave_value::binary_op op = static_cast<octave_value::binary_op> (i);
-      std::string op_name = octave_value::binary_op_as_string (op);
-      binary_ops[i].stash_name ("binary" + op_name);
-    }
-
-  for (int op = 0; op < octave_value::num_binary_ops; ++op)
-    {
-      llvm::Twine fn_name ("octave_jit_binary_any_any_");
-      fn_name = fn_name + llvm::Twine (op);
-
-      fn = create_function (jit_convention::internal, fn_name, any, any, any);
-      fn.mark_can_error ();
-      llvm::BasicBlock *block = fn.new_block ();
-      builder.SetInsertPoint (block);
-      llvm::APInt op_int(sizeof (octave_value::binary_op) * 8, op,
-                         std::numeric_limits<octave_value::binary_op>::is_signed);
-      llvm::Value *op_as_llvm = llvm::ConstantInt::get (llvm_bo_type, op_int);
-      llvm::Value *ret = any_binary.call (builder, op_as_llvm,
-                                          fn.argument (builder, 0),
-                                          fn.argument (builder, 1));
-      fn.do_return (builder, ret);
-      binary_ops[op].add_overload (fn);
-    }
-
-  // grab any
-  fn = create_function (jit_convention::external, "octave_jit_grab_any", any,
-                        any);
-  fn.add_mapping (engine, &octave_jit_grab_any);
-  grab_fn.add_overload (fn);
-  grab_fn.stash_name ("grab");
-
-  // grab matrix
-  fn = create_function (jit_convention::external, "octave_jit_grab_matrix",
-                        matrix, matrix);
-  fn.add_mapping (engine, &octave_jit_grab_matrix);
-  grab_fn.add_overload (fn);
-
-  // release any
-  fn = create_function (jit_convention::external, "octave_jit_release_any", 0,
-                        any);
-  fn.add_mapping (engine, &octave_jit_release_any);
-  release_fn.add_overload (fn);
-  release_fn.stash_name ("release");
-
-  // release matrix
-  fn = create_function (jit_convention::external, "octave_jit_release_matrix",
-                        0, matrix);
-  fn.add_mapping (engine, &octave_jit_release_matrix);
-  release_fn.add_overload (fn);
-
-  // release scalar
-  fn = create_identity (scalar);
-  release_fn.add_overload (fn);
-
-  // release complex
-  fn = create_identity (complex);
-  release_fn.add_overload (fn);
-
-  // release index
-  fn = create_identity (index);
-  release_fn.add_overload (fn);
-
-  // now for binary scalar operations
-  // FIXME: Finish all operations
-  add_binary_op (scalar, octave_value::op_add, llvm::Instruction::FAdd);
-  add_binary_op (scalar, octave_value::op_sub, llvm::Instruction::FSub);
-  add_binary_op (scalar, octave_value::op_mul, llvm::Instruction::FMul);
-  add_binary_op (scalar, octave_value::op_el_mul, llvm::Instruction::FMul);
-
-  add_binary_fcmp (scalar, octave_value::op_lt, llvm::CmpInst::FCMP_ULT);
-  add_binary_fcmp (scalar, octave_value::op_le, llvm::CmpInst::FCMP_ULE);
-  add_binary_fcmp (scalar, octave_value::op_eq, llvm::CmpInst::FCMP_UEQ);
-  add_binary_fcmp (scalar, octave_value::op_ge, llvm::CmpInst::FCMP_UGE);
-  add_binary_fcmp (scalar, octave_value::op_gt, llvm::CmpInst::FCMP_UGT);
-  add_binary_fcmp (scalar, octave_value::op_ne, llvm::CmpInst::FCMP_UNE);
-
-  jit_function gripe_div0 = create_function (jit_convention::external,
-                                             "gripe_divide_by_zero", 0);
-  gripe_div0.add_mapping (engine, &gripe_divide_by_zero);
-  gripe_div0.mark_can_error ();
-
-  // divide is annoying because it might error
-  fn = create_function (jit_convention::internal,
-                        "octave_jit_div_scalar_scalar", scalar, scalar, scalar);
-  fn.mark_can_error ();
-
-  llvm::BasicBlock *body = fn.new_block ();
-  builder.SetInsertPoint (body);
-  {
-    llvm::BasicBlock *warn_block = fn.new_block ("warn");
-    llvm::BasicBlock *normal_block = fn.new_block ("normal");
-
-    llvm::Value *zero = llvm::ConstantFP::get (scalar_t, 0);
-    llvm::Value *check = builder.CreateFCmpUEQ (zero, fn.argument (builder, 1));
-    builder.CreateCondBr (check, warn_block, normal_block);
-
-    builder.SetInsertPoint (warn_block);
-    gripe_div0.call (builder);
-    builder.CreateBr (normal_block);
-
-    builder.SetInsertPoint (normal_block);
-    llvm::Value *ret = builder.CreateFDiv (fn.argument (builder, 0),
-                                           fn.argument (builder, 1));
-    fn.do_return (builder, ret);
-  }
-  binary_ops[octave_value::op_div].add_overload (fn);
-  binary_ops[octave_value::op_el_div].add_overload (fn);
-
-  // ldiv is the same as div with the operators reversed
-  fn = mirror_binary (fn);
-  binary_ops[octave_value::op_ldiv].add_overload (fn);
-  binary_ops[octave_value::op_el_ldiv].add_overload (fn);
-
-  // In general, the result of scalar ^ scalar is a complex number. We might be
-  // able to improve on this if we keep track of the range of values varaibles
-  // can take on.
-  fn = create_function (jit_convention::external,
-                        "octave_jit_pow_scalar_scalar", complex, scalar,
-                        scalar);
-  fn.add_mapping (engine, &octave_jit_pow_scalar_scalar);
-  binary_ops[octave_value::op_pow].add_overload (fn);
-  binary_ops[octave_value::op_el_pow].add_overload (fn);
-
-  // now for binary complex operations
-  add_binary_op (complex, octave_value::op_add, llvm::Instruction::FAdd);
-  add_binary_op (complex, octave_value::op_sub, llvm::Instruction::FSub);
-
-  fn = create_function (jit_convention::internal,
-                        "octave_jit_*_complex_complex", complex, complex,
-                        complex);
-  body = fn.new_block ();
-  builder.SetInsertPoint (body);
-  {
-    // (x0*x1 - y0*y1, x0*y1 + y0*x1) = (x0,y0) * (x1,y1)
-    // We compute this in one vectorized multiplication, a subtraction, and an
-    // addition.
-    llvm::Value *lhs = fn.argument (builder, 0);
-    llvm::Value *rhs = fn.argument (builder, 1);
-
-    // FIXME: We need a better way of doing this, working with llvm's IR
-    // directly is sort of a pain.
-    llvm::Value *zero = builder.getInt32 (0);
-    llvm::Value *one = builder.getInt32 (1);
-    llvm::Value *two = builder.getInt32 (2);
-    llvm::Value *three = builder.getInt32 (3);
-
-    llvm::Type *vec4 = llvm::VectorType::get (scalar_t, 4);
-    llvm::Value *mlhs = llvm::UndefValue::get (vec4);
-    llvm::Value *mrhs = mlhs;
-
-    llvm::Value *temp = complex_real (lhs);
-    mlhs = builder.CreateInsertElement (mlhs, temp, zero);
-    mlhs = builder.CreateInsertElement (mlhs, temp, two);
-    temp = complex_imag (lhs);
-    mlhs = builder.CreateInsertElement (mlhs, temp, one);
-    mlhs = builder.CreateInsertElement (mlhs, temp, three);
-
-    temp = complex_real (rhs);
-    mrhs = builder.CreateInsertElement (mrhs, temp, zero);
-    mrhs = builder.CreateInsertElement (mrhs, temp, three);
-    temp = complex_imag (rhs);
-    mrhs = builder.CreateInsertElement (mrhs, temp, one);
-    mrhs = builder.CreateInsertElement (mrhs, temp, two);
-
-    llvm::Value *mres = builder.CreateFMul (mlhs, mrhs);
-    llvm::Value *tlhs = builder.CreateExtractElement (mres, zero);
-    llvm::Value *trhs = builder.CreateExtractElement (mres, one);
-    llvm::Value *ret_real = builder.CreateFSub (tlhs, trhs);
-
-    tlhs = builder.CreateExtractElement (mres, two);
-    trhs = builder.CreateExtractElement (mres, three);
-    llvm::Value *ret_imag = builder.CreateFAdd (tlhs, trhs);
-    fn.do_return (builder, complex_new (ret_real, ret_imag));
-  }
-
-  binary_ops[octave_value::op_mul].add_overload (fn);
-  binary_ops[octave_value::op_el_mul].add_overload (fn);
-
-  jit_function complex_div = create_function (jit_convention::external,
-                                              "octave_jit_complex_div",
-                                              complex, complex, complex);
-  complex_div.add_mapping (engine, &octave_jit_complex_div);
-  complex_div.mark_can_error ();
-  binary_ops[octave_value::op_div].add_overload (fn);
-  binary_ops[octave_value::op_ldiv].add_overload (fn);
-
-  fn = mirror_binary (complex_div);
-  binary_ops[octave_value::op_ldiv].add_overload (fn);
-  binary_ops[octave_value::op_el_ldiv].add_overload (fn);
-
-  fn = create_function (jit_convention::external,
-                        "octave_jit_pow_complex_complex", complex, complex,
-                        complex);
-  fn.add_mapping (engine, &octave_jit_pow_complex_complex);
-  binary_ops[octave_value::op_pow].add_overload (fn);
-  binary_ops[octave_value::op_el_pow].add_overload (fn);
-
-  fn = create_function (jit_convention::internal,
-                        "octave_jit_*_scalar_complex", complex, scalar,
-                        complex);
-  jit_function mul_scalar_complex = fn;
-  body = fn.new_block ();
-  builder.SetInsertPoint (body);
-  {
-    llvm::Value *lhs = fn.argument (builder, 0);
-    llvm::Value *tlhs = complex_new (lhs, lhs);
-    llvm::Value *rhs = fn.argument (builder, 1);
-    fn.do_return (builder, builder.CreateFMul (tlhs, rhs));
-  }
-  binary_ops[octave_value::op_mul].add_overload (fn);
-  binary_ops[octave_value::op_el_mul].add_overload (fn);
-
-
-  fn = mirror_binary (mul_scalar_complex);
-  binary_ops[octave_value::op_mul].add_overload (fn);
-  binary_ops[octave_value::op_el_mul].add_overload (fn);
-
-  fn = create_function (jit_convention::internal, "octave_jit_+_scalar_complex",
-                        complex, scalar, complex);
-  body = fn.new_block ();
-  builder.SetInsertPoint (body);
-  {
-    llvm::Value *lhs = fn.argument (builder, 0);
-    llvm::Value *rhs = fn.argument (builder, 1);
-    llvm::Value *real = builder.CreateFAdd (lhs, complex_real (rhs));
-    fn.do_return (builder, complex_real (rhs, real));
-  }
-  binary_ops[octave_value::op_add].add_overload (fn);
-
-  fn = mirror_binary (fn);
-  binary_ops[octave_value::op_add].add_overload (fn);
-
-  fn = create_function (jit_convention::internal, "octave_jit_-_complex_scalar",
-                        complex, complex, scalar);
-  body = fn.new_block ();
-  builder.SetInsertPoint (body);
-  {
-    llvm::Value *lhs = fn.argument (builder, 0);
-    llvm::Value *rhs = fn.argument (builder, 1);
-    llvm::Value *real = builder.CreateFSub (complex_real (lhs), rhs);
-    fn.do_return (builder, complex_real (lhs, real));
-  }
-  binary_ops[octave_value::op_sub].add_overload (fn);
-
-  fn = create_function (jit_convention::internal, "octave_jit_-_scalar_complex",
-                        complex, scalar, complex);
-  body = fn.new_block ();
-  builder.SetInsertPoint (body);
-  {
-    llvm::Value *lhs = fn.argument (builder, 0);
-    llvm::Value *rhs = fn.argument (builder, 1);
-    llvm::Value *real = builder.CreateFSub (lhs, complex_real (rhs));
-    fn.do_return (builder, complex_real (rhs, real));
-  }
-  binary_ops[octave_value::op_sub].add_overload (fn);
-
-  fn = create_function (jit_convention::external,
-                        "octave_jit_pow_scalar_complex", complex, scalar,
-                        complex);
-  fn.add_mapping (engine, &octave_jit_pow_scalar_complex);
-  binary_ops[octave_value::op_pow].add_overload (fn);
-  binary_ops[octave_value::op_el_pow].add_overload (fn);
-
-  fn = create_function (jit_convention::external,
-                        "octave_jit_pow_complex_scalar", complex, complex,
-                        scalar);
-  fn.add_mapping (engine, &octave_jit_pow_complex_scalar);
-  binary_ops[octave_value::op_pow].add_overload (fn);
-  binary_ops[octave_value::op_el_pow].add_overload (fn);
-
-  // now for binary index operators
-  add_binary_op (index, octave_value::op_add, llvm::Instruction::Add);
-
-  // and binary bool operators
-  add_binary_op (boolean, octave_value::op_el_or, llvm::Instruction::Or);
-  add_binary_op (boolean, octave_value::op_el_and, llvm::Instruction::And);
-
-  // now for printing functions
-  print_fn.stash_name ("print");
-  add_print (any, reinterpret_cast<void *> (&octave_jit_print_any));
-  add_print (scalar, reinterpret_cast<void *> (&octave_jit_print_scalar));
-
-  // initialize for loop
-  for_init_fn.stash_name ("for_init");
-
-  fn = create_function (jit_convention::internal, "octave_jit_for_range_init",
-                        index, range);
-  body = fn.new_block ();
-  builder.SetInsertPoint (body);
-  {
-    llvm::Value *zero = llvm::ConstantInt::get (index_t, 0);
-    fn.do_return (builder, zero);
-  }
-  for_init_fn.add_overload (fn);
-
-  // bounds check for for loop
-  for_check_fn.stash_name ("for_check");
-
-  fn = create_function (jit_convention::internal, "octave_jit_for_range_check",
-                        boolean, range, index);
-  body = fn.new_block ();
-  builder.SetInsertPoint (body);
-  {
-    llvm::Value *nelem
-      = builder.CreateExtractValue (fn.argument (builder, 0), 3);
-    llvm::Value *idx = fn.argument (builder, 1);
-    llvm::Value *ret = builder.CreateICmpULT (idx, nelem);
-    fn.do_return (builder, ret);
-  }
-  for_check_fn.add_overload (fn);
-
-  // index variabe for for loop
-  for_index_fn.stash_name ("for_index");
-
-  fn = create_function (jit_convention::internal, "octave_jit_for_range_idx",
-                        scalar, range, index);
-  body = fn.new_block ();
-  builder.SetInsertPoint (body);
-  {
-    llvm::Value *idx = fn.argument (builder, 1);
-    llvm::Value *didx = builder.CreateSIToFP (idx, scalar_t);
-    llvm::Value *rng = fn.argument (builder, 0);
-    llvm::Value *base = builder.CreateExtractValue (rng, 0);
-    llvm::Value *inc = builder.CreateExtractValue (rng, 2);
-
-    llvm::Value *ret = builder.CreateFMul (didx, inc);
-    ret = builder.CreateFAdd (base, ret);
-    fn.do_return (builder, ret);
-  }
-  for_index_fn.add_overload (fn);
-
-  // logically true
-  logically_true_fn.stash_name ("logically_true");
-
-  jit_function gripe_nantl
-    = create_function (jit_convention::external,
-                       "octave_jit_gripe_nan_to_logical_conversion", 0);
-  gripe_nantl.add_mapping (engine, &octave_jit_gripe_nan_to_logical_conversion);
-  gripe_nantl.mark_can_error ();
-
-  fn = create_function (jit_convention::internal,
-                        "octave_jit_logically_true_scalar", boolean, scalar);
-  fn.mark_can_error ();
-
-  body = fn.new_block ();
-  builder.SetInsertPoint (body);
-  {
-    llvm::BasicBlock *error_block = fn.new_block ("error");
-    llvm::BasicBlock *normal_block = fn.new_block ("normal");
-
-    llvm::Value *check = builder.CreateFCmpUNE (fn.argument (builder, 0),
-                                                fn.argument (builder, 0));
-    builder.CreateCondBr (check, error_block, normal_block);
-
-    builder.SetInsertPoint (error_block);
-    gripe_nantl.call (builder);
-    builder.CreateBr (normal_block);
-    builder.SetInsertPoint (normal_block);
-
-    llvm::Value *zero = llvm::ConstantFP::get (scalar_t, 0);
-    llvm::Value *ret = builder.CreateFCmpONE (fn.argument (builder, 0), zero);
-    fn.do_return (builder, ret);
-  }
-  logically_true_fn.add_overload (fn);
-
-  // logically_true boolean
-  fn = create_identity (boolean);
-  logically_true_fn.add_overload (fn);
-
-  // make_range
-  // FIXME: May be benificial to implement all in LLVM
-  make_range_fn.stash_name ("make_range");
-  jit_function compute_nelem
-    = create_function (jit_convention::external, "octave_jit_compute_nelem",
-                       index, scalar, scalar, scalar);
-  compute_nelem.add_mapping (engine, &octave_jit_compute_nelem);
-
-  fn = create_function (jit_convention::internal, "octave_jit_make_range",
-                        range, scalar, scalar, scalar);
-  body = fn.new_block ();
-  builder.SetInsertPoint (body);
-  {
-    llvm::Value *base = fn.argument (builder, 0);
-    llvm::Value *limit = fn.argument (builder, 1);
-    llvm::Value *inc = fn.argument (builder, 2);
-    llvm::Value *nelem = compute_nelem.call (builder, base, limit, inc);
-
-    llvm::Value *dzero = llvm::ConstantFP::get (scalar_t, 0);
-    llvm::Value *izero = llvm::ConstantInt::get (index_t, 0);
-    llvm::Value *rng = llvm::ConstantStruct::get (range_t, dzero, dzero, dzero,
-                                                  izero, NULL);
-    rng = builder.CreateInsertValue (rng, base, 0);
-    rng = builder.CreateInsertValue (rng, limit, 1);
-    rng = builder.CreateInsertValue (rng, inc, 2);
-    rng = builder.CreateInsertValue (rng, nelem, 3);
-    fn.do_return (builder, rng);
-  }
-  make_range_fn.add_overload (fn);
-
-  // paren_subsref
-  jit_type *jit_int = intN (sizeof (int) * 8);
-  llvm::Type *int_t = jit_int->to_llvm ();
-  jit_function ginvalid_index
-    = create_function (jit_convention::external, "octave_jit_ginvalid_index",
-                       0);
-  ginvalid_index.add_mapping (engine, &octave_jit_ginvalid_index);
-  jit_function gindex_range = create_function (jit_convention::external,
-                                               "octave_jit_gindex_range",
-                                               0, jit_int, jit_int, index,
-                                               index);
-  gindex_range.add_mapping (engine, &octave_jit_gindex_range);
-
-  fn = create_function (jit_convention::internal, "()subsref", scalar, matrix,
-                        scalar);
-  fn.mark_can_error ();
-
-  body = fn.new_block ();
-  builder.SetInsertPoint (body);
-  {
-    llvm::Value *one = llvm::ConstantInt::get (index_t, 1);
-    llvm::Value *ione;
-    if (index_t == int_t)
-      ione = one;
-    else
-      ione = llvm::ConstantInt::get (int_t, 1);
-
-    llvm::Value *undef = llvm::UndefValue::get (scalar_t);
-    llvm::Value *mat = fn.argument (builder, 0);
-    llvm::Value *idx = fn.argument (builder, 1);
-
-    // convert index to scalar to integer, and check index >= 1
-    llvm::Value *int_idx = builder.CreateFPToSI (idx, index_t);
-    llvm::Value *check_idx = builder.CreateSIToFP (int_idx, scalar_t);
-    llvm::Value *cond0 = builder.CreateFCmpUNE (idx, check_idx);
-    llvm::Value *cond1 = builder.CreateICmpSLT (int_idx, one);
-    llvm::Value *cond = builder.CreateOr (cond0, cond1);
-
-    llvm::BasicBlock *done = fn.new_block ("done");
-    llvm::BasicBlock *conv_error = fn.new_block ("conv_error", done);
-    llvm::BasicBlock *normal = fn.new_block ("normal", done);
-    builder.CreateCondBr (cond, conv_error, normal);
-
-    builder.SetInsertPoint (conv_error);
-    ginvalid_index.call (builder);
-    builder.CreateBr (done);
-
-    builder.SetInsertPoint (normal);
-    llvm::Value *len = builder.CreateExtractValue (mat,
-                                                   llvm::ArrayRef<unsigned> (2));
-    cond = builder.CreateICmpSGT (int_idx, len);
-
-
-    llvm::BasicBlock *bounds_error = fn.new_block ("bounds_error", done);
-    llvm::BasicBlock *success = fn.new_block ("success", done);
-    builder.CreateCondBr (cond, bounds_error, success);
-
-    builder.SetInsertPoint (bounds_error);
-    gindex_range.call (builder, ione, ione, int_idx, len);
-    builder.CreateBr (done);
-
-    builder.SetInsertPoint (success);
-    llvm::Value *data = builder.CreateExtractValue (mat,
-                                                    llvm::ArrayRef<unsigned> (1));
-    llvm::Value *gep = builder.CreateInBoundsGEP (data, int_idx);
-    llvm::Value *ret = builder.CreateLoad (gep);
-    builder.CreateBr (done);
-
-    builder.SetInsertPoint (done);
-
-    llvm::PHINode *merge = llvm::PHINode::Create (scalar_t, 3);
-    builder.Insert (merge);
-    merge->addIncoming (undef, conv_error);
-    merge->addIncoming (undef, bounds_error);
-    merge->addIncoming (ret, success);
-    fn.do_return (builder, merge);
-  }
-  paren_subsref_fn.add_overload (fn);
-
-  // paren subsasgn
-  paren_subsasgn_fn.stash_name ("()subsasgn");
-
-  jit_function resize_paren_subsasgn
-    = create_function (jit_convention::external,
-                       "octave_jit_paren_subsasgn_impl", matrix, matrix, index,
-                       scalar);
-  resize_paren_subsasgn.add_mapping (engine, &octave_jit_paren_subsasgn_impl);
-  fn = create_function (jit_convention::internal, "octave_jit_paren_subsasgn",
-                        matrix, matrix, scalar, scalar);
-  fn.mark_can_error ();
-  body = fn.new_block ();
-  builder.SetInsertPoint (body);
-  {
-    llvm::Value *one = llvm::ConstantInt::get (index_t, 1);
-
-    llvm::Value *mat = fn.argument (builder, 0);
-    llvm::Value *idx = fn.argument (builder, 1);
-    llvm::Value *value = fn.argument (builder, 2);
-
-    llvm::Value *int_idx = builder.CreateFPToSI (idx, index_t);
-    llvm::Value *check_idx = builder.CreateSIToFP (int_idx, scalar_t);
-    llvm::Value *cond0 = builder.CreateFCmpUNE (idx, check_idx);
-    llvm::Value *cond1 = builder.CreateICmpSLT (int_idx, one);
-    llvm::Value *cond = builder.CreateOr (cond0, cond1);
-
-    llvm::BasicBlock *done = fn.new_block ("done");
-
-    llvm::BasicBlock *conv_error = fn.new_block ("conv_error", done);
-    llvm::BasicBlock *normal = fn.new_block ("normal", done);
-    builder.CreateCondBr (cond, conv_error, normal);
-    builder.SetInsertPoint (conv_error);
-    ginvalid_index.call (builder);
-    builder.CreateBr (done);
-
-    builder.SetInsertPoint (normal);
-    llvm::Value *len = builder.CreateExtractValue (mat, 2);
-    cond0 = builder.CreateICmpSGT (int_idx, len);
-
-    llvm::Value *rcount = builder.CreateExtractValue (mat, 0);
-    rcount = builder.CreateLoad (rcount);
-    cond1 = builder.CreateICmpSGT (rcount, one);
-    cond = builder.CreateOr (cond0, cond1);
-
-    llvm::BasicBlock *bounds_error = fn.new_block ("bounds_error", done);
-    llvm::BasicBlock *success = fn.new_block ("success", done);
-    builder.CreateCondBr (cond, bounds_error, success);
-
-    // resize on out of bounds access
-    builder.SetInsertPoint (bounds_error);
-    llvm::Value *resize_result = resize_paren_subsasgn.call (builder, mat,
-                                                             int_idx, value);
-    builder.CreateBr (done);
-
-    builder.SetInsertPoint (success);
-    llvm::Value *data = builder.CreateExtractValue (mat,
-                                                    llvm::ArrayRef<unsigned> (1));
-    llvm::Value *gep = builder.CreateInBoundsGEP (data, int_idx);
-    builder.CreateStore (value, gep);
-    builder.CreateBr (done);
-
-    builder.SetInsertPoint (done);
-
-    llvm::PHINode *merge = llvm::PHINode::Create (matrix_t, 3);
-    builder.Insert (merge);
-    merge->addIncoming (mat, conv_error);
-    merge->addIncoming (resize_result, bounds_error);
-    merge->addIncoming (mat, success);
-    fn.do_return (builder, merge);
-  }
-  paren_subsasgn_fn.add_overload (fn);
-
-  fn = create_function (jit_convention::external,
-                        "octave_jit_paren_subsasgn_matrix_range", matrix,
-                        matrix, range, scalar);
-  fn.add_mapping (engine, &octave_jit_paren_subsasgn_matrix_range);
-  fn.mark_can_error ();
-  paren_subsasgn_fn.add_overload (fn);
-
-  end_fn.stash_name ("end");
-  fn = create_function (jit_convention::internal, "octave_jit_end_matrix",
-                        scalar, matrix);
-  body = fn.new_block ();
-  builder.SetInsertPoint (body);
-  {
-    llvm::Value *mat = fn.argument (builder, 0);
-    llvm::Value *ret = builder.CreateExtractValue (mat, 2);
-    fn.do_return (builder, builder.CreateSIToFP (ret, scalar_t));
-  }
-  end_fn.add_overload (fn);
-
-  casts[any->type_id ()].stash_name ("(any)");
-  casts[scalar->type_id ()].stash_name ("(scalar)");
-  casts[complex->type_id ()].stash_name ("(complex)");
-  casts[matrix->type_id ()].stash_name ("(matrix)");
-  casts[any->type_id ()].stash_name ("(range)");
-
-  // cast any <- matrix
-  fn = create_function (jit_convention::external, "octave_jit_cast_any_matrix",
-                        any, matrix);
-  fn.add_mapping (engine, &octave_jit_cast_any_matrix);
-  casts[any->type_id ()].add_overload (fn);
-
-  // cast matrix <- any
-  fn = create_function (jit_convention::external, "octave_jit_cast_matrix_any",
-                        matrix, any);
-  fn.add_mapping (engine, &octave_jit_cast_matrix_any);
-  casts[matrix->type_id ()].add_overload (fn);
-
-  // cast any <- range
-  fn = create_function (jit_convention::external, "octave_jit_cast_any_range",
-                        any, range);
-  fn.add_mapping (engine, &octave_jit_cast_any_range);
-  casts[any->type_id ()].add_overload (fn);
-
-  // cast range <- any
-  fn = create_function (jit_convention::external, "octave_jit_cast_range_any",
-                        range, any);
-  fn.add_mapping (engine, &octave_jit_cast_range_any);
-  casts[range->type_id ()].add_overload (fn);
-
-  // cast any <- scalar
-  fn = create_function (jit_convention::external, "octave_jit_cast_any_scalar",
-                        any, scalar);
-  fn.add_mapping (engine, &octave_jit_cast_any_scalar);
-  casts[any->type_id ()].add_overload (fn);
-
-  // cast scalar <- any
-  fn = create_function (jit_convention::external, "octave_jit_cast_scalar_any",
-                        scalar, any);
-  fn.add_mapping (engine, &octave_jit_cast_scalar_any);
-  casts[scalar->type_id ()].add_overload (fn);
-
-  // cast any <- complex
-  fn = create_function (jit_convention::external, "octave_jit_cast_any_complex",
-                        any, complex);
-  fn.add_mapping (engine, &octave_jit_cast_any_complex);
-  casts[any->type_id ()].add_overload (fn);
-
-  // cast complex <- any
-  fn = create_function (jit_convention::external, "octave_jit_cast_complex_any",
-                        complex, any);
-  fn.add_mapping (engine, &octave_jit_cast_complex_any);
-  casts[complex->type_id ()].add_overload (fn);
-
-  // cast complex <- scalar
-  fn = create_function (jit_convention::internal,
-                        "octave_jit_cast_complex_scalar", complex, scalar);
-  body = fn.new_block ();
-  builder.SetInsertPoint (body);
-  {
-    llvm::Value *zero = llvm::ConstantFP::get (scalar_t, 0);
-    fn.do_return (builder, complex_new (fn.argument (builder, 0), zero));
-  }
-  casts[complex->type_id ()].add_overload (fn);
-
-  // cast scalar <- complex
-  fn = create_function (jit_convention::internal,
-                        "octave_jit_cast_scalar_complex", scalar, complex);
-  body = fn.new_block ();
-  builder.SetInsertPoint (body);
-  fn.do_return (builder, complex_real (fn.argument (builder, 0)));
-  casts[scalar->type_id ()].add_overload (fn);
-
-  // cast any <- any
-  fn = create_identity (any);
-  casts[any->type_id ()].add_overload (fn);
-
-  // cast scalar <- scalar
-  fn = create_identity (scalar);
-  casts[scalar->type_id ()].add_overload (fn);
-
-  // cast complex <- complex
-  fn = create_identity (complex);
-  casts[complex->type_id ()].add_overload (fn);
-
-  // -------------------- builtin functions --------------------
-  add_builtin ("#unknown_function");
-  unknown_function = builtins["#unknown_function"];
-
-  add_builtin ("sin");
-  register_intrinsic ("sin", llvm::Intrinsic::sin, scalar, scalar);
-  register_generic ("sin", matrix, matrix);
-
-  add_builtin ("cos");
-  register_intrinsic ("cos", llvm::Intrinsic::cos, scalar, scalar);
-  register_generic ("cos", matrix, matrix);
-
-  add_builtin ("exp");
-  register_intrinsic ("exp", llvm::Intrinsic::cos, scalar, scalar);
-  register_generic ("exp", matrix, matrix);
-
-  casts.resize (next_id + 1);
-  jit_function any_id = create_identity (any);
-  jit_function release_any = get_release (any);
-  std::vector<jit_type *> args;
-  args.resize (1);
-
-  for (std::map<std::string, jit_type *>::iterator iter = builtins.begin ();
-       iter != builtins.end (); ++iter)
-    {
-      jit_type *btype = iter->second;
-      args[0] = btype;
-
-      release_fn.add_overload (jit_function (release_any, 0, args));
-      casts[any->type_id ()].add_overload (jit_function (any_id, any, args));
-
-      args[0] = any;
-      casts[btype->type_id ()].add_overload (jit_function (any_id, btype,
-                                                           args));
-    }
-}
-
-void
-jit_typeinfo::add_print (jit_type *ty, void *fptr)
-{
-  std::stringstream name;
-  name << "octave_jit_print_" << ty->name ();
-  jit_function fn = create_function (jit_convention::external, name.str (), 0,
-                                     intN (8), ty);
-  fn.add_mapping (engine, fptr);
-  print_fn.add_overload (fn);
-}
-
-// FIXME: cp between add_binary_op, add_binary_icmp, and add_binary_fcmp
-void
-jit_typeinfo::add_binary_op (jit_type *ty, int op, int llvm_op)
-{
-  std::stringstream fname;
-  octave_value::binary_op ov_op = static_cast<octave_value::binary_op>(op);
-  fname << "octave_jit_" << octave_value::binary_op_as_string (ov_op)
-        << "_" << ty->name ();
-
-  jit_function fn = create_function (jit_convention::internal, fname.str (),
-                                        ty, ty, ty);
-  llvm::BasicBlock *block = fn.new_block ();
-  builder.SetInsertPoint (block);
-  llvm::Instruction::BinaryOps temp
-    = static_cast<llvm::Instruction::BinaryOps>(llvm_op);
-
-  llvm::Value *ret = builder.CreateBinOp (temp, fn.argument (builder, 0),
-                                          fn.argument (builder, 1));
-  fn.do_return (builder, ret);
-  binary_ops[op].add_overload (fn);
-}
-
-void
-jit_typeinfo::add_binary_icmp (jit_type *ty, int op, int llvm_op)
-{
-  std::stringstream fname;
-  octave_value::binary_op ov_op = static_cast<octave_value::binary_op>(op);
-  fname << "octave_jit" << octave_value::binary_op_as_string (ov_op)
-        << "_" << ty->name ();
-
-  jit_function fn = create_function (jit_convention::internal, fname.str (),
-                                     boolean, ty, ty);
-  llvm::BasicBlock *block = fn.new_block ();
-  builder.SetInsertPoint (block);
-  llvm::CmpInst::Predicate temp
-    = static_cast<llvm::CmpInst::Predicate>(llvm_op);
-  llvm::Value *ret = builder.CreateICmp (temp, fn.argument (builder, 0),
-                                         fn.argument (builder, 1));
-  fn.do_return (builder, ret);
-  binary_ops[op].add_overload (fn);
-}
-
-void
-jit_typeinfo::add_binary_fcmp (jit_type *ty, int op, int llvm_op)
-{
-  std::stringstream fname;
-  octave_value::binary_op ov_op = static_cast<octave_value::binary_op>(op);
-  fname << "octave_jit" << octave_value::binary_op_as_string (ov_op)
-        << "_" << ty->name ();
-
-  jit_function fn = create_function (jit_convention::internal, fname.str (),
-                                     boolean, ty, ty);
-  llvm::BasicBlock *block = fn.new_block ();
-  builder.SetInsertPoint (block);
-  llvm::CmpInst::Predicate temp
-    = static_cast<llvm::CmpInst::Predicate>(llvm_op);
-  llvm::Value *ret = builder.CreateFCmp (temp, fn.argument (builder, 0),
-                                         fn.argument (builder, 1));
-  fn.do_return (builder, ret);
-  binary_ops[op].add_overload (fn);
-}
-
-jit_function
-jit_typeinfo::create_function (jit_convention::type cc, const llvm::Twine& name,
-                               jit_type *ret,
-                               const std::vector<jit_type *>& args)
-{
-  jit_function result (module, cc, name, ret, args);
-  return result;
-}
-
-jit_function
-jit_typeinfo::create_identity (jit_type *type)
-{
-  size_t id = type->type_id ();
-  if (id >= identities.size ())
-    identities.resize (id + 1);
-
-  if (! identities[id].valid ())
-    {
-      jit_function fn = create_function (jit_convention::internal, "id", type,
-                                         type);
-      llvm::BasicBlock *body = fn.new_block ();
-      builder.SetInsertPoint (body);
-      fn.do_return (builder, fn.argument (builder, 0));
-      return identities[id] = fn;
-    }
-
-  return identities[id];
-}
-
-llvm::Value *
-jit_typeinfo::do_insert_error_check (llvm::IRBuilderD& abuilder)
-{
-  return abuilder.CreateLoad (lerror_state);
-}
-
-void
-jit_typeinfo::add_builtin (const std::string& name)
-{
-  jit_type *btype = new_type (name, any, any->to_llvm ());
-  builtins[name] = btype;
-
-  octave_builtin *ov_builtin = find_builtin (name);
-  if (ov_builtin)
-    ov_builtin->stash_jit (*btype);
-}
-
-void
-jit_typeinfo::register_intrinsic (const std::string& name, size_t iid,
-                                  jit_type *result,
-                                  const std::vector<jit_type *>& args)
-{
-  jit_type *builtin_type = builtins[name];
-  size_t nargs = args.size ();
-  llvm::SmallVector<llvm::Type *, 5> llvm_args (nargs);
-  for (size_t i = 0; i < nargs; ++i)
-    llvm_args[i] = args[i]->to_llvm ();
-
-  llvm::Intrinsic::ID id = static_cast<llvm::Intrinsic::ID> (iid);
-  llvm::Function *ifun = llvm::Intrinsic::getDeclaration (module, id,
-                                                          llvm_args);
-  std::stringstream fn_name;
-  fn_name << "octave_jit_" << name;
-
-  std::vector<jit_type *> args1 (nargs + 1);
-  args1[0] = builtin_type;
-  std::copy (args.begin (), args.end (), args1.begin () + 1);
-
-  // The first argument will be the Octave function, but we already know that
-  // the function call is the equivalent of the intrinsic, so we ignore it and
-  // call the intrinsic with the remaining arguments.
-  jit_function fn = create_function (jit_convention::internal, fn_name.str (),
-                                     result, args1);
-  llvm::BasicBlock *body = fn.new_block ();
-  builder.SetInsertPoint (body);
-
-  llvm::SmallVector<llvm::Value *, 5> fargs (nargs);
-  for (size_t i = 0; i < nargs; ++i)
-    fargs[i] = fn.argument (builder, i + 1);
-
-  llvm::Value *ret = builder.CreateCall (ifun, fargs);
-  fn.do_return (builder, ret);
-  paren_subsref_fn.add_overload (fn);
-}
-
-octave_builtin *
-jit_typeinfo::find_builtin (const std::string& name)
-{
-  // FIXME: Finalize what we want to store in octave_builtin, then add functions
-  // to access these values in octave_value
-  octave_value ov_builtin = symbol_table::find (name);
-  return dynamic_cast<octave_builtin *> (ov_builtin.internal_rep ());
-}
-
-void
-jit_typeinfo::register_generic (const std::string&, jit_type *,
-                                const std::vector<jit_type *>&)
-{
-  // FIXME: Implement
-}
-
-jit_function
-jit_typeinfo::mirror_binary (const jit_function& fn)
-{
-  jit_function ret = create_function (jit_convention::internal,
-                                      fn.name () + "_reverse",
-                                      fn.result (), fn.argument_type (1),
-                                      fn.argument_type (0));
-  if (fn.can_error ())
-    ret.mark_can_error ();
-
-  llvm::BasicBlock *body = ret.new_block ();
-  builder.SetInsertPoint (body);
-  llvm::Value *result = fn.call (builder, ret.argument (builder, 1),
-                                 ret.argument (builder, 0));
-  if (ret.result ())
-    ret.do_return (builder, result);
-  else
-    ret.do_return (builder);
-
-  return ret;
-}
-
-llvm::Value *
-jit_typeinfo::pack_complex (llvm::IRBuilderD& bld, llvm::Value *cplx)
-{
-  llvm::Type *complex_ret = instance->complex_ret;
-  llvm::Value *real = bld.CreateExtractElement (cplx, bld.getInt32 (0));
-  llvm::Value *imag = bld.CreateExtractElement (cplx, bld.getInt32 (1));
-  llvm::Value *ret = llvm::UndefValue::get (complex_ret);
-  ret = bld.CreateInsertValue (ret, real, 0);
-  return bld.CreateInsertValue (ret, imag, 1);
-}
-
-llvm::Value *
-jit_typeinfo::unpack_complex (llvm::IRBuilderD& bld, llvm::Value *result)
-{
-  llvm::Type *complex_t = get_complex ()->to_llvm ();
-  llvm::Value *real = bld.CreateExtractValue (result, 0);
-  llvm::Value *imag = bld.CreateExtractValue (result, 1);
-  llvm::Value *ret = llvm::UndefValue::get (complex_t);
-  ret = bld.CreateInsertElement (ret, real, bld.getInt32 (0));
-  return bld.CreateInsertElement (ret, imag, bld.getInt32 (1));
-}
-
-llvm::Value *
-jit_typeinfo::complex_real (llvm::Value *cx)
-{
-  return builder.CreateExtractElement (cx, builder.getInt32 (0));
-}
-
-llvm::Value *
-jit_typeinfo::complex_real (llvm::Value *cx, llvm::Value *real)
-{
-  return builder.CreateInsertElement (cx, real, builder.getInt32 (0));
-}
-
-llvm::Value *
-jit_typeinfo::complex_imag (llvm::Value *cx)
-{
-  return builder.CreateExtractElement (cx, builder.getInt32 (1));
-}
-
-llvm::Value *
-jit_typeinfo::complex_imag (llvm::Value *cx, llvm::Value *imag)
-{
-  return builder.CreateInsertElement (cx, imag, builder.getInt32 (1));
-}
-
-llvm::Value *
-jit_typeinfo::complex_new (llvm::Value *real, llvm::Value *imag)
-{
-  llvm::Value *ret = llvm::UndefValue::get (complex->to_llvm ());
-  ret = complex_real (ret, real);
-  return complex_imag (ret, imag);
-}
-
-void
-jit_typeinfo::create_int (size_t nbits)
-{
-  std::stringstream tname;
-  tname << "int" << nbits;
-  ints[nbits] = new_type (tname.str (), any, llvm::Type::getIntNTy (context,
-                                                                    nbits));
-}
-
-jit_type *
-jit_typeinfo::intN (size_t nbits) const
-{
-  std::map<size_t, jit_type *>::const_iterator iter = ints.find (nbits);
-  if (iter != ints.end ())
-    return iter->second;
-
-  throw jit_fail_exception ("No such integer type");
-}
-
-jit_type *
-jit_typeinfo::do_type_of (const octave_value &ov) const
-{
-  if (ov.is_function ())
-    {
-      // FIXME: This is ugly, we need to finalize how we want to to this, then
-      // have octave_value fully support the needed functionality
-      octave_builtin *builtin
-        = dynamic_cast<octave_builtin *> (ov.internal_rep ());
-      return builtin && builtin->to_jit () ? builtin->to_jit ()
-        : unknown_function;
-    }
-
-  if (ov.is_range ())
-    return get_range ();
-
-  if (ov.is_double_type ())
-    {
-      if (ov.is_real_scalar ())
-        return get_scalar ();
-
-      if (ov.is_matrix_type ())
-        return get_matrix ();
-    }
-
-  if (ov.is_complex_scalar ())
-    return get_complex ();
-
-  return get_any ();
-}
-
-jit_type*
-jit_typeinfo::new_type (const std::string& name, jit_type *parent,
-                        llvm::Type *llvm_type)
-{
-  jit_type *ret = new jit_type (name, parent, llvm_type, next_id++);
-  id_to_type.push_back (ret);
-  return ret;
-}
-
-#endif
--- a/src/jit-typeinfo.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,753 +0,0 @@
-/*
-
-Copyright (C) 2012 Max Brister <max@2bass.com>
-
-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/>.
-
-*/
-
-#if !defined (octave_jit_typeinfo_h)
-#define octave_jit_typeinfo_h 1
-
-#ifdef HAVE_LLVM
-
-#include <map>
-#include <vector>
-
-#include "Range.h"
-#include "jit-util.h"
-
-// Defines the type system used by jit and a singleton class, jit_typeinfo, to
-// manage the types.
-//
-// FIXME:
-// Operations are defined and implemented in jit_typeinfo. Eventually they
-// should be moved elsewhere. (just like with octave_typeinfo)
-
-// jit_range is compatable with the llvm range structure
-struct
-jit_range
-{
-  jit_range (const Range& from) : base (from.base ()), limit (from.limit ()),
-                                  inc (from.inc ()), nelem (from.nelem ())
-  {}
-
-  operator Range () const
-  {
-    return Range (base, limit, inc);
-  }
-
-  bool all_elements_are_ints () const;
-
-  double base;
-  double limit;
-  double inc;
-  octave_idx_type nelem;
-};
-
-std::ostream& operator<< (std::ostream& os, const jit_range& rng);
-
-// jit_array is compatable with the llvm array/matrix structures
-template <typename T, typename U>
-struct
-jit_array
-{
-  jit_array (T& from) : array (new T (from))
-  {
-    update ();
-  }
-
-  void update (void)
-  {
-    ref_count = array->jit_ref_count ();
-    slice_data = array->jit_slice_data () - 1;
-    slice_len = array->capacity ();
-    dimensions = array->jit_dimensions ();
-  }
-
-  void update (T *aarray)
-  {
-    array = aarray;
-    update ();
-  }
-
-  operator T () const
-  {
-    return *array;
-  }
-
-  int *ref_count;
-
-  U *slice_data;
-  octave_idx_type slice_len;
-  octave_idx_type *dimensions;
-
-  T *array;
-};
-
-typedef jit_array<NDArray, double> jit_matrix;
-
-std::ostream& operator<< (std::ostream& os, const jit_matrix& mat);
-
-// calling convention
-namespace
-jit_convention
-{
-  enum
-  type
-  {
-    // internal to jit
-    internal,
-
-    // an external C call
-    external,
-
-    length
-  };
-}
-
-// Used to keep track of estimated (infered) types during JIT. This is a
-// hierarchical type system which includes both concrete and abstract types.
-//
-// The types form a lattice. Currently we only allow for one parent type, but
-// eventually we may allow for multiple predecessors.
-class
-jit_type
-{
-public:
-  typedef llvm::Value *(*convert_fn) (llvm::IRBuilderD&, llvm::Value *);
-
-  jit_type (const std::string& aname, jit_type *aparent, llvm::Type *allvm_type,
-            int aid);
-
-  // a user readable type name
-  const std::string& name (void) const { return mname; }
-
-  // a unique id for the type
-  int type_id (void) const { return mid; }
-
-  // An abstract base type, may be null
-  jit_type *parent (void) const { return mparent; }
-
-  // convert to an llvm type
-  llvm::Type *to_llvm (void) const { return llvm_type; }
-
-  // how this type gets passed as a function argument
-  llvm::Type *to_llvm_arg (void) const;
-
-  size_t depth (void) const { return mdepth; }
-
-  // -------------------- Calling Convention information --------------------
-
-  // A function declared like: mytype foo (int arg0, int arg1);
-  // Will be converted to: void foo (mytype *retval, int arg0, int arg1)
-  // if mytype is sret. The caller is responsible for allocating space for
-  // retval. (on the stack)
-  bool sret (jit_convention::type cc) const { return msret[cc]; }
-
-  void mark_sret (jit_convention::type cc = jit_convention::external)
-  { msret[cc] = true; }
-
-  // A function like: void foo (mytype arg0)
-  // Will be converted to: void foo (mytype *arg0)
-  // Basically just pass by reference.
-  bool pointer_arg (jit_convention::type cc) const { return mpointer_arg[cc]; }
-
-  void mark_pointer_arg (jit_convention::type cc = jit_convention::external)
-  { mpointer_arg[cc] = true; }
-
-  // Convert into an equivalent form before calling. For example, complex is
-  // represented as two values llvm vector, but we need to pass it as a two
-  // valued llvm structure to C functions.
-  convert_fn pack (jit_convention::type cc) { return mpack[cc]; }
-
-  void set_pack (jit_convention::type cc, convert_fn fn) { mpack[cc] = fn; }
-
-  // The inverse operation of pack.
-  convert_fn unpack (jit_convention::type cc) { return munpack[cc]; }
-
-  void set_unpack (jit_convention::type cc, convert_fn fn)
-  { munpack[cc] = fn; }
-
-  // The resulting type after pack is called.
-  llvm::Type *packed_type (jit_convention::type cc)
-  { return mpacked_type[cc]; }
-
-  void set_packed_type (jit_convention::type cc, llvm::Type *ty)
-  { mpacked_type[cc] = ty; }
-private:
-  std::string mname;
-  jit_type *mparent;
-  llvm::Type *llvm_type;
-  int mid;
-  size_t mdepth;
-
-  bool msret[jit_convention::length];
-  bool mpointer_arg[jit_convention::length];
-
-  convert_fn mpack[jit_convention::length];
-  convert_fn munpack[jit_convention::length];
-
-  llvm::Type *mpacked_type[jit_convention::length];
-};
-
-// seperate print function to allow easy printing if type is null
-std::ostream& jit_print (std::ostream& os, jit_type *atype);
-
-class jit_value;
-
-// An abstraction for calling llvm functions with jit_values. Deals with calling
-// convention details.
-class
-jit_function
-{
-  friend std::ostream& operator<< (std::ostream& os, const jit_function& fn);
-public:
-  // create a function in an invalid state
-  jit_function ();
-
-  jit_function (llvm::Module *amodule, jit_convention::type acall_conv,
-                const llvm::Twine& aname, jit_type *aresult,
-                const std::vector<jit_type *>& aargs);
-
-  // Use an existing function, but change the argument types. The new argument
-  // types must behave the same for the current calling convention.
-  jit_function (const jit_function& fn, jit_type *aresult,
-                const std::vector<jit_type *>& aargs);
-
-  jit_function (const jit_function& fn);
-
-  template <typename T>
-  void add_mapping (llvm::ExecutionEngine *engine, T fn)
-  {
-    do_add_mapping (engine, reinterpret_cast<void *> (fn));
-  }
-
-  bool valid (void) const { return llvm_function; }
-
-  std::string name (void) const;
-
-  llvm::BasicBlock *new_block (const std::string& aname = "body",
-                               llvm::BasicBlock *insert_before = 0);
-
-  llvm::Value *call (llvm::IRBuilderD& builder,
-                     const std::vector<jit_value *>& in_args) const;
-
-  llvm::Value *call (llvm::IRBuilderD& builder,
-                     const std::vector<llvm::Value *>& in_args
-                     = std::vector<llvm::Value *> ()) const;
-
-#define JIT_PARAM_ARGS llvm::IRBuilderD& builder,
-#define JIT_PARAMS builder,
-#define JIT_CALL(N) JIT_EXPAND (llvm::Value *, call, llvm::Value *, const, N)
-
-  JIT_CALL (1)
-  JIT_CALL (2)
-  JIT_CALL (3)
-  JIT_CALL (4)
-  JIT_CALL (5)
-
-#undef JIT_CALL
-
-#define JIT_CALL(N) JIT_EXPAND (llvm::Value *, call, jit_value *, const, N)
-
-  JIT_CALL (1);
-  JIT_CALL (2);
-
-#undef JIT_CALL
-#undef JIT_PARAMS
-#undef JIT_PARAM_ARGS
-
-  llvm::Value *argument (llvm::IRBuilderD& builder, size_t idx) const;
-
-  void do_return (llvm::IRBuilderD& builder, llvm::Value *rval = 0);
-
-  llvm::Function *to_llvm (void) const { return llvm_function; }
-
-  // If true, then the return value is passed as a pointer in the first argument
-  bool sret (void) const { return mresult && mresult->sret (call_conv); }
-
-  bool can_error (void) const { return mcan_error; }
-
-  void mark_can_error (void) { mcan_error = true; }
-
-  jit_type *result (void) const { return mresult; }
-
-  jit_type *argument_type (size_t idx) const
-  {
-    assert (idx < args.size ());
-    return args[idx];
-  }
-
-  const std::vector<jit_type *>& arguments (void) const { return args; }
-private:
-  void do_add_mapping (llvm::ExecutionEngine *engine, void *fn);
-
-  llvm::Module *module;
-  llvm::Function *llvm_function;
-  jit_type *mresult;
-  std::vector<jit_type *> args;
-  jit_convention::type call_conv;
-  bool mcan_error;
-};
-
-std::ostream& operator<< (std::ostream& os, const jit_function& fn);
-
-
-// Keeps track of information about how to implement operations (+, -, *, ect)
-// and their resulting types.
-class
-jit_operation
-{
-public:
-  // type signature vector
-  typedef std::vector<jit_type *> signature_vec;
-
-  virtual ~jit_operation (void);
-
-  void add_overload (const jit_function& func)
-  {
-    add_overload (func, func.arguments ());
-  }
-
-  void add_overload (const jit_function& func,
-                     const signature_vec& args);
-
-  const jit_function& overload (const signature_vec& types) const;
-
-  jit_type *result (const signature_vec& types) const
-  {
-    const jit_function& temp = overload (types);
-    return temp.result ();
-  }
-
-#define JIT_PARAMS
-#define JIT_PARAM_ARGS
-#define JIT_OVERLOAD(N)                                              \
-  JIT_EXPAND (const jit_function&, overload, jit_type *, const, N)   \
-  JIT_EXPAND (jit_type *, result, jit_type *, const, N)
-
-  JIT_OVERLOAD (1);
-  JIT_OVERLOAD (2);
-  JIT_OVERLOAD (3);
-
-#undef JIT_PARAMS
-#undef JIT_PARAM_ARGS
-
-  const std::string& name (void) const { return mname; }
-
-  void stash_name (const std::string& aname) { mname = aname; }
-protected:
-  virtual jit_function *generate (const signature_vec& types) const;
-private:
-  Array<octave_idx_type> to_idx (const signature_vec& types) const;
-
-  const jit_function& do_generate (const signature_vec& types) const;
-
-  struct signature_cmp
-  {
-    bool operator() (const signature_vec *lhs, const signature_vec *rhs);
-  };
-
-  typedef std::map<const signature_vec *, jit_function *, signature_cmp>
-  generated_map;
-
-  mutable generated_map generated;
-
-  std::vector<Array<jit_function> > overloads;
-
-  std::string mname;
-};
-
-class
-jit_index_operation : public jit_operation
-{
-public:
-  jit_index_operation (void) : module (0), engine (0) {}
-
-  void initialize (llvm::Module *amodule, llvm::ExecutionEngine *aengine)
-  {
-    module = amodule;
-    engine = aengine;
-    do_initialize ();
-  }
-protected:
-  virtual jit_function *generate (const signature_vec& types) const;
-
-  virtual jit_function *generate_matrix (const signature_vec& types) const = 0;
-
-  virtual void do_initialize (void) = 0;
-
-  // helper functions
-  // [start_idx, end_idx).
-  llvm::Value *create_arg_array (llvm::IRBuilderD& builder,
-                                 const jit_function &fn, size_t start_idx,
-                                 size_t end_idx) const;
-
-  llvm::Module *module;
-  llvm::ExecutionEngine *engine;
-};
-
-class
-jit_paren_subsref : public jit_index_operation
-{
-protected:
-  virtual jit_function *generate_matrix (const signature_vec& types) const;
-
-  virtual void do_initialize (void);
-private:
-  jit_function paren_scalar;
-};
-
-class
-jit_paren_subsasgn : public jit_index_operation
-{
-protected:
-  jit_function *generate_matrix (const signature_vec& types) const;
-
-  virtual void do_initialize (void);
-private:
-  jit_function paren_scalar;
-};
-
-// A singleton class which handles the construction of jit_types and
-// jit_operations.
-class
-jit_typeinfo
-{
-public:
-  static void initialize (llvm::Module *m, llvm::ExecutionEngine *e);
-
-  static jit_type *join (jit_type *lhs, jit_type *rhs)
-  {
-    return instance->do_join (lhs, rhs);
-  }
-
-  static jit_type *get_any (void) { return instance->any; }
-
-  static jit_type *get_matrix (void) { return instance->matrix; }
-
-  static jit_type *get_scalar (void) { return instance->scalar; }
-
-  static llvm::Type *get_scalar_llvm (void)
-  { return instance->scalar->to_llvm (); }
-
-  static jit_type *get_scalar_ptr (void) { return instance->scalar_ptr; }
-
-  static jit_type *get_range (void) { return instance->range; }
-
-  static jit_type *get_string (void) { return instance->string; }
-
-  static jit_type *get_bool (void) { return instance->boolean; }
-
-  static jit_type *get_index (void) { return instance->index; }
-
-  static llvm::Type *get_index_llvm (void)
-  { return instance->index->to_llvm (); }
-
-  static jit_type *get_complex (void) { return instance->complex; }
-
-  // Get the jit_type of an octave_value
-  static jit_type *type_of (const octave_value& ov)
-  {
-    return instance->do_type_of (ov);
-  }
-
-  static const jit_operation& binary_op (int op)
-  {
-    return instance->do_binary_op (op);
-  }
-
-  static const jit_operation& grab (void) { return instance->grab_fn; }
-
-  static const jit_function& get_grab (jit_type *type)
-  {
-    return instance->grab_fn.overload (type);
-  }
-
-  static const jit_operation& release (void)
-  {
-    return instance->release_fn;
-  }
-
-  static const jit_function& get_release (jit_type *type)
-  {
-    return instance->release_fn.overload (type);
-  }
-
-  static const jit_operation& print_value (void)
-  {
-    return instance->print_fn;
-  }
-
-  static const jit_operation& for_init (void)
-  {
-    return instance->for_init_fn;
-  }
-
-  static const jit_operation& for_check (void)
-  {
-    return instance->for_check_fn;
-  }
-
-  static const jit_operation& for_index (void)
-  {
-    return instance->for_index_fn;
-  }
-
-  static const jit_operation& make_range (void)
-  {
-    return instance->make_range_fn;
-  }
-
-  static const jit_operation& paren_subsref (void)
-  {
-    return instance->paren_subsref_fn;
-  }
-
-  static const jit_operation& paren_subsasgn (void)
-  {
-    return instance->paren_subsasgn_fn;
-  }
-
-  static const jit_operation& logically_true (void)
-  {
-    return instance->logically_true_fn;
-  }
-
-  static const jit_operation& cast (jit_type *result)
-  {
-    return instance->do_cast (result);
-  }
-
-  static const jit_function& cast (jit_type *to, jit_type *from)
-  {
-    return instance->do_cast (to, from);
-  }
-
-  static llvm::Value *insert_error_check (llvm::IRBuilderD& bld)
-  {
-    return instance->do_insert_error_check (bld);
-  }
-
-  static const jit_operation& end (void)
-  {
-    return instance->end_fn;
-  }
-
-  static const jit_function& end (jit_type *ty)
-  {
-    return instance->end_fn.overload (ty);
-  }
-private:
-  jit_typeinfo (llvm::Module *m, llvm::ExecutionEngine *e);
-
-  // FIXME: Do these methods really need to be in jit_typeinfo?
-  jit_type *do_join (jit_type *lhs, jit_type *rhs)
-  {
-    // empty case
-    if (! lhs)
-      return rhs;
-
-    if (! rhs)
-      return lhs;
-
-    // check for a shared parent
-    while (lhs != rhs)
-      {
-        if (lhs->depth () > rhs->depth ())
-          lhs = lhs->parent ();
-        else if (lhs->depth () < rhs->depth ())
-          rhs = rhs->parent ();
-        else
-          {
-            // we MUST have depth > 0 as any is the base type of everything
-            do
-              {
-                lhs = lhs->parent ();
-                rhs = rhs->parent ();
-              }
-            while (lhs != rhs);
-          }
-      }
-
-    return lhs;
-  }
-
-  jit_type *do_difference (jit_type *lhs, jit_type *)
-  {
-    // FIXME: Maybe we can do something smarter?
-    return lhs;
-  }
-
-  jit_type *do_type_of (const octave_value &ov) const;
-
-  const jit_operation& do_binary_op (int op) const
-  {
-    assert (static_cast<size_t>(op) < binary_ops.size ());
-    return binary_ops[op];
-  }
-
-  const jit_operation& do_cast (jit_type *to)
-  {
-    static jit_operation null_function;
-    if (! to)
-      return null_function;
-
-    size_t id = to->type_id ();
-    if (id >= casts.size ())
-      return null_function;
-    return casts[id];
-  }
-
-  const jit_function& do_cast (jit_type *to, jit_type *from)
-  {
-    return do_cast (to).overload (from);
-  }
-
-  jit_type *new_type (const std::string& name, jit_type *parent,
-                      llvm::Type *llvm_type);
-
-
-  void add_print (jit_type *ty, void *fptr);
-
-  void add_binary_op (jit_type *ty, int op, int llvm_op);
-
-  void add_binary_icmp (jit_type *ty, int op, int llvm_op);
-
-  void add_binary_fcmp (jit_type *ty, int op, int llvm_op);
-
-  jit_function create_function (jit_convention::type cc,
-                                const llvm::Twine& name, jit_type *ret,
-                                const std::vector<jit_type *>& args
-                                = std::vector<jit_type *> ());
-
-#define JIT_PARAM_ARGS jit_convention::type cc, const llvm::Twine& name, \
-    jit_type *ret,
-#define JIT_PARAMS cc, name, ret,
-#define CREATE_FUNCTION(N) JIT_EXPAND(jit_function, create_function,    \
-                                      jit_type *, /* empty */, N)
-
-  CREATE_FUNCTION(1);
-  CREATE_FUNCTION(2);
-  CREATE_FUNCTION(3);
-  CREATE_FUNCTION(4);
-
-#undef JIT_PARAM_ARGS
-#undef JIT_PARAMS
-#undef CREATE_FUNCTION
-
-  jit_function create_identity (jit_type *type);
-
-  llvm::Value *do_insert_error_check (llvm::IRBuilderD& bld);
-
-  void add_builtin (const std::string& name);
-
-  void register_intrinsic (const std::string& name, size_t id,
-                           jit_type *result, jit_type *arg0)
-  {
-    std::vector<jit_type *> args (1, arg0);
-    register_intrinsic (name, id, result, args);
-  }
-
-  void register_intrinsic (const std::string& name, size_t id, jit_type *result,
-                           const std::vector<jit_type *>& args);
-
-  void register_generic (const std::string& name, jit_type *result,
-                         jit_type *arg0)
-  {
-    std::vector<jit_type *> args (1, arg0);
-    register_generic (name, result, args);
-  }
-
-  void register_generic (const std::string& name, jit_type *result,
-                         const std::vector<jit_type *>& args);
-
-  octave_builtin *find_builtin (const std::string& name);
-
-  jit_function mirror_binary (const jit_function& fn);
-
-  llvm::Function *wrap_complex (llvm::Function *wrap);
-
-  static llvm::Value *pack_complex (llvm::IRBuilderD& bld,
-                                    llvm::Value *cplx);
-
-  static llvm::Value *unpack_complex (llvm::IRBuilderD& bld,
-                                      llvm::Value *result);
-
-  llvm::Value *complex_real (llvm::Value *cx);
-
-  llvm::Value *complex_real (llvm::Value *cx, llvm::Value *real);
-
-  llvm::Value *complex_imag (llvm::Value *cx);
-
-  llvm::Value *complex_imag (llvm::Value *cx, llvm::Value *imag);
-
-  llvm::Value *complex_new (llvm::Value *real, llvm::Value *imag);
-
-  void create_int (size_t nbits);
-
-  jit_type *intN (size_t nbits) const;
-
-  static jit_typeinfo *instance;
-
-  llvm::Module *module;
-  llvm::ExecutionEngine *engine;
-  int next_id;
-
-  llvm::GlobalVariable *lerror_state;
-
-  std::vector<jit_type*> id_to_type;
-  jit_type *any;
-  jit_type *matrix;
-  jit_type *scalar;
-  jit_type *scalar_ptr; // a fake type for interfacing with C++
-  jit_type *range;
-  jit_type *string;
-  jit_type *boolean;
-  jit_type *index;
-  jit_type *complex;
-  jit_type *unknown_function;
-  std::map<size_t, jit_type *> ints;
-  std::map<std::string, jit_type *> builtins;
-
-  llvm::StructType *complex_ret;
-
-  std::vector<jit_operation> binary_ops;
-  jit_operation grab_fn;
-  jit_operation release_fn;
-  jit_operation print_fn;
-  jit_operation for_init_fn;
-  jit_operation for_check_fn;
-  jit_operation for_index_fn;
-  jit_operation logically_true_fn;
-  jit_operation make_range_fn;
-  jit_paren_subsref paren_subsref_fn;
-  jit_paren_subsasgn paren_subsasgn_fn;
-  jit_operation end_fn;
-
-  // type id -> cast function TO that type
-  std::vector<jit_operation> casts;
-
-  // type id -> identity function
-  std::vector<jit_function> identities;
-
-  llvm::IRBuilderD& builder;
-};
-
-#endif
-#endif
--- a/src/jit-util.cc	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-/*
-
-Copyright (C) 2012 Max Brister <max@2bass.com>
-
-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/>.
-
-*/
-
-// defines required by llvm
-#define __STDC_LIMIT_MACROS
-#define __STDC_CONSTANT_MACROS
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifdef HAVE_LLVM
-
-#include <llvm/Value.h>
-#include <llvm/Support/raw_os_ostream.h>
-
-std::ostream&
-operator<< (std::ostream& os, const llvm::Value& v)
-{
-  llvm::raw_os_ostream llvm_out (os);
-  v.print (llvm_out);
-  return os;
-}
-
-#endif
--- a/src/jit-util.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,203 +0,0 @@
-/*
-
-Copyright (C) 2012 Max Brister <max@2bass.com>
-
-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/>.
-
-*/
-
-// Some utility classes and functions used throughout jit
-
-#if !defined (octave_jit_util_h)
-#define octave_jit_util_h 1
-
-#ifdef HAVE_LLVM
-
-#include <stdexcept>
-
-// we don't want to include llvm headers here, as they require
-// __STDC_LIMIT_MACROS and __STDC_CONSTANT_MACROS be defined in the entire
-// compilation unit
-namespace llvm
-{
-  class Value;
-  class Module;
-  class FunctionPassManager;
-  class PassManager;
-  class ExecutionEngine;
-  class Function;
-  class BasicBlock;
-  class LLVMContext;
-  class Type;
-  class StructType;
-  class Twine;
-  class GlobalVariable;
-  class TerminatorInst;
-  class PHINode;
-
-  class ConstantFolder;
-
-  template <bool preserveNames>
-  class IRBuilderDefaultInserter;
-
-  template <bool preserveNames, typename T, typename Inserter>
-  class IRBuilder;
-
-typedef IRBuilder<true, ConstantFolder, IRBuilderDefaultInserter<true> >
-IRBuilderD;
-}
-
-class octave_base_value;
-class octave_builtin;
-class octave_value;
-class tree;
-class tree_expression;
-
-// thrown when we should give up on JIT and interpret
-class jit_fail_exception : public std::runtime_error
-{
-public:
-  jit_fail_exception (void) : std::runtime_error ("unknown"), mknown (false) {}
-  jit_fail_exception (const std::string& reason) : std::runtime_error (reason),
-                                                   mknown (true)
-  {}
-
-  bool known (void) const { return mknown; }
-private:
-  bool mknown;
-};
-
-// llvm doesn't provide this, and it's really useful for debugging
-std::ostream& operator<< (std::ostream& os, const llvm::Value& v);
-
-template <typename HOLDER_T, typename SUB_T>
-class jit_internal_node;
-
-// jit_internal_list and jit_internal_node implement generic embedded doubly
-// linked lists. List items extend from jit_internal_list, and can be placed
-// in nodes of type jit_internal_node. We use CRTP twice.
-template <typename LIST_T, typename NODE_T>
-class
-jit_internal_list
-{
-  friend class jit_internal_node<LIST_T, NODE_T>;
-public:
-  jit_internal_list (void) : use_head (0), use_tail (0), muse_count (0) {}
-
-  virtual ~jit_internal_list (void)
-  {
-    while (use_head)
-      use_head->stash_value (0);
-  }
-
-  NODE_T *first_use (void) const { return use_head; }
-
-  size_t use_count (void) const { return muse_count; }
-private:
-  NODE_T *use_head;
-  NODE_T *use_tail;
-  size_t muse_count;
-};
-
-// a node for internal linked lists
-template <typename LIST_T, typename NODE_T>
-class
-jit_internal_node
-{
-public:
-  typedef jit_internal_list<LIST_T, NODE_T> jit_ilist;
-
-  jit_internal_node (void) : mvalue (0), mnext (0), mprev (0) {}
-
-  ~jit_internal_node (void) { remove (); }
-
-  LIST_T *value (void) const { return mvalue; }
-
-  void stash_value (LIST_T *avalue)
-  {
-    remove ();
-
-    mvalue = avalue;
-
-    if (mvalue)
-      {
-        jit_ilist *ilist = mvalue;
-        NODE_T *sthis = static_cast<NODE_T *> (this);
-        if (ilist->use_head)
-          {
-            ilist->use_tail->mnext = sthis;
-            mprev = ilist->use_tail;
-          }
-        else
-          ilist->use_head = sthis;
-
-        ilist->use_tail = sthis;
-        ++ilist->muse_count;
-      }
-  }
-
-  NODE_T *next (void) const { return mnext; }
-
-  NODE_T *prev (void) const { return mprev; }
-private:
-  void remove ()
-  {
-    if (mvalue)
-      {
-        jit_ilist *ilist = mvalue;
-        if (mprev)
-          mprev->mnext = mnext;
-        else
-          // we are the use_head
-          ilist->use_head = mnext;
-
-        if (mnext)
-          mnext->mprev = mprev;
-        else
-          // we are the use tail
-          ilist->use_tail = mprev;
-
-        mnext = mprev = 0;
-        --ilist->muse_count;
-        mvalue = 0;
-      }
-  }
-
-  LIST_T *mvalue;
-  NODE_T *mnext;
-  NODE_T *mprev;
-};
-
-// Use like: isa<jit_phi> (value)
-// basically just a short cut type typing dyanmic_cast.
-template <typename T, typename U>
-bool isa (U *value)
-{
-  return dynamic_cast<T *> (value);
-}
-
-#define JIT_ASSIGN_ARG(i) the_args[i] = arg ## i;
-#define JIT_EXPAND(ret, fname, type, isconst, N)                        \
-  ret fname (JIT_PARAM_ARGS OCT_MAKE_DECL_LIST (type, arg, N)) isconst  \
-  {                                                                     \
-    std::vector<type> the_args (N);                                     \
-    OCT_ITERATE_MACRO (JIT_ASSIGN_ARG, N);                              \
-    return fname (JIT_PARAMS the_args);                                 \
-  }
-
-#endif
-#endif
--- a/src/ls-ascii-helper.cc	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,175 +0,0 @@
-/*
-
-Copyright (C) 2009-2012 Benjamin Lindner
-
-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/>.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "ls-ascii-helper.h"
-
-#include <iostream>
-#include <sstream>
-
-// Helper functions when reading from ascii files.
-
-// These function take care of CR/LF issues when files are opened in
-// text-mode for reading.
-
-// Skip characters from stream IS until a newline is reached.
-// Depending on KEEP_NEWLINE, either eat newline from stream or
-// keep it unread.
-
-void
-skip_until_newline (std::istream& is, bool keep_newline)
-{
-  if (! is)
-    return;
-
-  while (is)
-    {
-      char c = is.peek ();
-
-      if (c == '\n' || c == '\r')
-        {
-          // Reached newline.
-          if (! keep_newline)
-            {
-              // Eat the CR or LF character.
-              char d;
-              is.get (d);
-
-              // Make sure that for binary-mode opened ascii files
-              // containing CRLF line endings we skip the LF after CR.
-              if (c == '\r' && is.peek () == '\n')
-                {
-                  // Yes, LF following CR, eat it.
-                  is.get (d);
-                }
-            }
-
-          // Newline was found, and read from stream if
-          // keep_newline == true, so exit loop.
-          break;
-        }
-      else
-        {
-          // No newline charater peeked, so read it and proceed to next
-          // character.
-          char d;
-          is.get (d);
-        }
-    }
-}
-
-
-// If stream IS currently points to a newline (a leftover from a
-// previous read) then eat newline(s) until a non-newline character is
-// found.
-
-void
-skip_preceeding_newline (std::istream& is)
-{
-  if (! is)
-    return;
-
-  // Check whether IS currently points to newline character.
-  char c = is.peek ();
-
-  if (c == '\n' || c == '\r')
-    {
-      // Yes, at newline.
-      do
-        {
-          // Eat the CR or LF character.
-          char d;
-          is.get (d);
-
-          // Make sure that for binary-mode opened ascii files
-          // containing CRLF line endings we skip the LF after CR.
-          if (c == '\r' && is.peek () == '\n')
-            {
-              // Yes, LF following CR, eat it.
-              is.get (d);
-          }
-
-          // Peek into next character.
-          c = is.peek ();
-
-          // Loop while still a newline ahead.
-        }
-      while (c == '\n' || c == '\r');
-    }
-}
-
-// Read charaters from stream IS until a newline is reached.
-// Depending on KEEP_NEWLINE, either eat newline from stream or keep
-// it unread.  Characters read are stored and returned as
-// std::string.
-
-std::string
-read_until_newline (std::istream& is, bool keep_newline)
-{
-  if (! is)
-    return std::string ();
-
-  std::ostringstream buf;
-
-  while (is)
-    {
-      char c = is.peek ();
-
-      if (c == '\n' || c == '\r')
-        {
-          // Reached newline.
-          if (! keep_newline)
-            {
-              // Eat the CR or LF character.
-              char d;
-              is.get (d);
-
-              // Make sure that for binary-mode opened ascii files
-              // containing CRLF line endings we skip the LF after
-              // CR.
-
-              if (c == '\r' && is.peek () == '\n')
-                {
-                  // Yes, LF following CR, eat it.
-                  is.get (d);
-                }
-            }
-
-          // Newline was found, and read from stream if
-          // keep_newline == true, so exit loop.
-          break;
-        }
-      else
-        {
-          // No newline charater peeked, so read it, store it, and
-          // proceed to next.
-          char d;
-          is.get (d);
-          buf << d;
-        }
-    }
-
-  return buf.str ();
-}
--- a/src/ls-ascii-helper.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-/*
-
-Copyright (C) 2009-2012 Benjamin Lindner
-
-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/>.
-
-*/
-
-#if !defined (octave_ls_ascii_helper_h)
-#define octave_ls_ascii_helper_h 1
-
-#include <iosfwd>
-#include <string>
-
-extern OCTINTERP_API void
-skip_until_newline (std::istream& is, bool keep_newline = false);
-
-extern OCTINTERP_API void
-skip_preceeding_newline (std::istream& is);
-
-extern OCTINTERP_API std::string
-read_until_newline (std::istream& is, bool keep_newline = false);
-
-#endif
--- a/src/ls-hdf5.cc	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,921 +0,0 @@
-/*
-
-Copyright (C) 1996-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-// Author: Steven G. Johnson <stevenj@alum.mit.edu>
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#if defined (HAVE_HDF5)
-
-#include <cfloat>
-#include <cstring>
-#include <cctype>
-
-#include <fstream>
-#include <iomanip>
-#include <iostream>
-#include <string>
-#include <vector>
-
-#include "byte-swap.h"
-#include "data-conv.h"
-#include "file-ops.h"
-#include "glob-match.h"
-#include "lo-mappers.h"
-#include "mach-info.h"
-#include "oct-env.h"
-#include "oct-time.h"
-#include "quit.h"
-#include "str-vec.h"
-#include "oct-locbuf.h"
-
-#include "Cell.h"
-#include "defun.h"
-#include "error.h"
-#include "gripes.h"
-#include "load-save.h"
-#include "oct-obj.h"
-#include "oct-map.h"
-#include "ov-cell.h"
-#include "pager.h"
-#include "pt-exp.h"
-#include "sysdep.h"
-#include "unwind-prot.h"
-#include "utils.h"
-#include "variables.h"
-#include "version.h"
-#include "dMatrix.h"
-#include "ov-lazy-idx.h"
-
-#include "ls-utils.h"
-#include "ls-hdf5.h"
-
-static std::string
-make_valid_identifier (const std::string& nm)
-{
-  std::string retval;
-
-  size_t nm_len = nm.length ();
-
-  if (nm_len > 0)
-    {
-      if (! isalpha (nm[0]))
-        retval += '_';
-
-      for (size_t i = 0; i < nm_len; i++)
-        {
-          char c = nm[i];
-          retval += (isalnum (c) || c == '_') ? c : '_';
-        }
-    }
-
-  return retval;
-}
-
-// Define this to 1 if/when HDF5 supports automatic conversion between
-// integer and floating-point binary data:
-#define HAVE_HDF5_INT2FLOAT_CONVERSIONS 0
-
-// Given two compound types t1 and t2, determine whether they
-// are compatible for reading/writing.  This function only
-// works for non-nested types composed of simple elements (ints, floats...),
-// which is all we need it for
-
-bool
-hdf5_types_compatible (hid_t t1, hid_t t2)
-{
-  int n;
-  if ((n = H5Tget_nmembers (t1)) != H5Tget_nmembers (t2))
-    return false;
-
-  for (int i = 0; i < n; ++i)
-    {
-      hid_t mt1 = H5Tget_member_type (t1, i);
-      hid_t mt2 = H5Tget_member_type (t2, i);
-
-      if (H5Tget_class (mt1) != H5Tget_class (mt2))
-        return false;
-
-      H5Tclose (mt2);
-      H5Tclose (mt1);
-    }
-
-  return true;
-}
-
-// Return true if loc_id has the attribute named attr_name, and false
-// otherwise.
-
-bool
-hdf5_check_attr (hid_t loc_id, const char *attr_name)
-{
-  bool retval = false;
-
-  // we have to pull some shenanigans here to make sure
-  // HDF5 doesn't print out all sorts of error messages if we
-  // call H5Aopen for a non-existing attribute
-
-  H5E_auto_t err_func;
-  void *err_func_data;
-
-  // turn off error reporting temporarily, but save the error
-  // reporting function:
-
-#if HAVE_HDF5_18
-  H5Eget_auto (H5E_DEFAULT, &err_func, &err_func_data);
-  H5Eset_auto (H5E_DEFAULT, 0, 0);
-#else
-  H5Eget_auto (&err_func, &err_func_data);
-  H5Eset_auto (0, 0);
-#endif
-
-  hid_t attr_id = H5Aopen_name (loc_id, attr_name);
-
-  if (attr_id >= 0)
-    {
-      // successful
-      retval = true;
-      H5Aclose (attr_id);
-    }
-
-  // restore error reporting:
-#if HAVE_HDF5_18
-  H5Eset_auto (H5E_DEFAULT, err_func, err_func_data);
-#else
-  H5Eset_auto (err_func, err_func_data);
-#endif
-  return retval;
-}
-
-bool
-hdf5_get_scalar_attr (hid_t loc_id, hid_t type_id,
-                      const char *attr_name, void *buf)
-{
-  bool retval = false;
-
-  // we have to pull some shenanigans here to make sure
-  // HDF5 doesn't print out all sorts of error messages if we
-  // call H5Aopen for a non-existing attribute
-
-  H5E_auto_t err_func;
-  void *err_func_data;
-
-  // turn off error reporting temporarily, but save the error
-  // reporting function:
-
-#if HAVE_HDF5_18
-  H5Eget_auto (H5E_DEFAULT, &err_func, &err_func_data);
-  H5Eset_auto (H5E_DEFAULT, 0, 0);
-#else
-  H5Eget_auto (&err_func, &err_func_data);
-  H5Eset_auto (0, 0);
-#endif
-
-  hid_t attr_id = H5Aopen_name (loc_id, attr_name);
-
-  if (attr_id >= 0)
-    {
-      hid_t space_id = H5Aget_space (attr_id);
-
-      hsize_t rank = H5Sget_simple_extent_ndims (space_id);
-
-      if (rank == 0)
-        retval = H5Aread (attr_id, type_id, buf) >= 0;
-      H5Aclose (attr_id);
-    }
-
-  // restore error reporting:
-#if HAVE_HDF5_18
-  H5Eset_auto (H5E_DEFAULT, err_func, err_func_data);
-#else
-  H5Eset_auto (err_func, err_func_data);
-#endif
-  return retval;
-}
-
-
-
-
-// The following subroutines creates an HDF5 representations of the way
-// we will store Octave complex types (pairs of floating-point numbers).
-// NUM_TYPE is the HDF5 numeric type to use for storage (e.g.
-// H5T_NATIVE_DOUBLE to save as 'double'). Note that any necessary
-// conversions are handled automatically by HDF5.
-
-hid_t
-hdf5_make_complex_type (hid_t num_type)
-{
-  hid_t type_id = H5Tcreate (H5T_COMPOUND, sizeof (double) * 2);
-
-  H5Tinsert (type_id, "real", 0 * sizeof (double), num_type);
-  H5Tinsert (type_id, "imag", 1 * sizeof (double), num_type);
-
-  return type_id;
-}
-
-// This function is designed to be passed to H5Giterate, which calls it
-// on each data item in an HDF5 file.  For the item whose name is NAME in
-// the group GROUP_ID, this function sets dv->tc to an Octave representation
-// of that item.  (dv must be a pointer to hdf5_callback_data.)  (It also
-// sets the other fields of dv).
-//
-// It returns 1 on success (in which case H5Giterate stops and returns),
-// -1 on error, and 0 to tell H5Giterate to continue on to the next item
-// (e.g. if NAME was a data type we don't recognize).
-
-herr_t
-hdf5_read_next_data (hid_t group_id, const char *name, void *dv)
-{
-  hdf5_callback_data *d = static_cast <hdf5_callback_data *> (dv);
-  hid_t type_id = -1, type_class_id = -1, data_id = -1, subgroup_id = -1,
-    space_id = -1;
-
-  H5G_stat_t info;
-  herr_t retval = 0;
-  bool ident_valid = valid_identifier (name);
-
-  std::string vname = name;
-
-  // Allow identifiers as all digits so we can load lists saved by
-  // earlier versions of Octave.
-
-  if (! ident_valid )
-    {
-      // fix the identifier, replacing invalid chars with underscores
-      vname = make_valid_identifier (vname);
-
-      // check again (in case vname was null, empty, or some such thing):
-      ident_valid = valid_identifier (vname);
-    }
-
-  H5Gget_objinfo (group_id, name, 1, &info);
-
-  if (info.type == H5G_GROUP && ident_valid)
-    {
-#if HAVE_HDF5_18
-      subgroup_id = H5Gopen (group_id, name, H5P_DEFAULT);
-#else
-      subgroup_id = H5Gopen (group_id, name);
-#endif
-
-      if (subgroup_id < 0)
-        {
-          retval = subgroup_id;
-          goto done;
-        }
-
-      if (hdf5_check_attr (subgroup_id, "OCTAVE_NEW_FORMAT"))
-        {
-#if HAVE_HDF5_18
-          data_id = H5Dopen (subgroup_id, "type", H5P_DEFAULT);
-#else
-          data_id = H5Dopen (subgroup_id, "type");
-#endif
-
-          if (data_id < 0)
-            {
-              retval = data_id;
-              goto done;
-            }
-
-          type_id = H5Dget_type (data_id);
-
-          type_class_id = H5Tget_class (type_id);
-
-          if (type_class_id != H5T_STRING)
-            goto done;
-
-          space_id = H5Dget_space (data_id);
-          hsize_t rank = H5Sget_simple_extent_ndims (space_id);
-
-          if (rank != 0)
-            goto done;
-
-          int slen = H5Tget_size (type_id);
-          if (slen < 0)
-            goto done;
-
-          OCTAVE_LOCAL_BUFFER (char, typ, slen);
-
-          // create datatype for (null-terminated) string to read into:
-          hid_t st_id = H5Tcopy (H5T_C_S1);
-          H5Tset_size (st_id, slen);
-
-          if (H5Dread (data_id, st_id, H5S_ALL, H5S_ALL, H5P_DEFAULT,
-                       typ) < 0)
-            goto done;
-
-          H5Tclose (st_id);
-          H5Dclose (data_id);
-
-          d->tc = octave_value_typeinfo::lookup_type (typ);
-
-          retval = (d->tc.load_hdf5 (subgroup_id, "value") ? 1 : -1);
-
-          // check for OCTAVE_GLOBAL attribute:
-          d->global = hdf5_check_attr (subgroup_id, "OCTAVE_GLOBAL");
-
-          H5Gclose (subgroup_id);
-        }
-      else
-        {
-          // an HDF5 group is treated as an octave structure by
-          // default (since that preserves name information), and an
-          // octave list otherwise.
-
-          if (hdf5_check_attr (subgroup_id, "OCTAVE_LIST"))
-            d->tc = octave_value_typeinfo::lookup_type ("list");
-          else
-            d->tc = octave_value_typeinfo::lookup_type ("struct");
-
-          // check for OCTAVE_GLOBAL attribute:
-          d->global = hdf5_check_attr (subgroup_id, "OCTAVE_GLOBAL");
-
-          H5Gclose (subgroup_id);
-
-          retval = (d->tc.load_hdf5 (group_id, name) ? 1 : -1);
-        }
-
-    }
-  else if (info.type == H5G_DATASET && ident_valid)
-    {
-      // For backwards compatiability.
-#if HAVE_HDF5_18
-      data_id = H5Dopen (group_id, name, H5P_DEFAULT);
-#else
-      data_id = H5Dopen (group_id, name);
-#endif
-
-      if (data_id < 0)
-        {
-          retval = data_id;
-          goto done;
-        }
-
-      type_id = H5Dget_type (data_id);
-
-      type_class_id = H5Tget_class (type_id);
-
-      if (type_class_id == H5T_FLOAT)
-        {
-          space_id = H5Dget_space (data_id);
-
-          hsize_t rank = H5Sget_simple_extent_ndims (space_id);
-
-          if (rank == 0)
-            d->tc = octave_value_typeinfo::lookup_type ("scalar");
-          else
-            d->tc = octave_value_typeinfo::lookup_type ("matrix");
-
-          H5Sclose (space_id);
-        }
-      else if (type_class_id == H5T_INTEGER)
-        {
-          // What integer type do we really have..
-          std::string int_typ;
-#ifdef HAVE_H5T_GET_NATIVE_TYPE
-          // FIXME test this code and activated with an autoconf
-          // test!! It is also incorrect for 64-bit indexing!!
-
-          switch (H5Tget_native_type (type_id, H5T_DIR_ASCEND))
-            {
-            case H5T_NATIVE_CHAR:
-              int_typ = "int8 ";
-              break;
-
-            case H5T_NATIVE_SHORT:
-              int_typ = "int16 ";
-              break;
-
-            case H5T_NATIVE_INT:
-            case H5T_NATIVE_LONG:
-              int_typ = "int32 ";
-              break;
-
-            case H5T_NATIVE_LLONG:
-              int_typ = "int64 ";
-              break;
-
-            case H5T_NATIVE_UCHAR:
-              int_typ = "uint8 ";
-              break;
-
-            case H5T_NATIVE_USHORT:
-              int_typ = "uint16 ";
-              break;
-
-            case H5T_NATIVE_UINT:
-            case H5T_NATIVE_ULONG:
-              int_typ = "uint32 ";
-              break;
-
-            case H5T_NATIVE_ULLONG:
-              int_typ = "uint64 ";
-              break;
-            }
-#else
-          hid_t int_sign = H5Tget_sign (type_id);
-
-          if (int_sign == H5T_SGN_ERROR)
-            warning ("load: can't read `%s' (unknown datatype)", name);
-          else
-            {
-              if (int_sign == H5T_SGN_NONE)
-                int_typ.append ("u");
-              int_typ.append ("int");
-
-              int slen = H5Tget_size (type_id);
-              if (slen < 0)
-                warning ("load: can't read `%s' (unknown datatype)", name);
-              else
-                {
-                  switch (slen)
-                    {
-                    case 1:
-                      int_typ.append ("8 ");
-                      break;
-
-                    case 2:
-                      int_typ.append ("16 ");
-                      break;
-
-                    case 4:
-                      int_typ.append ("32 ");
-                      break;
-
-                    case 8:
-                      int_typ.append ("64 ");
-                      break;
-
-                    default:
-                      warning ("load: can't read `%s' (unknown datatype)",
-                               name);
-                      int_typ = "";
-                      break;
-                    }
-                }
-            }
-#endif
-          if (int_typ == "")
-            warning ("load: can't read `%s' (unknown datatype)", name);
-          else
-            {
-              // Matrix or scalar?
-              space_id = H5Dget_space (data_id);
-
-              hsize_t rank = H5Sget_simple_extent_ndims (space_id);
-
-              if (rank == 0)
-                int_typ.append ("scalar");
-              else
-                int_typ.append ("matrix");
-
-              d->tc = octave_value_typeinfo::lookup_type (int_typ);
-              H5Sclose (space_id);
-            }
-        }
-      else if (type_class_id == H5T_STRING)
-        d->tc = octave_value_typeinfo::lookup_type ("string");
-      else if (type_class_id == H5T_COMPOUND)
-        {
-          hid_t complex_type = hdf5_make_complex_type (H5T_NATIVE_DOUBLE);
-
-          if (hdf5_types_compatible (type_id, complex_type))
-            {
-              // read complex matrix or scalar variable
-              space_id = H5Dget_space (data_id);
-              hsize_t rank = H5Sget_simple_extent_ndims (space_id);
-
-              if (rank == 0)
-                d->tc = octave_value_typeinfo::lookup_type ("complex scalar");
-              else
-                d->tc = octave_value_typeinfo::lookup_type ("complex matrix");
-
-              H5Sclose (space_id);
-            }
-          else
-            // Assume that if its not complex its a range. If its not
-            // it'll be rejected later in the range code
-            d->tc = octave_value_typeinfo::lookup_type ("range");
-
-          H5Tclose (complex_type);
-        }
-      else
-        {
-          warning ("load: can't read `%s' (unknown datatype)", name);
-          retval = 0; // unknown datatype; skip
-        }
-
-      // check for OCTAVE_GLOBAL attribute:
-      d->global = hdf5_check_attr (data_id, "OCTAVE_GLOBAL");
-
-      H5Tclose (type_id);
-      H5Dclose (data_id);
-
-      retval = (d->tc.load_hdf5 (group_id, name) ? 1 : -1);
-    }
-
-  if (!ident_valid)
-    {
-      // should we attempt to handle invalid identifiers by converting
-      // bad characters to '_', say?
-      warning ("load: skipping invalid identifier `%s' in hdf5 file",
-               name);
-    }
-
- done:
-  if (retval < 0)
-    error ("load: error while reading hdf5 item %s", name);
-
-  if (retval > 0)
-    {
-      // get documentation string, if any:
-      int comment_length = H5Gget_comment (group_id, name, 0, 0);
-
-      if (comment_length > 1)
-        {
-          OCTAVE_LOCAL_BUFFER (char, tdoc, comment_length);
-          H5Gget_comment (group_id, name, comment_length, tdoc);
-          d->doc = tdoc;
-        }
-      else if (vname != name)
-        {
-          // the name was changed; store the original name
-          // as the documentation string:
-          d->doc = name;
-        }
-
-      // copy name (actually, vname):
-      d->name = vname;
-    }
-
-  return retval;
-}
-
-// Read the next Octave variable from the stream IS, which must really be
-// an hdf5_ifstream.  Return the variable value in tc, its doc string
-// in doc, and whether it is global in global.  The return value is
-// the name of the variable, or NULL if none were found or there was
-// and error.
-std::string
-read_hdf5_data (std::istream& is, const std::string& /* filename */,
-                bool& global, octave_value& tc, std::string& doc)
-{
-  std::string retval;
-
-  doc.resize (0);
-
-  hdf5_ifstream& hs = dynamic_cast<hdf5_ifstream&> (is);
-  hdf5_callback_data d;
-
-  herr_t H5Giterate_retval = -1;
-
-  hsize_t num_obj = 0;
-#if HAVE_HDF5_18
-  hid_t group_id = H5Gopen (hs.file_id, "/", H5P_DEFAULT);
-#else
-  hid_t group_id = H5Gopen (hs.file_id, "/");
-#endif
-  H5Gget_num_objs (group_id, &num_obj);
-  H5Gclose (group_id);
-  if (hs.current_item < static_cast<int> (num_obj))
-    H5Giterate_retval = H5Giterate (hs.file_id, "/", &hs.current_item,
-                                    hdf5_read_next_data, &d);
-
-  if (H5Giterate_retval > 0)
-    {
-      global = d.global;
-      tc = d.tc;
-      doc = d.doc;
-    }
-  else
-    {
-      // an error occurred (H5Giterate_retval < 0) or there are no
-      // more datasets print an error message if retval < 0?
-      // hdf5_read_next_data already printed one, probably.
-    }
-
-  if (! d.name.empty ())
-    retval = d.name;
-
-  return retval;
-}
-
-// Add an attribute named attr_name to loc_id (a simple scalar
-// attribute with value 1).  Return value is >= 0 on success.
-herr_t
-hdf5_add_attr (hid_t loc_id, const char *attr_name)
-{
-  herr_t retval = 0;
-
-  hid_t as_id = H5Screate (H5S_SCALAR);
-
-  if (as_id >= 0)
-    {
-#if HAVE_HDF5_18
-      hid_t a_id = H5Acreate (loc_id, attr_name, H5T_NATIVE_UCHAR,
-                              as_id, H5P_DEFAULT, H5P_DEFAULT);
-#else
-      hid_t a_id = H5Acreate (loc_id, attr_name,
-                              H5T_NATIVE_UCHAR, as_id, H5P_DEFAULT);
-#endif
-      if (a_id >= 0)
-        {
-          unsigned char attr_val = 1;
-
-          retval = H5Awrite (a_id, H5T_NATIVE_UCHAR, &attr_val);
-
-          H5Aclose (a_id);
-        }
-      else
-        retval = a_id;
-
-      H5Sclose (as_id);
-    }
-  else
-    retval = as_id;
-
-  return retval;
-}
-
-herr_t
-hdf5_add_scalar_attr (hid_t loc_id, hid_t type_id,
-                      const char *attr_name, void *buf)
-{
-  herr_t retval = 0;
-
-  hid_t as_id = H5Screate (H5S_SCALAR);
-
-  if (as_id >= 0)
-    {
-#if HAVE_HDF5_18
-      hid_t a_id = H5Acreate (loc_id, attr_name, type_id,
-                              as_id, H5P_DEFAULT, H5P_DEFAULT);
-#else
-      hid_t a_id = H5Acreate (loc_id, attr_name,
-                              type_id, as_id, H5P_DEFAULT);
-#endif
-      if (a_id >= 0)
-        {
-          retval = H5Awrite (a_id, type_id, buf);
-
-          H5Aclose (a_id);
-        }
-      else
-        retval = a_id;
-
-      H5Sclose (as_id);
-    }
-  else
-    retval = as_id;
-
-  return retval;
-}
-
-// Save an empty matrix, if needed. Returns
-//    > 0  Saved empty matrix
-//    = 0  Not an empty matrix; did nothing
-//    < 0  Error condition
-int
-save_hdf5_empty (hid_t loc_id, const char *name, const dim_vector d)
-{
-  hsize_t sz = d.length ();
-  OCTAVE_LOCAL_BUFFER (octave_idx_type, dims, sz);
-  bool empty = false;
-  hid_t space_hid = -1, data_hid = -1;
-  int retval;
-  for (hsize_t i = 0; i < sz; i++)
-    {
-      dims[i] = d(i);
-      if (dims[i] < 1)
-        empty = true;
-    }
-
-  if (!empty)
-    return 0;
-
-  space_hid = H5Screate_simple (1, &sz, 0);
-  if (space_hid < 0) return space_hid;
-#if HAVE_HDF5_18
-  data_hid = H5Dcreate (loc_id, name, H5T_NATIVE_IDX, space_hid,
-                        H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
-#else
-  data_hid = H5Dcreate (loc_id, name, H5T_NATIVE_IDX, space_hid,
-                        H5P_DEFAULT);
-#endif
-  if (data_hid < 0)
-    {
-      H5Sclose (space_hid);
-      return data_hid;
-    }
-
-  retval = H5Dwrite (data_hid, H5T_NATIVE_IDX, H5S_ALL, H5S_ALL,
-                     H5P_DEFAULT, dims) >= 0;
-
-  H5Dclose (data_hid);
-  H5Sclose (space_hid);
-
-  if (retval >= 0)
-    retval = hdf5_add_attr (loc_id, "OCTAVE_EMPTY_MATRIX");
-
-  return (retval == 0 ? 1 : retval);
-}
-
-// Load an empty matrix, if needed. Returns
-//    > 0  loaded empty matrix, dimensions returned
-//    = 0  Not an empty matrix; did nothing
-//    < 0  Error condition
-int
-load_hdf5_empty (hid_t loc_id, const char *name, dim_vector &d)
-{
-  if (! hdf5_check_attr (loc_id, "OCTAVE_EMPTY_MATRIX"))
-    return 0;
-
-  hsize_t hdims, maxdims;
-#if HAVE_HDF5_18
-  hid_t data_hid = H5Dopen (loc_id, name, H5P_DEFAULT);
-#else
-  hid_t data_hid = H5Dopen (loc_id, name);
-#endif
-  hid_t space_id = H5Dget_space (data_hid);
-  H5Sget_simple_extent_dims (space_id, &hdims, &maxdims);
-  int retval;
-
-  OCTAVE_LOCAL_BUFFER (octave_idx_type, dims, hdims);
-
-  retval = H5Dread (data_hid, H5T_NATIVE_IDX, H5S_ALL, H5S_ALL,
-                    H5P_DEFAULT, dims);
-  if (retval >= 0)
-    {
-      d.resize (hdims);
-      for (hsize_t i = 0; i < hdims; i++)
-        d(i) = dims[i];
-    }
-
-  H5Sclose (space_id);
-  H5Dclose (data_hid);
-
-  return (retval == 0 ? hdims : retval);
-}
-
-// save_type_to_hdf5 is not currently used, since hdf5 doesn't yet support
-// automatic float<->integer conversions:
-
-#if HAVE_HDF5_INT2FLOAT_CONVERSIONS
-
-// return the HDF5 type id corresponding to the Octave save_type
-
-hid_t
-save_type_to_hdf5 (save_type st)
-{
-  switch (st)
-    {
-    case LS_U_CHAR:
-      return H5T_NATIVE_UCHAR;
-
-    case LS_U_SHORT:
-      return H5T_NATIVE_USHORT;
-
-    case LS_U_INT:
-      return H5T_NATIVE_UINT;
-
-    case LS_CHAR:
-      return H5T_NATIVE_CHAR;
-
-    case LS_SHORT:
-      return H5T_NATIVE_SHORT;
-
-    case LS_INT:
-      return H5T_NATIVE_INT;
-
-    case LS_FLOAT:
-      return H5T_NATIVE_FLOAT;
-
-    case LS_DOUBLE:
-    default:
-      return H5T_NATIVE_DOUBLE;
-    }
-}
-#endif /* HAVE_HDF5_INT2FLOAT_CONVERSIONS */
-
-// Add the data from TC to the HDF5 location loc_id, which could
-// be either a file or a group within a file.  Return true if
-// successful.  This function calls itself recursively for lists
-// (stored as HDF5 groups).
-
-bool
-add_hdf5_data (hid_t loc_id, const octave_value& tc,
-               const std::string& name, const std::string& doc,
-               bool mark_as_global, bool save_as_floats)
-{
-  hsize_t dims[3];
-  hid_t type_id = -1, space_id = -1, data_id = -1, data_type_id = -1;
-  bool retval = false;
-  octave_value val = tc;
-  // FIXME: diagonal & permutation matrices currently don't know how to save
-  // themselves, so we convert them first to normal matrices using A = A(:,:).
-  // This is a temporary hack.
-  if (val.is_diag_matrix () || val.is_perm_matrix ()
-      || val.type_id () == octave_lazy_index::static_type_id ())
-    val = val.full_value ();
-
-  std::string t = val.type_name ();
-#if HAVE_HDF5_18
-  data_id = H5Gcreate (loc_id, name.c_str (), H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
-#else
-  data_id = H5Gcreate (loc_id, name.c_str (), 0);
-#endif
-  if (data_id < 0)
-    goto error_cleanup;
-
-  // attach the type of the variable
-  type_id = H5Tcopy (H5T_C_S1); H5Tset_size (type_id, t.length () + 1);
-  if (type_id < 0)
-    goto error_cleanup;
-
-  dims[0] = 0;
-  space_id = H5Screate_simple (0 , dims, 0);
-  if (space_id < 0)
-    goto error_cleanup;
-#if HAVE_HDF5_18
-  data_type_id = H5Dcreate (data_id, "type",  type_id, space_id,
-                            H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
-#else
-  data_type_id = H5Dcreate (data_id, "type",  type_id, space_id, H5P_DEFAULT);
-#endif
-  if (data_type_id < 0 || H5Dwrite (data_type_id, type_id, H5S_ALL, H5S_ALL,
-                                    H5P_DEFAULT, t.c_str ()) < 0)
-    goto error_cleanup;
-
-  // Now call the real function to save the variable
-  retval = val.save_hdf5 (data_id, "value", save_as_floats);
-
-  // attach doc string as comment:
-  if (retval && doc.length () > 0
-      && H5Gset_comment (loc_id, name.c_str (), doc.c_str ()) < 0)
-    retval = false;
-
-  // if it's global, add an attribute "OCTAVE_GLOBAL" with value 1
-  if (retval && mark_as_global)
-    retval = hdf5_add_attr (data_id, "OCTAVE_GLOBAL") >= 0;
-
-  // We are saving in the new variable format, so mark it
-  if (retval)
-    retval = hdf5_add_attr (data_id, "OCTAVE_NEW_FORMAT") >= 0;
-
- error_cleanup:
-
-  if (data_type_id >= 0)
-    H5Dclose (data_type_id);
-
-  if (type_id >= 0)
-    H5Tclose (type_id);
-
-  if (space_id >= 0)
-    H5Sclose (space_id);
-
-  if (data_id >= 0)
-    H5Gclose (data_id);
-
-  if (! retval)
-    error ("save: error while writing `%s' to hdf5 file", name.c_str ());
-
-  return retval;
-}
-
-// Write data from TC in HDF5 (binary) format to the stream OS,
-// which must be an hdf5_ofstream, returning true on success.
-
-bool
-save_hdf5_data (std::ostream& os, const octave_value& tc,
-                const std::string& name, const std::string& doc,
-                bool mark_as_global, bool save_as_floats)
-{
-  hdf5_ofstream& hs = dynamic_cast<hdf5_ofstream&> (os);
-
-  return add_hdf5_data (hs.file_id, tc, name, doc,
-                        mark_as_global, save_as_floats);
-}
-
-#endif
--- a/src/ls-hdf5.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,213 +0,0 @@
-/*
-
-Copyright (C) 2003-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#if !defined (octave_ls_hdf5_h)
-#define octave_ls_hdf5_h 1
-
-#if defined (HAVE_HDF5)
-
-#include "oct-hdf5.h"
-
-// first, we need to define our own dummy stream subclass, since
-// HDF5 needs to do its own file i/o
-
-// hdf5_fstreambase is used for both input and output streams, modeled
-// on the fstreambase class in <fstream.h>
-
-class hdf5_fstreambase : virtual public std::ios
-{
-public:
-
-  // HDF5 uses an "id" to refer to an open file
-  hid_t file_id;
-
-  // keep track of current item index in the file
-  int current_item;
-
-  hdf5_fstreambase () : file_id (-1), current_item () { }
-
-  ~hdf5_fstreambase () { close (); }
-
-  hdf5_fstreambase (const char *name, int mode, int /* prot */ = 0)
-    : file_id (-1), current_item (-1)
-    {
-      if (mode & std::ios::in)
-        file_id = H5Fopen (name, H5F_ACC_RDONLY, H5P_DEFAULT);
-      else if (mode & std::ios::out)
-        {
-          if (mode & std::ios::app && H5Fis_hdf5 (name) > 0)
-            file_id = H5Fopen (name, H5F_ACC_RDWR, H5P_DEFAULT);
-          else
-            file_id = H5Fcreate (name, H5F_ACC_TRUNC, H5P_DEFAULT,
-                                 H5P_DEFAULT);
-        }
-      if (file_id < 0)
-        std::ios::setstate (std::ios::badbit);
-
-      current_item = 0;
-    }
-
-  void close ()
-    {
-      if (file_id >= 0)
-        {
-          if (H5Fclose (file_id) < 0)
-            std::ios::setstate (std::ios::badbit);
-          file_id = -1;
-        }
-    }
-
-  void open (const char *name, int mode, int)
-    {
-      clear ();
-
-      if (mode & std::ios::in)
-        file_id = H5Fopen (name, H5F_ACC_RDONLY, H5P_DEFAULT);
-      else if (mode & std::ios::out)
-        {
-          if (mode & std::ios::app && H5Fis_hdf5 (name) > 0)
-            file_id = H5Fopen (name, H5F_ACC_RDWR, H5P_DEFAULT);
-          else
-            file_id = H5Fcreate (name, H5F_ACC_TRUNC, H5P_DEFAULT,
-                                 H5P_DEFAULT);
-        }
-      if (file_id < 0)
-        std::ios::setstate (std::ios::badbit);
-
-      current_item = 0;
-    }
-};
-
-// input and output streams, subclassing istream and ostream
-// so that we can pass them for stream parameters in the functions below.
-
-class hdf5_ifstream : public hdf5_fstreambase, public std::istream
-{
-public:
-
-  hdf5_ifstream () : hdf5_fstreambase (), std::istream (0) { }
-
-  hdf5_ifstream (const char *name, int mode = std::ios::in|std::ios::binary,
-                 int prot = 0)
-    : hdf5_fstreambase (name, mode, prot), std::istream (0) { }
-
-  void open (const char *name, int mode = std::ios::in|std::ios::binary,
-             int prot = 0)
-    { hdf5_fstreambase::open (name, mode, prot); }
-};
-
-class hdf5_ofstream : public hdf5_fstreambase, public std::ostream
-{
-public:
-
-  hdf5_ofstream () : hdf5_fstreambase (), std::ostream (0) { }
-
-  hdf5_ofstream (const char *name, int mode = std::ios::out|std::ios::binary,
-                 int prot = 0)
-    : hdf5_fstreambase (name, mode, prot), std::ostream (0) { }
-
-  void open (const char *name, int mode = std::ios::out|std::ios::binary,
-             int prot = 0)
-    { hdf5_fstreambase::open (name, mode, prot); }
-};
-
-// Callback data structure for passing data to hdf5_read_next_data, below.
-
-struct
-hdf5_callback_data
-{
-  hdf5_callback_data (void)
-    : name (), global (false), tc (), doc () { }
-
-  // the following fields are set by hdf5_read_data on successful return:
-
-  // the name of the variable
-  std::string name;
-
-  // whether it is global
-  bool global;
-
-  // the value of the variable, in Octave form
-  octave_value tc;
-
-  // a documentation string (NULL if none)
-  std::string doc;
-};
-
-#if HAVE_HDF5_INT2FLOAT_CONVERSIONS
-extern OCTINTERP_API hid_t
-save_type_to_hdf5 (save_type st)
-#endif
-
-extern OCTINTERP_API hid_t
-hdf5_make_complex_type (hid_t num_type);
-
-extern OCTINTERP_API bool
-hdf5_types_compatible (hid_t t1, hid_t t2);
-
-extern OCTINTERP_API herr_t
-hdf5_read_next_data (hid_t group_id, const char *name, void *dv);
-
-extern OCTINTERP_API bool
-add_hdf5_data (hid_t loc_id, const octave_value& tc,
-               const std::string& name, const std::string& doc,
-               bool mark_as_global, bool save_as_floats);
-
-extern OCTINTERP_API int
-save_hdf5_empty (hid_t loc_id, const char *name, const dim_vector d);
-
-extern OCTINTERP_API int
-load_hdf5_empty (hid_t loc_id, const char *name, dim_vector &d);
-
-extern OCTINTERP_API std::string
-read_hdf5_data (std::istream& is,  const std::string& filename, bool& global,
-                octave_value& tc, std::string& doc);
-
-extern OCTINTERP_API bool
-save_hdf5_data (std::ostream& os, const octave_value& tc,
-                const std::string& name, const std::string& doc,
-                bool mark_as_global, bool save_as_floats);
-
-extern OCTINTERP_API bool
-hdf5_check_attr (hid_t loc_id, const char *attr_name);
-
-extern OCTINTERP_API bool
-hdf5_get_scalar_attr (hid_t loc_id, hid_t type_id, const char *attr_name,
-                      void *buf);
-
-extern OCTINTERP_API herr_t
-hdf5_add_attr (hid_t loc_id, const char *attr_name);
-
-
-extern OCTINTERP_API herr_t
-hdf5_add_scalar_attr (hid_t loc_id, hid_t type_id,
-                      const char *attr_name, void *buf);
-
-#ifdef IDX_TYPE_LONG
-#define H5T_NATIVE_IDX H5T_NATIVE_LONG
-#else
-#define H5T_NATIVE_IDX H5T_NATIVE_INT
-#endif
-
-#endif
-
-#endif
--- a/src/ls-mat-ascii.cc	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,378 +0,0 @@
-/*
-
-Copyright (C) 1996-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <cfloat>
-#include <cstring>
-#include <cctype>
-
-#include <fstream>
-#include <iomanip>
-#include <iostream>
-#include <sstream>
-#include <string>
-
-#include "byte-swap.h"
-#include "data-conv.h"
-#include "file-ops.h"
-#include "glob-match.h"
-#include "lo-mappers.h"
-#include "mach-info.h"
-#include "oct-env.h"
-#include "oct-time.h"
-#include "quit.h"
-#include "str-vec.h"
-
-#include "Cell.h"
-#include "defun.h"
-#include "error.h"
-#include "gripes.h"
-#include "lex.h"
-#include "load-save.h"
-#include "ls-ascii-helper.h"
-#include "ls-mat-ascii.h"
-#include "oct-obj.h"
-#include "oct-map.h"
-#include "ov-cell.h"
-#include "pager.h"
-#include "pt-exp.h"
-#include "sysdep.h"
-#include "unwind-prot.h"
-#include "utils.h"
-#include "variables.h"
-#include "version.h"
-#include "dMatrix.h"
-
-static std::string
-get_mat_data_input_line (std::istream& is)
-{
-  std::string retval;
-
-  bool have_data = false;
-
-  do
-    {
-      retval = "";
-
-      char c;
-      while (is.get (c))
-        {
-          if (c == '\n' || c == '\r')
-            {
-              is.putback (c);
-              skip_preceeding_newline (is);
-              break;
-            }
-
-          if (c == '%' || c == '#')
-            {
-              skip_until_newline (is, false);
-              break;
-            }
-
-          if (! is.eof ())
-            {
-              if (! have_data && c != ' ' && c != '\t')
-                have_data = true;
-
-              retval += c;
-            }
-        }
-    }
-  while (! (have_data || is.eof ()));
-
-  return retval;
-}
-
-static void
-get_lines_and_columns (std::istream& is, const std::string& filename, octave_idx_type& nr, octave_idx_type& nc)
-{
-  std::streampos pos = is.tellg ();
-
-  int file_line_number = 0;
-
-  nr = 0;
-  nc = 0;
-
-  while (is && ! error_state)
-    {
-      octave_quit ();
-
-      std::string buf = get_mat_data_input_line (is);
-
-      file_line_number++;
-
-      size_t beg = buf.find_first_not_of (", \t");
-
-      // If we see a CR as the last character in the buffer, we had a
-      // CRLF pair as the line separator.  Any other CR in the text
-      // will not be considered as whitespace.
-
-      if (beg != std::string::npos && buf[beg] == '\r' && beg == buf.length () - 1)
-        {
-          // We had a blank line ending with a CRLF.  Handle it the
-          // same as an empty line.
-          beg = std::string::npos;
-        }
-
-      octave_idx_type tmp_nc = 0;
-
-      while (beg != std::string::npos)
-        {
-          tmp_nc++;
-
-          size_t end = buf.find_first_of (", \t", beg);
-
-          if (end != std::string::npos)
-            {
-              beg = buf.find_first_not_of (", \t", end);
-
-              if (beg == std::string::npos || (buf[beg] == '\r' &&
-                                  beg == buf.length () - 1))
-                {
-                  // We had a line with trailing spaces and
-                  // ending with a CRLF, so this should look like EOL,
-                  // not a new colum.
-                  break;
-                }
-            }
-          else
-            break;
-        }
-
-      if (tmp_nc > 0)
-        {
-          if (nc == 0)
-            {
-              nc = tmp_nc;
-              nr++;
-            }
-          else if (nc == tmp_nc)
-            nr++;
-          else
-            error ("load: %s: inconsistent number of columns near line %d",
-                   filename.c_str (), file_line_number);
-        }
-    }
-
-  if (nr == 0 || nc == 0)
-    error ("load: file `%s' seems to be empty!", filename.c_str ());
-
-  is.clear ();
-  is.seekg (pos);
-}
-
-// Extract a matrix from a file of numbers only.
-//
-// Comments are not allowed.  The file should only have numeric values.
-//
-// Reads the file twice.  Once to find the number of rows and columns,
-// and once to extract the matrix.
-//
-// FILENAME is used for error messages.
-//
-// This format provides no way to tag the data as global.
-
-std::string
-read_mat_ascii_data (std::istream& is, const std::string& filename,
-                     octave_value& tc)
-{
-  std::string retval;
-
-  std::string varname;
-
-  size_t pos = filename.rfind ('/');
-
-  if (pos != std::string::npos)
-    varname = filename.substr (pos+1);
-  else
-    varname = filename;
-
-  pos = varname.rfind ('.');
-
-  if (pos != std::string::npos)
-    varname = varname.substr (0, pos);
-
-  size_t len = varname.length ();
-  for (size_t i = 0; i < len; i++)
-    {
-      char c = varname[i];
-      if (! (isalnum (c) || c == '_'))
-        varname[i] = '_';
-    }
-
-  if (is_keyword (varname) || ! isalpha (varname[0]))
-    varname.insert (0, "X");
-
-  if (valid_identifier (varname))
-    {
-      octave_idx_type nr = 0;
-      octave_idx_type nc = 0;
-
-      int total_count = 0;
-
-      get_lines_and_columns (is, filename, nr, nc);
-
-      octave_quit ();
-
-      if (! error_state && nr > 0 && nc > 0)
-        {
-          Matrix tmp (nr, nc);
-
-          if (nr < 1 || nc < 1)
-            is.clear (std::ios::badbit);
-          else
-            {
-              double d;
-              for (octave_idx_type i = 0; i < nr; i++)
-                {
-                  std::string buf = get_mat_data_input_line (is);
-
-                  std::istringstream tmp_stream (buf);
-
-                  for (octave_idx_type j = 0; j < nc; j++)
-                    {
-                      octave_quit ();
-
-                      d = octave_read_value<double> (tmp_stream);
-
-                      if (tmp_stream || tmp_stream.eof ())
-                        {
-                          tmp.elem (i, j) = d;
-                          total_count++;
-
-                          // Skip whitespace and commas.
-                          char c;
-                          while (1)
-                            {
-                              tmp_stream >> c;
-
-                              if (! tmp_stream)
-                                break;
-
-                              if (! (c == ' ' || c == '\t' || c == ','))
-                                {
-                                  tmp_stream.putback (c);
-                                  break;
-                                }
-                            }
-
-                          if (tmp_stream.eof ())
-                            break;
-                        }
-                      else
-                        {
-                          error ("load: failed to read matrix from file `%s'",
-                                 filename.c_str ());
-
-                          return retval;
-                        }
-
-                    }
-                }
-            }
-
-          if (is || is.eof ())
-            {
-              // FIXME -- not sure this is best, but it works.
-
-              if (is.eof ())
-                is.clear ();
-
-              octave_idx_type expected = nr * nc;
-
-              if (expected == total_count)
-                {
-                  tc = tmp;
-                  retval = varname;
-                }
-              else
-                error ("load: expected %d elements, found %d",
-                       expected, total_count);
-            }
-          else
-            error ("load: failed to read matrix from file `%s'",
-                   filename.c_str ());
-        }
-      else
-        error ("load: unable to extract matrix size from file `%s'",
-               filename.c_str ());
-    }
-  else
-    error ("load: unable to convert filename `%s' to valid identifier",
-           filename.c_str ());
-
-  return retval;
-}
-
-bool
-save_mat_ascii_data (std::ostream& os, const octave_value& val,
-                     int precision, bool tabs)
-{
-  bool success = true;
-
-  if (val.is_complex_type ())
-    warning ("save: omitting imaginary part for ASCII file");
-
-  Matrix m = val.matrix_value (true);
-
-  if (error_state)
-    {
-      success = false;
-
-      error_state = 0;
-    }
-  else
-    {
-      long old_precision = os.precision ();
-
-      os.precision (precision);
-
-      std::ios::fmtflags oflags
-        = os.flags (static_cast<std::ios::fmtflags> (std::ios::scientific));
-
-      if (tabs)
-        {
-          for (octave_idx_type i = 0; i < m.rows (); i++)
-            {
-              for (octave_idx_type j = 0; j < m.cols (); j++)
-                {
-                  // Omit leading tabs.
-                  if (j != 0) os << '\t';
-                  octave_write_double (os, m (i, j));
-                }
-              os << "\n";
-            }
-        }
-      else
-        os << m;
-
-      os.flags (oflags);
-
-      os.precision (old_precision);
-    }
-
-  return (os && success);
-}
--- a/src/ls-mat-ascii.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-/*
-
-Copyright (C) 2003-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#if !defined (octave_ls_mat_ascii_h)
-#define octave_ls_mat_ascii_h 1
-
-extern std::string
-read_mat_ascii_data (std::istream& is, const std::string& filename,
-                     octave_value& tc);
-
-extern bool
-save_mat_ascii_data (std::ostream& os, const octave_value& val_arg,
-                     int precision, bool tabs = false);
-
-#endif
--- a/src/ls-mat4.cc	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,609 +0,0 @@
-/*
-
-Copyright (C) 1996-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <cfloat>
-#include <cstring>
-#include <cctype>
-
-#include <fstream>
-#include <iomanip>
-#include <iostream>
-#include <string>
-#include <vector>
-
-#include "byte-swap.h"
-#include "data-conv.h"
-#include "file-ops.h"
-#include "glob-match.h"
-#include "lo-mappers.h"
-#include "mach-info.h"
-#include "oct-env.h"
-#include "oct-time.h"
-#include "quit.h"
-#include "str-vec.h"
-#include "oct-locbuf.h"
-
-#include "Cell.h"
-#include "defun.h"
-#include "error.h"
-#include "gripes.h"
-#include "load-save.h"
-#include "oct-obj.h"
-#include "oct-map.h"
-#include "ov-cell.h"
-#include "pager.h"
-#include "pt-exp.h"
-#include "sysdep.h"
-#include "unwind-prot.h"
-#include "utils.h"
-#include "variables.h"
-#include "version.h"
-#include "dMatrix.h"
-#include "dSparse.h"
-
-#include "ls-mat4.h"
-
-// Read LEN elements of data from IS in the format specified by
-// PRECISION, placing the result in DATA.  If SWAP is TRUE, swap
-// the bytes of each element before copying to DATA.  FLT_FMT
-// specifies the format of the data if we are reading floating point
-// numbers.
-
-static void
-read_mat_binary_data (std::istream& is, double *data, int precision,
-                      int len, bool swap,
-                      oct_mach_info::float_format flt_fmt)
-{
-  switch (precision)
-    {
-    case 0:
-      read_doubles (is, data, LS_DOUBLE, len, swap, flt_fmt);
-      break;
-
-    case 1:
-      read_doubles (is, data, LS_FLOAT, len, swap, flt_fmt);
-      break;
-
-    case 2:
-      read_doubles (is, data, LS_INT, len, swap, flt_fmt);
-      break;
-
-    case 3:
-      read_doubles (is, data, LS_SHORT, len, swap, flt_fmt);
-      break;
-
-    case 4:
-      read_doubles (is, data, LS_U_SHORT, len, swap, flt_fmt);
-      break;
-
-    case 5:
-      read_doubles (is, data, LS_U_CHAR, len, swap, flt_fmt);
-      break;
-
-    default:
-      break;
-    }
-}
-
-int
-read_mat_file_header (std::istream& is, bool& swap, int32_t& mopt,
-                      int32_t& nr, int32_t& nc,
-                      int32_t& imag, int32_t& len,
-                      int quiet)
-{
-  swap = false;
-
-  // We expect to fail here, at the beginning of a record, so not
-  // being able to read another mopt value should not result in an
-  // error.
-
-  is.read (reinterpret_cast<char *> (&mopt), 4);
-  if (! is)
-    return 1;
-
-  if (! is.read (reinterpret_cast<char *> (&nr), 4))
-    goto data_read_error;
-
-  if (! is.read (reinterpret_cast<char *> (&nc), 4))
-    goto data_read_error;
-
-  if (! is.read (reinterpret_cast<char *> (&imag), 4))
-    goto data_read_error;
-
-  if (! is.read (reinterpret_cast<char *> (&len), 4))
-    goto data_read_error;
-
-// If mopt is nonzero and the byte order is swapped, mopt will be
-// bigger than we expect, so we swap bytes.
-//
-// If mopt is zero, it means the file was written on a little endian
-// machine, and we only need to swap if we are running on a big endian
-// machine.
-//
-// Gag me.
-
-  if (oct_mach_info::words_big_endian () && mopt == 0)
-    swap = true;
-
-  // mopt is signed, therefore byte swap may result in negative value.
-
-  if (mopt > 9999 || mopt < 0)
-    swap = true;
-
-  if (swap)
-    {
-      swap_bytes<4> (&mopt);
-      swap_bytes<4> (&nr);
-      swap_bytes<4> (&nc);
-      swap_bytes<4> (&imag);
-      swap_bytes<4> (&len);
-    }
-
-  if (mopt > 9999 || mopt < 0 || imag > 1 || imag < 0)
-    {
-      if (! quiet)
-        error ("load: can't read binary file");
-      return -1;
-    }
-
-  return 0;
-
- data_read_error:
-  return -1;
-}
-
-// We don't just use a cast here, because we need to be able to detect
-// possible errors.
-
-oct_mach_info::float_format
-mopt_digit_to_float_format (int mach)
-{
-  oct_mach_info::float_format flt_fmt = oct_mach_info::flt_fmt_unknown;
-
-  switch (mach)
-    {
-    case 0:
-      flt_fmt = oct_mach_info::flt_fmt_ieee_little_endian;
-      break;
-
-    case 1:
-      flt_fmt = oct_mach_info::flt_fmt_ieee_big_endian;
-      break;
-
-    case 2:
-      flt_fmt = oct_mach_info::flt_fmt_vax_d;
-      break;
-
-    case 3:
-      flt_fmt = oct_mach_info::flt_fmt_vax_g;
-      break;
-
-    case 4:
-      flt_fmt = oct_mach_info::flt_fmt_cray;
-      break;
-
-    default:
-      flt_fmt = oct_mach_info::flt_fmt_unknown;
-      break;
-    }
-
-  return flt_fmt;
-}
-
-int
-float_format_to_mopt_digit (oct_mach_info::float_format flt_fmt)
-{
-  int retval = -1;
-
-  switch (flt_fmt)
-    {
-    case oct_mach_info::flt_fmt_ieee_little_endian:
-      retval = 0;
-      break;
-
-    case oct_mach_info::flt_fmt_ieee_big_endian:
-      retval = 1;
-      break;
-
-    case oct_mach_info::flt_fmt_vax_d:
-      retval = 2;
-      break;
-
-    case oct_mach_info::flt_fmt_vax_g:
-      retval = 3;
-      break;
-
-    case oct_mach_info::flt_fmt_cray:
-      retval = 4;
-      break;
-
-    default:
-      break;
-    }
-
-  return retval;
-}
-
-// Extract one value (scalar, matrix, string, etc.) from stream IS and
-// place it in TC, returning the name of the variable.
-//
-// The data is expected to be in Matlab version 4 .mat format, though
-// not all the features of that format are supported.
-//
-// FILENAME is used for error messages.
-//
-// This format provides no way to tag the data as global.
-
-std::string
-read_mat_binary_data (std::istream& is, const std::string& filename,
-                      octave_value& tc)
-{
-  std::string retval;
-
-  // These are initialized here instead of closer to where they are
-  // first used to avoid errors from gcc about goto crossing
-  // initialization of variable.
-
-  Matrix re;
-  oct_mach_info::float_format flt_fmt = oct_mach_info::flt_fmt_unknown;
-  bool swap = false;
-  int type = 0;
-  int prec = 0;
-  int order = 0;
-  int mach = 0;
-  int dlen = 0;
-
-  int32_t mopt, nr, nc, imag, len;
-
-  int err = read_mat_file_header (is, swap, mopt, nr, nc, imag, len);
-  if (err)
-    {
-      if (err < 0)
-        goto data_read_error;
-      else
-        return retval;
-    }
-
-  type = mopt % 10;  // Full, sparse, etc.
-  mopt /= 10;        // Eliminate first digit.
-  prec = mopt % 10;  // double, float, int, etc.
-  mopt /= 10;        // Eliminate second digit.
-  order = mopt % 10; // Row or column major ordering.
-  mopt /= 10;        // Eliminate third digit.
-  mach = mopt % 10;  // IEEE, VAX, etc.
-
-  flt_fmt = mopt_digit_to_float_format (mach);
-
-  if (flt_fmt == oct_mach_info::flt_fmt_unknown)
-    {
-      error ("load: unrecognized binary format!");
-      return retval;
-    }
-
-  if (imag && type == 1)
-    {
-      error ("load: encountered complex matrix with string flag set!");
-      return retval;
-    }
-
-  // LEN includes the terminating character, and the file is also
-  // supposed to include it, but apparently not all files do.  Either
-  // way, I think this should work.
-
-  {
-    OCTAVE_LOCAL_BUFFER (char, name, len+1);
-    name[len] = '\0';
-    if (! is.read (name, len))
-      goto data_read_error;
-    retval = name;
-
-    dlen = nr * nc;
-    if (dlen < 0)
-      goto data_read_error;
-
-    if (order)
-      {
-        octave_idx_type tmp = nr;
-        nr = nc;
-        nc = tmp;
-      }
-
-    if (type == 2)
-      {
-        if (nc == 4)
-          {
-            octave_idx_type nr_new, nc_new;
-            Array<Complex> data (dim_vector (1, nr - 1));
-            Array<octave_idx_type> c (dim_vector (1, nr - 1));
-            Array<octave_idx_type> r (dim_vector (1, nr - 1));
-            OCTAVE_LOCAL_BUFFER (double, dtmp, nr);
-            OCTAVE_LOCAL_BUFFER (double, ctmp, nr);
-
-            read_mat_binary_data (is, dtmp, prec, nr, swap, flt_fmt);
-            for (octave_idx_type i = 0; i < nr - 1; i++)
-              r.xelem (i) = dtmp[i] - 1;
-            nr_new = dtmp[nr - 1];
-            read_mat_binary_data (is, dtmp, prec, nr, swap, flt_fmt);
-            for (octave_idx_type i = 0; i < nr - 1; i++)
-              c.xelem (i) = dtmp[i] - 1;
-            nc_new = dtmp[nr - 1];
-            read_mat_binary_data (is, dtmp, prec, nr - 1, swap, flt_fmt);
-            read_mat_binary_data (is, ctmp, prec, 1, swap, flt_fmt);
-            read_mat_binary_data (is, ctmp, prec, nr - 1, swap, flt_fmt);
-
-            for (octave_idx_type i = 0; i < nr - 1; i++)
-              data.xelem (i) = Complex (dtmp[i], ctmp[i]);
-            read_mat_binary_data (is, ctmp, prec, 1, swap, flt_fmt);
-
-            SparseComplexMatrix smc = SparseComplexMatrix (data, r, c,
-                                                           nr_new, nc_new);
-
-            tc = order ? smc.transpose () : smc;
-          }
-        else
-          {
-            octave_idx_type nr_new, nc_new;
-            Array<double> data (dim_vector (1, nr - 1));
-            Array<octave_idx_type> c (dim_vector (1, nr - 1));
-            Array<octave_idx_type> r (dim_vector (1, nr - 1));
-            OCTAVE_LOCAL_BUFFER (double, dtmp, nr);
-
-            read_mat_binary_data (is, dtmp, prec, nr, swap, flt_fmt);
-            for (octave_idx_type i = 0; i < nr - 1; i++)
-              r.xelem (i) = dtmp[i] - 1;
-            nr_new = dtmp[nr - 1];
-            read_mat_binary_data (is, dtmp, prec, nr, swap, flt_fmt);
-            for (octave_idx_type i = 0; i < nr - 1; i++)
-              c.xelem (i) = dtmp[i] - 1;
-            nc_new = dtmp[nr - 1];
-            read_mat_binary_data (is, data.fortran_vec (), prec, nr - 1, swap, flt_fmt);
-            read_mat_binary_data (is, dtmp, prec, 1, swap, flt_fmt);
-
-            SparseMatrix sm = SparseMatrix (data, r, c, nr_new, nc_new);
-
-            tc = order ? sm.transpose () : sm;
-          }
-      }
-    else
-      {
-        re.resize (nr, nc);
-
-        read_mat_binary_data (is, re.fortran_vec (), prec, dlen, swap, flt_fmt);
-
-        if (! is || error_state)
-          {
-            error ("load: reading matrix data for `%s'", name);
-            goto data_read_error;
-          }
-
-        if (imag)
-          {
-            Matrix im (nr, nc);
-
-            read_mat_binary_data (is, im.fortran_vec (), prec, dlen, swap,
-                                  flt_fmt);
-
-            if (! is || error_state)
-              {
-                error ("load: reading imaginary matrix data for `%s'", name);
-                goto data_read_error;
-              }
-
-            ComplexMatrix ctmp (nr, nc);
-
-            for (octave_idx_type j = 0; j < nc; j++)
-              for (octave_idx_type i = 0; i < nr; i++)
-                ctmp (i, j) = Complex (re (i, j), im (i, j));
-
-            tc = order ? ctmp.transpose () : ctmp;
-          }
-        else
-          tc = order ? re.transpose () : re;
-
-        if (type == 1)
-          tc = tc.convert_to_str (false, true, '\'');
-      }
-
-      return retval;
-    }
-
- data_read_error:
-  error ("load: trouble reading binary file `%s'", filename.c_str ());
-  return retval;
-}
-
-// Save the data from TC along with the corresponding NAME on stream OS
-// in the MatLab version 4 binary format.
-
-bool
-save_mat_binary_data (std::ostream& os, const octave_value& tc,
-                      const std::string& name)
-{
-  int32_t mopt = 0;
-
-  mopt += tc.is_sparse_type () ? 2 : tc.is_string () ? 1 : 0;
-
-  oct_mach_info::float_format flt_fmt =
-    oct_mach_info::native_float_format ();;
-
-  mopt += 1000 * float_format_to_mopt_digit (flt_fmt);
-
-  os.write (reinterpret_cast<char *> (&mopt), 4);
-
-  octave_idx_type len;
-  int32_t nr = tc.rows ();
-
-  int32_t nc = tc.columns ();
-
-  if (tc.is_sparse_type ())
-    {
-      len = tc.nnz ();
-      uint32_t nnz = len + 1;
-      os.write (reinterpret_cast<char *> (&nnz), 4);
-
-      uint32_t iscmplx = tc.is_complex_type () ? 4 : 3;
-      os.write (reinterpret_cast<char *> (&iscmplx), 4);
-
-      uint32_t tmp = 0;
-      os.write (reinterpret_cast<char *> (&tmp), 4);
-    }
-  else
-    {
-      os.write (reinterpret_cast<char *> (&nr), 4);
-      os.write (reinterpret_cast<char *> (&nc), 4);
-
-      int32_t imag = tc.is_complex_type () ? 1 : 0;
-      os.write (reinterpret_cast<char *> (&imag), 4);
-
-      len = nr * nc;
-    }
-
-
-  // LEN includes the terminating character, and the file is also
-  // supposed to include it.
-
-  int32_t name_len = name.length () + 1;
-
-  os.write (reinterpret_cast<char *> (&name_len), 4);
-  os << name << '\0';
-
-  if (tc.is_string ())
-    {
-      unwind_protect frame;
-
-      charMatrix chm = tc.char_matrix_value ();
-
-      octave_idx_type nrow = chm.rows ();
-      octave_idx_type ncol = chm.cols ();
-
-      OCTAVE_LOCAL_BUFFER (double, buf, ncol*nrow);
-
-      for (octave_idx_type i = 0; i < nrow; i++)
-        {
-          std::string tstr = chm.row_as_string (i);
-          const char *s = tstr.data ();
-
-          for (octave_idx_type j = 0; j < ncol; j++)
-            buf[j*nrow+i] = static_cast<double> (*s++ & 0x00FF);
-        }
-      os.write (reinterpret_cast<char *> (buf), nrow*ncol*sizeof (double));
-    }
-  else if (tc.is_range ())
-    {
-      Range r = tc.range_value ();
-      double base = r.base ();
-      double inc = r.inc ();
-      octave_idx_type nel = r.nelem ();
-      for (octave_idx_type i = 0; i < nel; i++)
-        {
-          double x = base + i * inc;
-          os.write (reinterpret_cast<char *> (&x), 8);
-        }
-    }
-  else if (tc.is_real_scalar ())
-    {
-      double tmp = tc.double_value ();
-      os.write (reinterpret_cast<char *> (&tmp), 8);
-    }
-  else if (tc.is_sparse_type ())
-    {
-      double ds;
-      OCTAVE_LOCAL_BUFFER (double, dtmp, len);
-      if (tc.is_complex_matrix ())
-        {
-          SparseComplexMatrix m = tc.sparse_complex_matrix_value ();
-
-          for (octave_idx_type i = 0; i < len; i++)
-            dtmp[i] = m.ridx (i) + 1;
-          os.write (reinterpret_cast<const char *> (dtmp), 8 * len);
-          ds = nr;
-          os.write (reinterpret_cast<const char *> (&ds), 8);
-
-          octave_idx_type ii = 0;
-          for (octave_idx_type j = 0; j < nc; j++)
-            for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++)
-              dtmp[ii++] = j + 1;
-          os.write (reinterpret_cast<const char *> (dtmp), 8 * len);
-          ds = nc;
-          os.write (reinterpret_cast<const char *> (&ds), 8);
-
-          for (octave_idx_type i = 0; i < len; i++)
-            dtmp[i] = std::real (m.data (i));
-          os.write (reinterpret_cast<const char *> (dtmp), 8 * len);
-          ds = 0.;
-          os.write (reinterpret_cast<const char *> (&ds), 8);
-
-          for (octave_idx_type i = 0; i < len; i++)
-            dtmp[i] = std::imag (m.data (i));
-          os.write (reinterpret_cast<const char *> (dtmp), 8 * len);
-          os.write (reinterpret_cast<const char *> (&ds), 8);
-        }
-      else
-        {
-          SparseMatrix m = tc.sparse_matrix_value ();
-
-          for (octave_idx_type i = 0; i < len; i++)
-            dtmp[i] = m.ridx (i) + 1;
-          os.write (reinterpret_cast<const char *> (dtmp), 8 * len);
-          ds = nr;
-          os.write (reinterpret_cast<const char *> (&ds), 8);
-
-          octave_idx_type ii = 0;
-          for (octave_idx_type j = 0; j < nc; j++)
-            for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++)
-              dtmp[ii++] = j + 1;
-          os.write (reinterpret_cast<const char *> (dtmp), 8 * len);
-          ds = nc;
-          os.write (reinterpret_cast<const char *> (&ds), 8);
-
-          os.write (reinterpret_cast<const char *> (m.data ()), 8 * len);
-          ds = 0.;
-          os.write (reinterpret_cast<const char *> (&ds), 8);
-        }
-    }
-  else if (tc.is_real_matrix ())
-    {
-      Matrix m = tc.matrix_value ();
-      os.write (reinterpret_cast<const char *> (m.data ()), 8 * len);
-    }
-  else if (tc.is_complex_scalar ())
-    {
-      Complex tmp = tc.complex_value ();
-      os.write (reinterpret_cast<char *> (&tmp), 16);
-    }
-  else if (tc.is_complex_matrix ())
-    {
-      ComplexMatrix m_cmplx = tc.complex_matrix_value ();
-      Matrix m = ::real (m_cmplx);
-      os.write (reinterpret_cast<const char *> (m.data ()), 8 * len);
-      m = ::imag (m_cmplx);
-      os.write (reinterpret_cast<const char *> (m.data ()), 8 * len);
-    }
-  else
-    gripe_wrong_type_arg ("save", tc, false);
-
-  return os;
-}
--- a/src/ls-mat4.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
-
-Copyright (C) 2003-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#if !defined (octave_ls_mat4_h)
-#define octave_ls_mat4_h 1
-
-extern oct_mach_info::float_format
-mopt_digit_to_float_format (int mach);
-
-extern int
-float_format_to_mopt_digit (oct_mach_info::float_format flt_fmt);
-
-extern int
-read_mat_file_header (std::istream& is, bool& swap, int32_t& mopt,
-                      int32_t& nr, int32_t& nc, int32_t& imag,
-                      int32_t& len, int quiet = 0);
-
-extern std::string
-read_mat_binary_data (std::istream& is, const std::string& filename,
-                      octave_value& tc);
-
-extern bool
-save_mat_binary_data (std::ostream& os, const octave_value& tc,
-                      const std::string& name) ;
-
-#endif
--- a/src/ls-mat5.cc	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2719 +0,0 @@
-/*
-
-Copyright (C) 1996-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-// Author: James R. Van Zandt <jrv@vanzandt.mv.com>
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <cfloat>
-#include <cstring>
-#include <cctype>
-
-#include <fstream>
-#include <iomanip>
-#include <iostream>
-#include <sstream>
-#include <string>
-#include <vector>
-
-#include "byte-swap.h"
-#include "data-conv.h"
-#include "file-ops.h"
-#include "glob-match.h"
-#include "lo-mappers.h"
-#include "mach-info.h"
-#include "oct-env.h"
-#include "oct-time.h"
-#include "quit.h"
-#include "str-vec.h"
-#include "file-stat.h"
-#include "oct-locbuf.h"
-
-#include "Cell.h"
-#include "defun.h"
-#include "error.h"
-#include "gripes.h"
-#include "load-save.h"
-#include "load-path.h"
-#include "oct-obj.h"
-#include "oct-map.h"
-#include "ov-cell.h"
-#include "ov-class.h"
-#include "ov-fcn-inline.h"
-#include "pager.h"
-#include "pt-exp.h"
-#include "sysdep.h"
-#include "toplev.h"
-#include "unwind-prot.h"
-#include "utils.h"
-#include "variables.h"
-#include "version.h"
-#include "dMatrix.h"
-
-#include "ls-utils.h"
-#include "ls-mat5.h"
-
-#include "parse.h"
-#include "defaults.h"
-
-#ifdef HAVE_ZLIB
-#include <zlib.h>
-#endif
-
-#define PAD(l) (((l) > 0 && (l) <= 4) ? 4 : (((l)+7)/8)*8)
-
-
-// The subsystem data block
-static octave_value subsys_ov;
-
-// FIXME -- the following enum values should be the same as the
-// mxClassID values in mexproto.h, but it seems they have also changed
-// over time.  What is the correct way to handle this and maintain
-// backward compatibility with old MAT files?  For now, use
-// "MAT_FILE_" instead of "mx" as the prefix for these names to avoid
-// conflict with the mxClassID enum in mexproto.h.
-
-enum arrayclasstype
-  {
-    MAT_FILE_CELL_CLASS=1,              // cell array
-    MAT_FILE_STRUCT_CLASS,              // structure
-    MAT_FILE_OBJECT_CLASS,              // object
-    MAT_FILE_CHAR_CLASS,                // character array
-    MAT_FILE_SPARSE_CLASS,              // sparse array
-    MAT_FILE_DOUBLE_CLASS,              // double precision array
-    MAT_FILE_SINGLE_CLASS,              // single precision floating point
-    MAT_FILE_INT8_CLASS,                // 8 bit signed integer
-    MAT_FILE_UINT8_CLASS,               // 8 bit unsigned integer
-    MAT_FILE_INT16_CLASS,               // 16 bit signed integer
-    MAT_FILE_UINT16_CLASS,              // 16 bit unsigned integer
-    MAT_FILE_INT32_CLASS,               // 32 bit signed integer
-    MAT_FILE_UINT32_CLASS,              // 32 bit unsigned integer
-    MAT_FILE_INT64_CLASS,               // 64 bit signed integer
-    MAT_FILE_UINT64_CLASS,              // 64 bit unsigned integer
-    MAT_FILE_FUNCTION_CLASS,            // Function handle
-    MAT_FILE_WORKSPACE_CLASS            // Workspace (undocumented)
-  };
-
-// Read COUNT elements of data from IS in the format specified by TYPE,
-// placing the result in DATA.  If SWAP is TRUE, swap the bytes of
-// each element before copying to DATA.  FLT_FMT specifies the format
-// of the data if we are reading floating point numbers.
-
-static void
-read_mat5_binary_data (std::istream& is, double *data,
-                       octave_idx_type  count, bool swap, mat5_data_type type,
-                       oct_mach_info::float_format flt_fmt)
-{
-
-  switch (type)
-    {
-    case miINT8:
-      read_doubles (is, data, LS_CHAR, count, swap, flt_fmt);
-      break;
-
-    case miUTF8:
-    case miUINT8:
-      read_doubles (is, data, LS_U_CHAR, count, swap, flt_fmt);
-      break;
-
-    case miINT16:
-      read_doubles (is, data, LS_SHORT, count, swap, flt_fmt);
-      break;
-
-    case miUTF16:
-    case miUINT16:
-      read_doubles (is, data, LS_U_SHORT, count, swap, flt_fmt);
-      break;
-
-    case miINT32:
-      read_doubles (is, data, LS_INT, count, swap, flt_fmt);
-      break;
-
-    case miUTF32:
-    case miUINT32:
-      read_doubles (is, data, LS_U_INT, count, swap, flt_fmt);
-      break;
-
-    case miSINGLE:
-      read_doubles (is, data, LS_FLOAT, count, swap, flt_fmt);
-      break;
-
-    case miRESERVE1:
-      break;
-
-    case miDOUBLE:
-      read_doubles (is, data, LS_DOUBLE, count, swap, flt_fmt);
-      break;
-
-    case miRESERVE2:
-    case miRESERVE3:
-      break;
-
-    // FIXME -- how are the 64-bit cases supposed to work here?
-    case miINT64:
-      read_doubles (is, data, LS_LONG, count, swap, flt_fmt);
-      break;
-
-    case miUINT64:
-      read_doubles (is, data, LS_U_LONG, count, swap, flt_fmt);
-      break;
-
-    case miMATRIX:
-    default:
-      break;
-    }
-}
-
-static void
-read_mat5_binary_data (std::istream& is, float *data,
-                       octave_idx_type  count, bool swap, mat5_data_type type,
-                       oct_mach_info::float_format flt_fmt)
-{
-
-  switch (type)
-    {
-    case miINT8:
-      read_floats (is, data, LS_CHAR, count, swap, flt_fmt);
-      break;
-
-    case miUTF8:
-    case miUINT8:
-      read_floats (is, data, LS_U_CHAR, count, swap, flt_fmt);
-      break;
-
-    case miINT16:
-      read_floats (is, data, LS_SHORT, count, swap, flt_fmt);
-      break;
-
-    case miUTF16:
-    case miUINT16:
-      read_floats (is, data, LS_U_SHORT, count, swap, flt_fmt);
-      break;
-
-    case miINT32:
-      read_floats (is, data, LS_INT, count, swap, flt_fmt);
-      break;
-
-    case miUTF32:
-    case miUINT32:
-      read_floats (is, data, LS_U_INT, count, swap, flt_fmt);
-      break;
-
-    case miSINGLE:
-      read_floats (is, data, LS_FLOAT, count, swap, flt_fmt);
-      break;
-
-    case miRESERVE1:
-      break;
-
-    case miDOUBLE:
-      read_floats (is, data, LS_DOUBLE, count, swap, flt_fmt);
-      break;
-
-    case miRESERVE2:
-    case miRESERVE3:
-      break;
-
-    // FIXME -- how are the 64-bit cases supposed to work here?
-    case miINT64:
-      read_floats (is, data, LS_LONG, count, swap, flt_fmt);
-      break;
-
-    case miUINT64:
-      read_floats (is, data, LS_U_LONG, count, swap, flt_fmt);
-      break;
-
-    case miMATRIX:
-    default:
-      break;
-    }
-}
-
-template <class T>
-void
-read_mat5_integer_data (std::istream& is, T *m, octave_idx_type count,
-                        bool swap, mat5_data_type type)
-{
-
-#define READ_INTEGER_DATA(TYPE, swap, data, size, len, stream)  \
-  do \
-    { \
-      if (len > 0) \
-        { \
-          OCTAVE_LOCAL_BUFFER (TYPE, ptr, len); \
-          stream.read (reinterpret_cast<char *> (ptr), size * len); \
-          if (swap) \
-            swap_bytes< size > (ptr, len); \
-          for (octave_idx_type i = 0; i < len; i++) \
-            data[i] = ptr[i]; \
-        } \
-    } \
-  while (0)
-
-  switch (type)
-    {
-    case miINT8:
-      READ_INTEGER_DATA (int8_t, swap, m, 1, count, is);
-      break;
-
-    case miUINT8:
-      READ_INTEGER_DATA (uint8_t, swap, m, 1, count, is);
-      break;
-
-    case miINT16:
-      READ_INTEGER_DATA (int16_t, swap, m, 2, count, is);
-      break;
-
-    case miUINT16:
-      READ_INTEGER_DATA (uint16_t, swap, m, 2, count, is);
-      break;
-
-    case miINT32:
-      READ_INTEGER_DATA (int32_t, swap, m, 4, count, is);
-      break;
-
-    case miUINT32:
-      READ_INTEGER_DATA (uint32_t, swap, m, 4, count, is);
-      break;
-
-    case miSINGLE:
-    case miRESERVE1:
-    case miDOUBLE:
-    case miRESERVE2:
-    case miRESERVE3:
-      break;
-
-    case miINT64:
-      READ_INTEGER_DATA (int64_t, swap, m, 8, count, is);
-      break;
-
-    case miUINT64:
-      READ_INTEGER_DATA (uint64_t, swap, m, 8, count, is);
-      break;
-
-    case miMATRIX:
-    default:
-      break;
-    }
-
-#undef READ_INTEGER_DATA
-
-}
-
-template void
-read_mat5_integer_data (std::istream& is, octave_int8 *m,
-                        octave_idx_type count, bool swap,
-                        mat5_data_type type);
-
-template void
-read_mat5_integer_data (std::istream& is, octave_int16 *m,
-                        octave_idx_type count, bool swap,
-                        mat5_data_type type);
-
-template void
-read_mat5_integer_data (std::istream& is, octave_int32 *m,
-                        octave_idx_type count, bool swap,
-                        mat5_data_type type);
-
-template void
-read_mat5_integer_data (std::istream& is, octave_int64 *m,
-                        octave_idx_type count, bool swap,
-                        mat5_data_type type);
-
-template void
-read_mat5_integer_data (std::istream& is, octave_uint8 *m,
-                        octave_idx_type count, bool swap,
-                        mat5_data_type type);
-
-template void
-read_mat5_integer_data (std::istream& is, octave_uint16 *m,
-                        octave_idx_type count, bool swap,
-                        mat5_data_type type);
-
-template void
-read_mat5_integer_data (std::istream& is, octave_uint32 *m,
-                        octave_idx_type count, bool swap,
-                        mat5_data_type type);
-
-template void
-read_mat5_integer_data (std::istream& is, octave_uint64 *m,
-                        octave_idx_type count, bool swap,
-                        mat5_data_type type);
-
-template void
-read_mat5_integer_data (std::istream& is, int *m,
-                        octave_idx_type count, bool swap,
-                        mat5_data_type type);
-
-#define OCTAVE_MAT5_INTEGER_READ(TYP) \
-  { \
-        TYP re (dims); \
-  \
-        std::streampos tmp_pos; \
-  \
-        if (read_mat5_tag (is, swap, type, len)) \
-          { \
-            error ("load: reading matrix data for `%s'", retval.c_str ()); \
-            goto data_read_error; \
-          } \
-  \
-        octave_idx_type n = re.numel (); \
-        tmp_pos = is.tellg (); \
-        read_mat5_integer_data (is, re.fortran_vec (), n, swap, \
-                                static_cast<enum mat5_data_type> (type)); \
-  \
-        if (! is || error_state) \
-          { \
-            error ("load: reading matrix data for `%s'", retval.c_str ()); \
-            goto data_read_error; \
-          } \
-  \
-        is.seekg (tmp_pos + static_cast<std::streamoff> (PAD (len))); \
-  \
-        if (imag) \
-          { \
-            /* We don't handle imag integer types, convert to an array */ \
-            NDArray im (dims); \
-  \
-            if (read_mat5_tag (is, swap, type, len)) \
-              { \
-                error ("load: reading matrix data for `%s'", \
-                       retval.c_str ()); \
-                goto data_read_error; \
-              } \
-  \
-            n = im.numel (); \
-            read_mat5_binary_data (is, im.fortran_vec (), n, swap, \
-                                   static_cast<enum mat5_data_type> (type), flt_fmt); \
-  \
-            if (! is || error_state) \
-              { \
-                error ("load: reading imaginary matrix data for `%s'", \
-                       retval.c_str ()); \
-                goto data_read_error; \
-              } \
-  \
-            ComplexNDArray ctmp (dims); \
-  \
-            for (octave_idx_type i = 0; i < n; i++) \
-              ctmp(i) = Complex (re(i).double_value (), im(i)); \
-  \
-            tc = ctmp;  \
-          } \
-        else \
-          tc = re; \
-  }
-
-// Read one element tag from stream IS,
-// place the type code in TYPE and the byte count in BYTES
-// return nonzero on error
-static int
-read_mat5_tag (std::istream& is, bool swap, int32_t& type, int32_t& bytes)
-{
-  unsigned int upper;
-  int32_t temp;
-
-  if (! is.read (reinterpret_cast<char *> (&temp), 4 ))
-    goto data_read_error;
-
-  if (swap)
-    swap_bytes<4> (&temp);
-
-  upper = (temp >> 16) & 0xffff;
-  type = temp & 0xffff;
-
-  if (upper)
-    {
-      // "compressed" format
-      bytes = upper;
-    }
-  else
-    {
-      if (! is.read (reinterpret_cast<char *> (&temp), 4 ))
-        goto data_read_error;
-      if (swap)
-        swap_bytes<4> (&temp);
-      bytes = temp;
-    }
-
-  return 0;
-
- data_read_error:
-  return 1;
-}
-
-static void
-read_int (std::istream& is, bool swap, int32_t& val)
-{
-  is.read (reinterpret_cast<char *> (&val), 4);
-
-  if (swap)
-    swap_bytes<4> (&val);
-}
-
-// Extract one data element (scalar, matrix, string, etc.) from stream
-// IS and place it in TC, returning the name of the variable.
-//
-// The data is expected to be in Matlab's "Version 5" .mat format,
-// though not all the features of that format are supported.
-//
-// FILENAME is used for error messages.
-
-std::string
-read_mat5_binary_element (std::istream& is, const std::string& filename,
-                          bool swap, bool& global, octave_value& tc)
-{
-  std::string retval;
-
-  global = false;
-
-  // NOTE: these are initialized here instead of closer to where they
-  // are first used to avoid errors from gcc about goto crossing
-  // initialization of variable.
-
-  bool imag;
-  bool isclass = false;
-  bool logicalvar;
-  dim_vector dims;
-  enum arrayclasstype arrayclass;
-  int16_t number = *(reinterpret_cast<const int16_t *>("\x00\x01"));
-  octave_idx_type nzmax;
-  std::string classname;
-
-  // MAT files always use IEEE floating point
-  oct_mach_info::float_format flt_fmt = oct_mach_info::flt_fmt_unknown;
-  if ((number == 1) ^ swap)
-    flt_fmt = oct_mach_info::flt_fmt_ieee_big_endian;
-  else
-    flt_fmt = oct_mach_info::flt_fmt_ieee_little_endian;
-
-  // element type and length
-  int32_t type = 0;
-  int32_t element_length;
-  if (read_mat5_tag (is, swap, type, element_length))
-    return retval;                      // EOF
-
-#ifdef HAVE_ZLIB
-  if (type == miCOMPRESSED)
-    {
-      // If C++ allowed us direct access to the file descriptor of an
-      // ifstream in a uniform way, the code below could be vastly
-      // simplified, and additional copies of the data in memory
-      // wouldn't be needed.
-
-      OCTAVE_LOCAL_BUFFER (char, inbuf, element_length);
-      is.read (inbuf, element_length);
-
-      // We uncompress the first 8 bytes of the header to get the buffer length
-      // This will fail with an error Z_MEM_ERROR
-      uLongf destLen = 8;
-      OCTAVE_LOCAL_BUFFER (unsigned int, tmp, 2);
-      if (uncompress (reinterpret_cast<Bytef *> (tmp), &destLen,
-                      reinterpret_cast<Bytef *> (inbuf), element_length)
-          !=  Z_MEM_ERROR)
-        {
-          // Why should I have to initialize outbuf as I'll just overwrite!!
-          if (swap)
-            swap_bytes<4> (tmp, 2);
-
-          destLen = tmp[1] + 8;
-          std::string outbuf (destLen, ' ');
-
-          // FIXME -- find a way to avoid casting away const here!
-
-          int err = uncompress (reinterpret_cast<Bytef *> (const_cast<char *> (outbuf.c_str ())),
-                                &destLen, reinterpret_cast<Bytef *> (inbuf),
-                                element_length);
-
-          if (err != Z_OK)
-            {
-              std::string msg;
-              switch (err)
-                {
-                case Z_STREAM_END:
-                  msg = "stream end";
-                  break;
-
-                case Z_NEED_DICT:
-                  msg = "need dict";
-                  break;
-
-                case Z_ERRNO:
-                  msg = "errno case";
-                  break;
-
-                case Z_STREAM_ERROR:
-                  msg = "stream error";
-                  break;
-
-                case Z_DATA_ERROR:
-                  msg = "data error";
-                  break;
-
-                case Z_MEM_ERROR:
-                  msg = "mem error";
-                  break;
-
-                case Z_BUF_ERROR:
-                  msg = "buf error";
-                  break;
-
-                case Z_VERSION_ERROR:
-                  msg = "version error";
-                  break;
-                }
-
-              error ("load: error uncompressing data element (%s from zlib)",
-                     msg.c_str ());
-            }
-          else
-            {
-              std::istringstream gz_is (outbuf);
-              retval = read_mat5_binary_element (gz_is, filename,
-                                                 swap, global, tc);
-            }
-        }
-      else
-        error ("load: error probing size of compressed data element");
-
-      return retval;
-    }
-#endif
-
-  std::streampos pos;
-
-  if (type != miMATRIX)
-    {
-      pos = is.tellg ();
-      error ("load: invalid element type = %d", type);
-      goto early_read_error;
-    }
-
-  if (element_length == 0)
-    {
-      tc = Matrix ();
-      return retval;
-    }
-
-  pos = is.tellg ();
-
-  // array flags subelement
-  int32_t len;
-  if (read_mat5_tag (is, swap, type, len) || type != miUINT32 || len != 8)
-    {
-      error ("load: invalid array flags subelement");
-      goto early_read_error;
-    }
-
-  int32_t flags;
-  read_int (is, swap, flags);
-
-  imag = (flags & 0x0800) != 0; // has an imaginary part?
-
-  global = (flags & 0x0400) != 0; // global variable?
-
-  logicalvar = (flags & 0x0200) != 0; // boolean ?
-
-  arrayclass = static_cast<arrayclasstype> (flags & 0xff);
-
-  int32_t tmp_nzmax;
-  read_int (is, swap, tmp_nzmax);   // max number of non-zero in sparse
-  nzmax = tmp_nzmax;
-
-  // dimensions array subelement
-  if (arrayclass != MAT_FILE_WORKSPACE_CLASS)
-    {
-      int32_t dim_len;
-
-      if (read_mat5_tag (is, swap, type, dim_len) || type != miINT32)
-        {
-          error ("load: invalid dimensions array subelement");
-          goto early_read_error;
-        }
-
-      int ndims = dim_len / 4;
-      dims.resize (ndims);
-      for (int i = 0; i < ndims; i++)
-        {
-          int32_t n;
-          read_int (is, swap, n);
-          dims(i) = n;
-        }
-
-      std::streampos tmp_pos = is.tellg ();
-      is.seekg (tmp_pos + static_cast<std::streamoff> (PAD (dim_len) - dim_len));
-    }
-  else
-    {
-      // Why did mathworks decide to not have dims for a workspace!!!
-      dims.resize (2);
-      dims(0) = 1;
-      dims(1) = 1;
-    }
-
-  if (read_mat5_tag (is, swap, type, len) || type != miINT8)
-    {
-      error ("load: invalid array name subelement");
-      goto early_read_error;
-    }
-
-  {
-    OCTAVE_LOCAL_BUFFER (char, name, len+1);
-
-    // Structure field subelements have zero-length array name subelements.
-
-    std::streampos tmp_pos = is.tellg ();
-
-    if (len)
-      {
-        if (! is.read (name, len ))
-          goto data_read_error;
-
-        is.seekg (tmp_pos + static_cast<std::streamoff> (PAD (len)));
-      }
-
-    name[len] = '\0';
-    retval = name;
-  }
-
-  switch (arrayclass)
-    {
-    case MAT_FILE_CELL_CLASS:
-      {
-        Cell cell_array (dims);
-
-        octave_idx_type n = cell_array.numel ();
-
-        for (octave_idx_type i = 0; i < n; i++)
-          {
-            octave_value tc2;
-
-            std::string nm
-              = read_mat5_binary_element (is, filename, swap, global, tc2);
-
-            if (! is || error_state)
-              {
-                error ("load: reading cell data for `%s'", nm.c_str ());
-                goto data_read_error;
-              }
-
-            cell_array(i) = tc2;
-          }
-
-        tc = cell_array;
-      }
-      break;
-
-    case MAT_FILE_SPARSE_CLASS:
-      {
-        octave_idx_type nr = dims(0);
-        octave_idx_type nc = dims(1);
-        SparseMatrix sm;
-        SparseComplexMatrix scm;
-        octave_idx_type *ridx;
-        octave_idx_type *cidx;
-        double *data;
-
-        // Setup return value
-        if (imag)
-          {
-            scm = SparseComplexMatrix (nr, nc, nzmax);
-            ridx = scm.ridx ();
-            cidx = scm.cidx ();
-            data = 0;
-          }
-        else
-          {
-            sm = SparseMatrix (nr, nc, nzmax);
-            ridx = sm.ridx ();
-            cidx = sm.cidx ();
-            data = sm.data ();
-          }
-
-        // row indices
-        std::streampos tmp_pos;
-
-        if (read_mat5_tag (is, swap, type, len))
-          {
-            error ("load: reading sparse row data for `%s'", retval.c_str ());
-            goto data_read_error;
-          }
-
-        tmp_pos = is.tellg ();
-
-        read_mat5_integer_data (is, ridx, nzmax, swap,
-                                static_cast<enum mat5_data_type> (type));
-
-        if (! is || error_state)
-          {
-            error ("load: reading sparse row data for `%s'", retval.c_str ());
-            goto data_read_error;
-          }
-
-        is.seekg (tmp_pos + static_cast<std::streamoff> (PAD (len)));
-
-        // col indices
-        if (read_mat5_tag (is, swap, type, len))
-          {
-            error ("load: reading sparse column data for `%s'", retval.c_str ());
-            goto data_read_error;
-          }
-
-        tmp_pos = is.tellg ();
-
-        read_mat5_integer_data (is, cidx, nc + 1, swap,
-                                static_cast<enum mat5_data_type> (type));
-
-        if (! is || error_state)
-          {
-            error ("load: reading sparse column data for `%s'", retval.c_str ());
-            goto data_read_error;
-          }
-
-        is.seekg (tmp_pos + static_cast<std::streamoff> (PAD (len)));
-
-        // real data subelement
-        if (read_mat5_tag (is, swap, type, len))
-          {
-            error ("load: reading sparse matrix data for `%s'", retval.c_str ());
-            goto data_read_error;
-          }
-
-        octave_idx_type nnz = cidx[nc];
-        NDArray re;
-        if (imag)
-          {
-            re = NDArray (dim_vector (nnz, 1));
-            data = re.fortran_vec ();
-          }
-
-        tmp_pos = is.tellg ();
-        read_mat5_binary_data (is, data, nnz, swap,
-                               static_cast<enum mat5_data_type> (type), flt_fmt);
-
-        if (! is || error_state)
-          {
-            error ("load: reading sparse matrix data for `%s'", retval.c_str ());
-            goto data_read_error;
-          }
-
-        is.seekg (tmp_pos + static_cast<std::streamoff> (PAD (len)));
-
-        // imaginary data subelement
-        if (imag)
-          {
-            NDArray im (dim_vector (static_cast<int> (nnz), 1));
-
-            if (read_mat5_tag (is, swap, type, len))
-              {
-                error ("load: reading sparse matrix data for `%s'", retval.c_str ());
-                goto data_read_error;
-              }
-
-            read_mat5_binary_data (is, im.fortran_vec (), nnz, swap,
-                                   static_cast<enum mat5_data_type> (type), flt_fmt);
-
-            if (! is || error_state)
-              {
-                error ("load: reading imaginary sparse matrix data for `%s'",
-                       retval.c_str ());
-                goto data_read_error;
-              }
-
-            for (octave_idx_type i = 0; i < nnz; i++)
-              scm.xdata (i) = Complex (re (i), im (i));
-
-            tc = scm;
-          }
-        else
-          tc = sm;
-      }
-      break;
-
-    case MAT_FILE_FUNCTION_CLASS:
-      {
-        octave_value tc2;
-        std::string nm
-          = read_mat5_binary_element (is, filename, swap, global, tc2);
-
-        if (! is || error_state)
-          goto data_read_error;
-
-        // Octave can handle both "/" and "\" as a directry seperator
-        // and so can ignore the seperator field of m0. I think the
-        // sentinel field is also save to ignore.
-        Octave_map m0 = tc2.map_value ();
-        Octave_map m1 = m0.contents ("function_handle")(0).map_value ();
-        std::string ftype = m1.contents ("type")(0).string_value ();
-        std::string fname = m1.contents ("function")(0).string_value ();
-        std::string fpath = m1.contents ("file")(0).string_value ();
-
-        if (ftype == "simple" || ftype == "scopedfunction")
-          {
-            if (fpath.length () == 0)
-              // We have a builtin function
-              tc = make_fcn_handle (fname);
-            else
-              {
-                std::string mroot =
-                  m0.contents ("matlabroot")(0).string_value ();
-
-                if ((fpath.length () >= mroot.length ()) &&
-                    fpath.substr (0, mroot.length ()) == mroot &&
-                    OCTAVE_EXEC_PREFIX != mroot)
-                  {
-                    // If fpath starts with matlabroot, and matlabroot
-                    // doesn't equal octave_config_info ("exec_prefix")
-                    // then the function points to a version of Octave
-                    // or Matlab other than the running version. In that
-                    // case we replace with the same function in the
-                    // running version of Octave?
-
-                    // First check if just replacing matlabroot is enough
-                    std::string str = OCTAVE_EXEC_PREFIX +
-                      fpath.substr (mroot.length ());
-                    file_stat fs (str);
-
-                    if (fs.exists ())
-                      {
-                        size_t xpos
-                          = str.find_last_of (file_ops::dir_sep_chars ());
-
-                        std::string dir_name = str.substr (0, xpos);
-
-                        octave_function *fcn
-                          = load_fcn_from_file (str, dir_name, "", fname);
-
-                        if (fcn)
-                          {
-                            octave_value tmp (fcn);
-
-                            tc = octave_value (new octave_fcn_handle (tmp, fname));
-                          }
-                      }
-                    else
-                      {
-                        // Next just search for it anywhere in the
-                        // system path
-                        string_vector names(3);
-                        names(0) = fname + ".oct";
-                        names(1) = fname + ".mex";
-                        names(2) = fname + ".m";
-
-                        dir_path p (load_path::system_path ());
-
-                        str = octave_env::make_absolute (p.find_first_of (names));
-
-                        size_t xpos
-                          = str.find_last_of (file_ops::dir_sep_chars ());
-
-                        std::string dir_name = str.substr (0, xpos);
-
-                        octave_function *fcn
-                          = load_fcn_from_file (str, dir_name, "", fname);
-
-                        if (fcn)
-                          {
-                            octave_value tmp (fcn);
-
-                            tc = octave_value (new octave_fcn_handle (tmp, fname));
-                          }
-                        else
-                          {
-                            warning ("load: can't find the file %s",
-                                     fpath.c_str ());
-                            goto skip_ahead;
-                          }
-                      }
-                  }
-                else
-                  {
-                    size_t xpos
-                      = fpath.find_last_of (file_ops::dir_sep_chars ());
-
-                    std::string dir_name = fpath.substr (0, xpos);
-
-                    octave_function *fcn
-                      = load_fcn_from_file (fpath, dir_name, "", fname);
-
-                    if (fcn)
-                      {
-                        octave_value tmp (fcn);
-
-                        tc = octave_value (new octave_fcn_handle (tmp, fname));
-                      }
-                    else
-                      {
-                        warning ("load: can't find the file %s",
-                                 fpath.c_str ());
-                        goto skip_ahead;
-                      }
-                  }
-              }
-          }
-        else if (ftype == "nested")
-          {
-            warning ("load: can't load nested function");
-            goto skip_ahead;
-          }
-        else if (ftype == "anonymous")
-          {
-            Octave_map m2 = m1.contents ("workspace")(0).map_value ();
-            uint32NDArray MCOS = m2.contents ("MCOS")(0).uint32_array_value ();
-            octave_idx_type off = static_cast<octave_idx_type>(MCOS(4).double_value ());
-            m2 = subsys_ov.map_value ();
-            m2 = m2.contents ("MCOS")(0).map_value ();
-            tc2 = m2.contents ("MCOS")(0).cell_value ()(1 + off).cell_value ()(1);
-            m2 = tc2.map_value ();
-
-            unwind_protect_safe frame;
-
-            // Set up temporary scope to use for evaluating the text
-            // that defines the anonymous function.
-
-            symbol_table::scope_id local_scope = symbol_table::alloc_scope ();
-            frame.add_fcn (symbol_table::erase_scope, local_scope);
-
-            symbol_table::set_scope (local_scope);
-
-            octave_call_stack::push (local_scope, 0);
-            frame.add_fcn (octave_call_stack::pop);
-
-            if (m2.nfields () > 0)
-              {
-                octave_value tmp;
-
-                for (Octave_map::iterator p0 = m2.begin () ;
-                     p0 != m2.end (); p0++)
-                  {
-                    std::string key = m2.key (p0);
-                    octave_value val = m2.contents (p0)(0);
-
-                    symbol_table::varref (key, local_scope, 0) = val;
-                  }
-              }
-
-            int parse_status;
-            octave_value anon_fcn_handle =
-              eval_string (fname.substr (4), true, parse_status);
-
-            if (parse_status == 0)
-              {
-                octave_fcn_handle *fh =
-                  anon_fcn_handle.fcn_handle_value ();
-
-                if (fh)
-                  tc = new octave_fcn_handle (fh->fcn_val (), "@<anonymous>");
-                else
-                  {
-                    error ("load: failed to load anonymous function handle");
-                    goto skip_ahead;
-                  }
-              }
-            else
-              {
-                error ("load: failed to load anonymous function handle");
-                goto skip_ahead;
-              }
-
-            frame.run ();
-          }
-        else
-          {
-            error ("load: invalid function handle type");
-            goto skip_ahead;
-          }
-      }
-      break;
-
-    case MAT_FILE_WORKSPACE_CLASS:
-      {
-        Octave_map m (dim_vector (1, 1));
-        int n_fields = 2;
-        string_vector field (n_fields);
-
-        for (int i = 0; i < n_fields; i++)
-          {
-            int32_t fn_type;
-            int32_t fn_len;
-            if (read_mat5_tag (is, swap, fn_type, fn_len) || fn_type != miINT8)
-              {
-                error ("load: invalid field name subelement");
-                goto data_read_error;
-              }
-
-            OCTAVE_LOCAL_BUFFER (char, elname, fn_len + 1);
-
-            std::streampos tmp_pos = is.tellg ();
-
-            if (fn_len)
-              {
-                if (! is.read (elname, fn_len))
-                  goto data_read_error;
-
-                is.seekg (tmp_pos +
-                          static_cast<std::streamoff> (PAD (fn_len)));
-              }
-
-            elname[fn_len] = '\0';
-
-            field(i) = elname;
-          }
-
-        std::vector<Cell> elt (n_fields);
-
-        for (octave_idx_type i = 0; i < n_fields; i++)
-          elt[i] = Cell (dims);
-
-        octave_idx_type n = dims.numel ();
-
-        // fields subelements
-        for (octave_idx_type j = 0; j < n; j++)
-          {
-            for (octave_idx_type i = 0; i < n_fields; i++)
-              {
-                if (field(i) == "MCOS")
-                  {
-                    octave_value fieldtc;
-                    read_mat5_binary_element (is, filename, swap, global,
-                                              fieldtc);
-                    if (! is || error_state)
-                      goto data_read_error;
-
-                    elt[i](j) = fieldtc;
-                  }
-                else
-                  elt[i](j) = octave_value ();
-              }
-          }
-
-        for (octave_idx_type i = 0; i < n_fields; i++)
-          m.assign (field (i), elt[i]);
-        tc = m;
-      }
-      break;
-
-    case MAT_FILE_OBJECT_CLASS:
-      {
-        isclass = true;
-
-        if (read_mat5_tag (is, swap, type, len) || type != miINT8)
-          {
-            error ("load: invalid class name");
-            goto skip_ahead;
-          }
-
-        {
-          OCTAVE_LOCAL_BUFFER (char, name, len+1);
-
-          std::streampos tmp_pos = is.tellg ();
-
-          if (len)
-            {
-              if (! is.read (name, len ))
-                goto data_read_error;
-
-              is.seekg (tmp_pos + static_cast<std::streamoff> (PAD (len)));
-            }
-
-          name[len] = '\0';
-          classname = name;
-        }
-      }
-      // Fall-through
-    case MAT_FILE_STRUCT_CLASS:
-      {
-        Octave_map m (dim_vector (1, 1));
-        int32_t fn_type;
-        int32_t fn_len;
-        int32_t field_name_length;
-
-        // field name length subelement -- actually the maximum length
-        // of a field name.  The Matlab docs promise this will always
-        // be 32.  We read and use the actual value, on the theory
-        // that eventually someone will recognize that's a waste of
-        // space.
-        if (read_mat5_tag (is, swap, fn_type, fn_len) || fn_type != miINT32)
-          {
-            error ("load: invalid field name length subelement");
-            goto data_read_error;
-          }
-
-        if (! is.read (reinterpret_cast<char *> (&field_name_length), fn_len ))
-          goto data_read_error;
-
-        if (swap)
-          swap_bytes<4> (&field_name_length);
-
-        // field name subelement.  The length of this subelement tells
-        // us how many fields there are.
-        if (read_mat5_tag (is, swap, fn_type, fn_len) || fn_type != miINT8)
-          {
-            error ("load: invalid field name subelement");
-            goto data_read_error;
-          }
-
-        octave_idx_type n_fields = fn_len/field_name_length;
-
-        if (n_fields > 0)
-          {
-            fn_len = PAD (fn_len);
-
-            OCTAVE_LOCAL_BUFFER (char, elname, fn_len);
-
-            if (! is.read (elname, fn_len))
-              goto data_read_error;
-
-            std::vector<Cell> elt (n_fields);
-
-            for (octave_idx_type i = 0; i < n_fields; i++)
-              elt[i] = Cell (dims);
-
-            octave_idx_type n = dims.numel ();
-
-            // fields subelements
-            for (octave_idx_type j = 0; j < n; j++)
-              {
-                for (octave_idx_type i = 0; i < n_fields; i++)
-                  {
-                    octave_value fieldtc;
-                    read_mat5_binary_element (is, filename, swap, global,
-                                              fieldtc);
-                    elt[i](j) = fieldtc;
-                  }
-              }
-
-            for (octave_idx_type i = 0; i < n_fields; i++)
-              {
-                const char *key = elname + i*field_name_length;
-
-                m.assign (key, elt[i]);
-              }
-          }
-
-        if (isclass)
-          {
-            if (classname == "inline")
-              {
-                // inline is not an object in Octave but rather an
-                // overload of a function handle. Special case.
-                tc =
-                  new octave_fcn_inline (m.contents ("expr")(0).string_value (),
-                                         m.contents ("args")(0).string_value ());
-              }
-            else
-              {
-                octave_class* cls
-                  = new octave_class (m, classname,
-                                      std::list<std::string> ());
-
-                if (cls->reconstruct_exemplar ())
-                  {
-
-                    if (! cls->reconstruct_parents ())
-                      warning ("load: unable to reconstruct object inheritance");
-
-                    tc = cls;
-                    if (load_path::find_method (classname, "loadobj") !=
-                        std::string ())
-                      {
-                        octave_value_list tmp = feval ("loadobj", tc, 1);
-
-                        if (! error_state)
-                          tc = tmp(0);
-                        else
-                          goto data_read_error;
-                      }
-                  }
-                else
-                  {
-                    tc = m;
-                    warning ("load: element has been converted to a structure");
-                  }
-              }
-          }
-        else
-          tc = m;
-      }
-      break;
-
-    case MAT_FILE_INT8_CLASS:
-      OCTAVE_MAT5_INTEGER_READ (int8NDArray);
-      break;
-
-    case MAT_FILE_UINT8_CLASS:
-      {
-        OCTAVE_MAT5_INTEGER_READ (uint8NDArray);
-
-        // Logical variables can either be MAT_FILE_UINT8_CLASS or
-        // MAT_FILE_DOUBLE_CLASS, so check if we have a logical
-        // variable and convert it.
-
-        if (logicalvar)
-          {
-            uint8NDArray in = tc.uint8_array_value ();
-            octave_idx_type nel = in.numel ();
-            boolNDArray out (dims);
-
-            for (octave_idx_type i = 0; i < nel; i++)
-              out(i) = in(i).bool_value ();
-
-            tc = out;
-          }
-      }
-      break;
-
-    case MAT_FILE_INT16_CLASS:
-      OCTAVE_MAT5_INTEGER_READ (int16NDArray);
-      break;
-
-    case MAT_FILE_UINT16_CLASS:
-      OCTAVE_MAT5_INTEGER_READ (uint16NDArray);
-      break;
-
-    case MAT_FILE_INT32_CLASS:
-      OCTAVE_MAT5_INTEGER_READ (int32NDArray);
-      break;
-
-    case MAT_FILE_UINT32_CLASS:
-      OCTAVE_MAT5_INTEGER_READ (uint32NDArray);
-      break;
-
-    case MAT_FILE_INT64_CLASS:
-      OCTAVE_MAT5_INTEGER_READ (int64NDArray);
-      break;
-
-    case MAT_FILE_UINT64_CLASS:
-      OCTAVE_MAT5_INTEGER_READ (uint64NDArray);
-      break;
-
-
-    case MAT_FILE_SINGLE_CLASS:
-      {
-        FloatNDArray re (dims);
-
-        // real data subelement
-
-        std::streampos tmp_pos;
-
-        if (read_mat5_tag (is, swap, type, len))
-          {
-            error ("load: reading matrix data for `%s'", retval.c_str ());
-            goto data_read_error;
-          }
-
-        octave_idx_type n = re.numel ();
-        tmp_pos = is.tellg ();
-        read_mat5_binary_data (is, re.fortran_vec (), n, swap,
-                               static_cast<enum mat5_data_type> (type), flt_fmt);
-
-        if (! is || error_state)
-          {
-            error ("load: reading matrix data for `%s'", retval.c_str ());
-            goto data_read_error;
-          }
-
-        is.seekg (tmp_pos + static_cast<std::streamoff> (PAD (len)));
-
-        if (imag)
-          {
-            // imaginary data subelement
-
-            FloatNDArray im (dims);
-
-            if (read_mat5_tag (is, swap, type, len))
-              {
-                error ("load: reading matrix data for `%s'", retval.c_str ());
-                goto data_read_error;
-              }
-
-            n = im.numel ();
-            read_mat5_binary_data (is, im.fortran_vec (), n, swap,
-                                   static_cast<enum mat5_data_type> (type), flt_fmt);
-
-            if (! is || error_state)
-              {
-                error ("load: reading imaginary matrix data for `%s'",
-                       retval.c_str ());
-                goto data_read_error;
-              }
-
-            FloatComplexNDArray ctmp (dims);
-
-            for (octave_idx_type i = 0; i < n; i++)
-              ctmp(i) = FloatComplex (re(i), im(i));
-
-            tc = ctmp;
-          }
-        else
-          tc = re;
-      }
-      break;
-
-    case MAT_FILE_CHAR_CLASS:
-      // handle as a numerical array to start with
-
-    case MAT_FILE_DOUBLE_CLASS:
-    default:
-      {
-        NDArray re (dims);
-
-        // real data subelement
-
-        std::streampos tmp_pos;
-
-        if (read_mat5_tag (is, swap, type, len))
-          {
-            error ("load: reading matrix data for `%s'", retval.c_str ());
-            goto data_read_error;
-          }
-
-        octave_idx_type n = re.numel ();
-        tmp_pos = is.tellg ();
-        read_mat5_binary_data (is, re.fortran_vec (), n, swap,
-                               static_cast<enum mat5_data_type> (type), flt_fmt);
-
-        if (! is || error_state)
-          {
-            error ("load: reading matrix data for `%s'", retval.c_str ());
-            goto data_read_error;
-          }
-
-        is.seekg (tmp_pos + static_cast<std::streamoff> (PAD (len)));
-
-        if (logicalvar)
-          {
-            // Logical variables can either be MAT_FILE_UINT8_CLASS or
-            // MAT_FILE_DOUBLE_CLASS, so check if we have a logical
-            // variable and convert it.
-
-            boolNDArray out (dims);
-
-            for (octave_idx_type i = 0; i < n; i++)
-              out (i) = static_cast<bool> (re (i));
-
-            tc = out;
-          }
-        else if (imag)
-          {
-            // imaginary data subelement
-
-            NDArray im (dims);
-
-            if (read_mat5_tag (is, swap, type, len))
-              {
-                error ("load: reading matrix data for `%s'", retval.c_str ());
-                goto data_read_error;
-              }
-
-            n = im.numel ();
-            read_mat5_binary_data (is, im.fortran_vec (), n, swap,
-                                   static_cast<enum mat5_data_type> (type), flt_fmt);
-
-            if (! is || error_state)
-              {
-                error ("load: reading imaginary matrix data for `%s'",
-                       retval.c_str ());
-                goto data_read_error;
-              }
-
-            ComplexNDArray ctmp (dims);
-
-            for (octave_idx_type i = 0; i < n; i++)
-              ctmp(i) = Complex (re(i), im(i));
-
-            tc = ctmp;
-          }
-        else
-          {
-            if (arrayclass == MAT_FILE_CHAR_CLASS)
-              {
-                if (type == miUTF16 || type == miUTF32)
-                  {
-                    bool found_big_char = false;
-                    for (octave_idx_type i = 0; i < n; i++)
-                      {
-                        if (re(i) > 127) {
-                          re(i) = '?';
-                          found_big_char = true;
-                        }
-                      }
-
-                    if (found_big_char)
-                      warning ("load: can not read non-ASCII portions of UTF characters; replacing unreadable characters with '?'");
-                  }
-                else if (type == miUTF8)
-                  {
-                    // Search for multi-byte encoded UTF8 characters and
-                    // replace with 0x3F for '?'... Give the user a warning
-
-                    bool utf8_multi_byte = false;
-                    for (octave_idx_type i = 0; i < n; i++)
-                      {
-                        unsigned char a = static_cast<unsigned char> (re(i));
-                        if (a > 0x7f)
-                          utf8_multi_byte = true;
-                      }
-
-                    if (utf8_multi_byte)
-                      {
-                        warning ("load: can not read multi-byte encoded UTF8 characters; replacing unreadable characters with '?'");
-                        for (octave_idx_type i = 0; i < n; i++)
-                          {
-                            unsigned char a = static_cast<unsigned char> (re(i));
-                            if (a > 0x7f)
-                              re(i) = '?';
-                          }
-                      }
-                  }
-                tc = re;
-                tc = tc.convert_to_str (false, true, '\'');
-              }
-            else
-              tc = re;
-          }
-      }
-    }
-
-  is.seekg (pos + static_cast<std::streamoff> (element_length));
-
-  if (is.eof ())
-    is.clear ();
-
-  return retval;
-
- data_read_error:
- early_read_error:
-  error ("load: trouble reading binary file `%s'", filename.c_str ());
-  return std::string ();
-
- skip_ahead:
-  warning ("skipping over `%s'", retval.c_str ());
-  is.seekg (pos + static_cast<std::streamoff> (element_length));
-  return read_mat5_binary_element (is, filename, swap, global, tc);
-}
-
-int
-read_mat5_binary_file_header (std::istream& is, bool& swap, bool quiet,
-                              const std::string& filename)
-{
-  int16_t version=0, magic=0;
-  uint64_t subsys_offset;
-
-  is.seekg (116, std::ios::beg);
-  is.read (reinterpret_cast<char *> (&subsys_offset), 8);
-
-  is.seekg (124, std::ios::beg);
-  is.read (reinterpret_cast<char *> (&version), 2);
-  is.read (reinterpret_cast<char *> (&magic), 2);
-
-  if (magic == 0x4d49)
-    swap = 0;
-  else if (magic == 0x494d)
-    swap = 1;
-  else
-    {
-      if (! quiet)
-        error ("load: can't read binary file");
-      return -1;
-    }
-
-  if (! swap)                   // version number is inverse swapped!
-    version = ((version >> 8) & 0xff) + ((version & 0xff) << 8);
-
-  if (version != 1 && !quiet)
-    warning ("load: found version %d binary MAT file, "
-             "but only prepared for version 1", version);
-
-  if (swap)
-    swap_bytes<8> (&subsys_offset, 1);
-
-  if (subsys_offset != 0x2020202020202020ULL && subsys_offset != 0ULL)
-    {
-      // Read the subsystem data block
-      is.seekg (subsys_offset, std::ios::beg);
-
-      octave_value tc;
-      bool global;
-      read_mat5_binary_element (is, filename, swap, global, tc);
-
-      if (!is || error_state)
-        return -1;
-
-      if (tc.is_uint8_type ())
-        {
-          const uint8NDArray itmp = tc.uint8_array_value ();
-          octave_idx_type ilen = itmp.numel ();
-
-          // Why should I have to initialize outbuf as just overwrite
-          std::string outbuf (ilen - 7, ' ');
-
-          // FIXME -- find a way to avoid casting away const here
-          char *ctmp = const_cast<char *> (outbuf.c_str ());
-          for (octave_idx_type j = 8; j < ilen; j++)
-            ctmp[j-8] = itmp(j).char_value ();
-
-          std::istringstream fh_ws (outbuf);
-
-          read_mat5_binary_element (fh_ws, filename, swap, global, subsys_ov);
-
-          if (error_state)
-            return -1;
-        }
-      else
-        return -1;
-
-      // Reposition to just after the header
-      is.seekg (128, std::ios::beg);
-    }
-
-  return 0;
-}
-
-static int
-write_mat5_tag (std::ostream& is, int type, octave_idx_type bytes)
-{
-  int32_t temp;
-
-  if (bytes > 0 && bytes <= 4)
-    temp = (bytes << 16) + type;
-  else
-    {
-      temp = type;
-      if (! is.write (reinterpret_cast<char *> (&temp), 4))
-        goto data_write_error;
-      temp = bytes;
-    }
-
-  if (! is.write (reinterpret_cast<char *> (&temp), 4))
-    goto data_write_error;
-
-  return 0;
-
- data_write_error:
-  return 1;
-}
-
-// Have to use copy here to avoid writing over data accessed via
-// Matrix::data().
-
-#define MAT5_DO_WRITE(TYPE, data, count, stream) \
-  do \
-    { \
-      OCTAVE_LOCAL_BUFFER (TYPE, ptr, count); \
-      for (octave_idx_type i = 0; i < count; i++) \
-        ptr[i] = static_cast<TYPE> (data[i]); \
-      stream.write (reinterpret_cast<char *> (ptr), count * sizeof (TYPE)); \
-    } \
-  while (0)
-
-// write out the numeric values in M to OS,
-// preceded by the appropriate tag.
-static void
-write_mat5_array (std::ostream& os, const NDArray& m, bool save_as_floats)
-{
-  save_type st = LS_DOUBLE;
-  const double *data = m.data ();
-
-  if (save_as_floats)
-    {
-      if (m.too_large_for_float ())
-        {
-          warning ("save: some values too large to save as floats --");
-          warning ("save: saving as doubles instead");
-        }
-      else
-        st = LS_FLOAT;
-    }
-
-  double max_val, min_val;
-  if (m.all_integers (max_val, min_val))
-    st = get_save_type (max_val, min_val);
-
-  mat5_data_type mst;
-  int size;
-  switch (st)
-    {
-    default:
-    case LS_DOUBLE:  mst = miDOUBLE; size = 8; break;
-    case LS_FLOAT:   mst = miSINGLE; size = 4; break;
-    case LS_U_CHAR:  mst = miUINT8;  size = 1; break;
-    case LS_U_SHORT: mst = miUINT16; size = 2; break;
-    case LS_U_INT:   mst = miUINT32; size = 4; break;
-    case LS_CHAR:    mst = miINT8;   size = 1; break;
-    case LS_SHORT:   mst = miINT16;  size = 2; break;
-    case LS_INT:     mst = miINT32;  size = 4; break;
-    }
-
-  octave_idx_type nel = m.numel ();
-  octave_idx_type len = nel*size;
-
-  write_mat5_tag (os, mst, len);
-
-  {
-    switch (st)
-      {
-      case LS_U_CHAR:
-        MAT5_DO_WRITE (uint8_t, data, nel, os);
-        break;
-
-      case LS_U_SHORT:
-        MAT5_DO_WRITE (uint16_t, data, nel, os);
-        break;
-
-      case LS_U_INT:
-        MAT5_DO_WRITE (uint32_t, data, nel, os);
-        break;
-
-      case LS_U_LONG:
-        MAT5_DO_WRITE (uint64_t, data, nel, os);
-        break;
-
-      case LS_CHAR:
-        MAT5_DO_WRITE (int8_t, data, nel, os);
-        break;
-
-      case LS_SHORT:
-        MAT5_DO_WRITE (int16_t, data, nel, os);
-        break;
-
-      case LS_INT:
-        MAT5_DO_WRITE (int32_t, data, nel, os);
-        break;
-
-      case LS_LONG:
-        MAT5_DO_WRITE (int64_t, data, nel, os);
-        break;
-
-      case LS_FLOAT:
-        MAT5_DO_WRITE (float, data, nel, os);
-        break;
-
-      case LS_DOUBLE: // No conversion necessary.
-        os.write (reinterpret_cast<const char *> (data), len);
-        break;
-
-      default:
-        (*current_liboctave_error_handler)
-          ("unrecognized data format requested");
-        break;
-      }
-  }
-  if (PAD (len) > len)
-    {
-      static char buf[9]="\x00\x00\x00\x00\x00\x00\x00\x00";
-      os.write (buf, PAD (len) - len);
-    }
-}
-
-static void
-write_mat5_array (std::ostream& os, const FloatNDArray& m, bool)
-{
-  save_type st = LS_FLOAT;
-  const float *data = m.data ();
-
-  float max_val, min_val;
-  if (m.all_integers (max_val, min_val))
-    st = get_save_type (max_val, min_val);
-
-  mat5_data_type mst;
-  int size;
-  switch (st)
-    {
-    default:
-    case LS_DOUBLE:  mst = miDOUBLE; size = 8; break;
-    case LS_FLOAT:   mst = miSINGLE; size = 4; break;
-    case LS_U_CHAR:  mst = miUINT8;  size = 1; break;
-    case LS_U_SHORT: mst = miUINT16; size = 2; break;
-    case LS_U_INT:   mst = miUINT32; size = 4; break;
-    case LS_CHAR:    mst = miINT8;   size = 1; break;
-    case LS_SHORT:   mst = miINT16;  size = 2; break;
-    case LS_INT:     mst = miINT32;  size = 4; break;
-    }
-
-  octave_idx_type nel = m.numel ();
-  octave_idx_type len = nel*size;
-
-  write_mat5_tag (os, mst, len);
-
-  {
-    switch (st)
-      {
-      case LS_U_CHAR:
-        MAT5_DO_WRITE (uint8_t, data, nel, os);
-        break;
-
-      case LS_U_SHORT:
-        MAT5_DO_WRITE (uint16_t, data, nel, os);
-        break;
-
-      case LS_U_INT:
-        MAT5_DO_WRITE (uint32_t, data, nel, os);
-        break;
-
-      case LS_U_LONG:
-        MAT5_DO_WRITE (uint64_t, data, nel, os);
-        break;
-
-      case LS_CHAR:
-        MAT5_DO_WRITE (int8_t, data, nel, os);
-        break;
-
-      case LS_SHORT:
-        MAT5_DO_WRITE (int16_t, data, nel, os);
-        break;
-
-      case LS_INT:
-        MAT5_DO_WRITE (int32_t, data, nel, os);
-        break;
-
-      case LS_LONG:
-        MAT5_DO_WRITE (int64_t, data, nel, os);
-        break;
-
-      case LS_FLOAT: // No conversion necessary.
-        os.write (reinterpret_cast<const char *> (data), len);
-        break;
-
-      case LS_DOUBLE:
-        MAT5_DO_WRITE (double, data, nel, os);
-        break;
-
-      default:
-        (*current_liboctave_error_handler)
-          ("unrecognized data format requested");
-        break;
-      }
-  }
-  if (PAD (len) > len)
-    {
-      static char buf[9]="\x00\x00\x00\x00\x00\x00\x00\x00";
-      os.write (buf, PAD (len) - len);
-    }
-}
-
-template <class T>
-void
-write_mat5_integer_data (std::ostream& os, const T *m, int size,
-                         octave_idx_type nel)
-{
-  mat5_data_type mst;
-  unsigned len;
-
-  switch (size)
-    {
-    case 1:
-      mst = miUINT8;
-      break;
-    case 2:
-      mst = miUINT16;
-      break;
-    case 4:
-      mst = miUINT32;
-      break;
-    case 8:
-      mst = miUINT64;
-      break;
-    case -1:
-      mst = miINT8;
-      size = - size;
-      break;
-    case -2:
-      mst = miINT16;
-      size = - size;
-      break;
-    case -4:
-      mst = miINT32;
-      size = - size;
-      break;
-    case -8:
-    default:
-      mst = miINT64;
-      size = - size;
-      break;
-    }
-
-  len = nel*size;
-  write_mat5_tag (os, mst, len);
-
-  os.write (reinterpret_cast<const char *> (m), len);
-
-  if (PAD (len) > len)
-    {
-      static char buf[9]="\x00\x00\x00\x00\x00\x00\x00\x00";
-      os.write (buf, PAD (len) - len);
-    }
-}
-
-template void
-write_mat5_integer_data (std::ostream& os, const octave_int8 *m,
-                         int size, octave_idx_type nel);
-
-template void
-write_mat5_integer_data (std::ostream& os, const octave_int16 *m,
-                         int size, octave_idx_type nel);
-
-template void
-write_mat5_integer_data (std::ostream& os, const octave_int32 *m,
-                         int size, octave_idx_type nel);
-
-template void
-write_mat5_integer_data (std::ostream& os, const octave_int64 *m,
-                         int size, octave_idx_type nel);
-
-template void
-write_mat5_integer_data (std::ostream& os, const octave_uint8 *m,
-                         int size, octave_idx_type nel);
-
-template void
-write_mat5_integer_data (std::ostream& os, const octave_uint16 *m,
-                         int size, octave_idx_type nel);
-
-template void
-write_mat5_integer_data (std::ostream& os, const octave_uint32 *m,
-                         int size, octave_idx_type nel);
-
-template void
-write_mat5_integer_data (std::ostream& os, const octave_uint64 *m,
-                         int size, octave_idx_type nel);
-
-template void
-write_mat5_integer_data (std::ostream& os, const int *m,
-                         int size, octave_idx_type nel);
-
-// Write out cell element values in the cell array to OS, preceded by
-// the appropriate tag.
-
-static bool
-write_mat5_cell_array (std::ostream& os, const Cell& cell,
-                       bool mark_as_global, bool save_as_floats)
-{
-  octave_idx_type nel = cell.numel ();
-
-  for (octave_idx_type i = 0; i < nel; i++)
-    {
-      octave_value ov = cell(i);
-
-      if (! save_mat5_binary_element (os, ov, "", mark_as_global,
-                                      false, save_as_floats))
-        return false;
-    }
-
-  return true;
-}
-
-int
-save_mat5_array_length (const double* val, octave_idx_type nel,
-                        bool save_as_floats)
-{
-  if (nel > 0)
-    {
-      int size = 8;
-
-      if (save_as_floats)
-        {
-          bool too_large_for_float = false;
-          for (octave_idx_type i = 0; i < nel; i++)
-            {
-              double tmp = val[i];
-
-              if (! (xisnan (tmp) || xisinf (tmp))
-                  && fabs (tmp) > FLT_MAX)
-                {
-                  too_large_for_float = true;
-                  break;
-                }
-            }
-
-          if (!too_large_for_float)
-            size = 4;
-        }
-
-      // The code below is disabled since get_save_type currently doesn't
-      // deal with integer types. This will need to be activated if get_save_type
-      // is changed.
-
-      // double max_val = val[0];
-      // double min_val = val[0];
-      // bool all_integers =  true;
-      //
-      // for (int i = 0; i < nel; i++)
-      //   {
-      //     double val = val[i];
-      //
-      //     if (val > max_val)
-      //       max_val = val;
-      //
-      //     if (val < min_val)
-      //       min_val = val;
-      //
-      //     if (D_NINT (val) != val)
-      //       {
-      //         all_integers = false;
-      //         break;
-      //       }
-      //   }
-      //
-      // if (all_integers)
-      //   {
-      //     if (max_val < 256 && min_val > -1)
-      //       size = 1;
-      //     else if (max_val < 65536 && min_val > -1)
-      //       size = 2;
-      //     else if (max_val < 4294967295UL && min_val > -1)
-      //       size = 4;
-      //     else if (max_val < 128 && min_val >= -128)
-      //       size = 1;
-      //     else if (max_val < 32768 && min_val >= -32768)
-      //       size = 2;
-      //     else if (max_val <= 2147483647L && min_val >= -2147483647L)
-      //       size = 4;
-      //   }
-
-      return 8 + nel * size;
-    }
-  else
-    return 8;
-}
-
-int
-save_mat5_array_length (const float* /* val */, octave_idx_type nel, bool)
-{
-  if (nel > 0)
-    {
-      int size = 4;
-
-
-      // The code below is disabled since get_save_type currently doesn't
-      // deal with integer types. This will need to be activated if get_save_type
-      // is changed.
-
-      // float max_val = val[0];
-      // float min_val = val[0];
-      // bool all_integers =  true;
-      //
-      // for (int i = 0; i < nel; i++)
-      //   {
-      //     float val = val[i];
-      //
-      //     if (val > max_val)
-      //       max_val = val;
-      //
-      //     if (val < min_val)
-      //       min_val = val;
-      //
-      //     if (D_NINT (val) != val)
-      //       {
-      //         all_integers = false;
-      //         break;
-      //       }
-      //   }
-      //
-      // if (all_integers)
-      //   {
-      //     if (max_val < 256 && min_val > -1)
-      //       size = 1;
-      //     else if (max_val < 65536 && min_val > -1)
-      //       size = 2;
-      //     else if (max_val < 4294967295UL && min_val > -1)
-      //       size = 4;
-      //     else if (max_val < 128 && min_val >= -128)
-      //       size = 1;
-      //     else if (max_val < 32768 && min_val >= -32768)
-      //       size = 2;
-      //     else if (max_val <= 2147483647L && min_val >= -2147483647L)
-      //       size = 4;
-      //   }
-
-      // Round nel up to nearest even number of elements. Take into account
-      // Short tags for 4 byte elements.
-      return PAD ((nel > 0 && nel * size <= 4 ? 4 : 8) + nel * size);
-    }
-  else
-    return 8;
-}
-
-int
-save_mat5_array_length (const Complex* val, octave_idx_type nel,
-                        bool save_as_floats)
-{
-  int ret;
-
-  OCTAVE_LOCAL_BUFFER (double, tmp, nel);
-
-  for (octave_idx_type i = 1; i < nel; i++)
-    tmp[i] = std::real (val[i]);
-
-  ret = save_mat5_array_length (tmp, nel, save_as_floats);
-
-  for (octave_idx_type i = 1; i < nel; i++)
-    tmp[i] = std::imag (val[i]);
-
-  ret += save_mat5_array_length (tmp, nel, save_as_floats);
-
-  return ret;
-}
-
-int
-save_mat5_array_length (const FloatComplex* val, octave_idx_type nel,
-                        bool save_as_floats)
-{
-  int ret;
-
-  OCTAVE_LOCAL_BUFFER (float, tmp, nel);
-
-  for (octave_idx_type i = 1; i < nel; i++)
-    tmp[i] = std::real (val[i]);
-
-  ret = save_mat5_array_length (tmp, nel, save_as_floats);
-
-  for (octave_idx_type i = 1; i < nel; i++)
-    tmp[i] = std::imag (val[i]);
-
-  ret += save_mat5_array_length (tmp, nel, save_as_floats);
-
-  return ret;
-}
-
-int
-save_mat5_element_length (const octave_value& tc, const std::string& name,
-                          bool save_as_floats, bool mat7_format)
-{
-  size_t max_namelen = (mat7_format ? 63 : 31);
-  size_t len = name.length ();
-  std::string cname = tc.class_name ();
-  int ret = 32;
-
-  if (len > 4)
-    ret += PAD (len > max_namelen ? max_namelen : len);
-
-  ret += PAD (4 * tc.ndims ());
-
-  if (tc.is_string ())
-    {
-      charNDArray chm = tc.char_array_value ();
-      ret += 8;
-      if (chm.numel () > 2)
-        ret += PAD (2 * chm.numel ());
-    }
-  else if (tc.is_sparse_type ())
-    {
-      if (tc.is_complex_type ())
-        {
-          const SparseComplexMatrix m = tc.sparse_complex_matrix_value ();
-          octave_idx_type nc = m.cols ();
-          octave_idx_type nnz = m.nnz ();
-
-          ret += 16 + save_mat5_array_length (m.data (), nnz, save_as_floats);
-          if (nnz > 1)
-            ret += PAD (nnz * sizeof (int32_t));
-          if (nc > 0)
-            ret += PAD ((nc + 1) * sizeof (int32_t));
-        }
-      else
-        {
-          const SparseMatrix m = tc.sparse_matrix_value ();
-          octave_idx_type nc = m.cols ();
-          octave_idx_type nnz = m.nnz ();
-
-          ret += 16 + save_mat5_array_length (m.data (), nnz, save_as_floats);
-          if (nnz > 1)
-            ret += PAD (nnz * sizeof (int32_t));
-          if (nc > 0)
-            ret += PAD ((nc + 1) * sizeof (int32_t));
-        }
-    }
-
-#define INT_LEN(nel, size) \
-  { \
-    ret += 8; \
-    octave_idx_type sz = nel * size; \
-    if (sz > 4) \
-      ret += PAD (sz);  \
-  }
-
-  else if (cname == "int8")
-    INT_LEN (tc.int8_array_value ().numel (), 1)
-  else if (cname == "int16")
-    INT_LEN (tc.int16_array_value ().numel (), 2)
-  else if (cname == "int32")
-    INT_LEN (tc.int32_array_value ().numel (), 4)
-  else if (cname == "int64")
-    INT_LEN (tc.int64_array_value ().numel (), 8)
-  else if (cname == "uint8")
-    INT_LEN (tc.uint8_array_value ().numel (), 1)
-  else if (cname == "uint16")
-    INT_LEN (tc.uint16_array_value ().numel (), 2)
-  else if (cname == "uint32")
-    INT_LEN (tc.uint32_array_value ().numel (), 4)
-  else if (cname == "uint64")
-    INT_LEN (tc.uint64_array_value ().numel (), 8)
-  else if (tc.is_bool_type ())
-    INT_LEN (tc.bool_array_value ().numel (), 1)
-  else if (tc.is_real_scalar () || tc.is_real_matrix () || tc.is_range ())
-    {
-      if (tc.is_single_type ())
-        {
-          const FloatNDArray m = tc.float_array_value ();
-          ret += save_mat5_array_length (m.fortran_vec (), m.numel (),
-                                         save_as_floats);
-        }
-      else
-        {
-          const NDArray m = tc.array_value ();
-          ret += save_mat5_array_length (m.fortran_vec (), m.numel (),
-                                         save_as_floats);
-        }
-    }
-  else if (tc.is_cell ())
-    {
-      Cell cell = tc.cell_value ();
-      octave_idx_type nel = cell.numel ();
-
-      for (int i = 0; i < nel; i++)
-        ret += 8 +
-          save_mat5_element_length (cell (i), "", save_as_floats, mat7_format);
-    }
-  else if (tc.is_complex_scalar () || tc.is_complex_matrix ())
-    {
-      if (tc.is_single_type ())
-        {
-          const FloatComplexNDArray m = tc.float_complex_array_value ();
-          ret += save_mat5_array_length (m.fortran_vec (), m.numel (),
-                                         save_as_floats);
-        }
-      else
-        {
-          const ComplexNDArray m = tc.complex_array_value ();
-          ret += save_mat5_array_length (m.fortran_vec (), m.numel (),
-                                         save_as_floats);
-        }
-    }
-  else if (tc.is_map () || tc.is_inline_function () || tc.is_object ())
-    {
-      int fieldcnt = 0;
-      const Octave_map m = tc.map_value ();
-      octave_idx_type nel = m.numel ();
-
-      if (tc.is_inline_function ())
-        // length of "inline" is 6
-        ret += 8 + PAD (6 > max_namelen ? max_namelen : 6);
-      else if (tc.is_object ())
-        {
-          size_t classlen = tc.class_name (). length ();
-
-          ret += 8 + PAD (classlen > max_namelen ? max_namelen : classlen);
-        }
-
-      for (Octave_map::const_iterator i = m.begin (); i != m.end (); i++)
-        fieldcnt++;
-
-      ret += 16 + fieldcnt * (max_namelen + 1);
-
-
-      for (octave_idx_type j = 0; j < nel; j++)
-        {
-
-          for (Octave_map::const_iterator i = m.begin (); i != m.end (); i++)
-            {
-              const Cell elts = m.contents (i);
-
-              ret += 8 + save_mat5_element_length (elts(j), "",
-                                               save_as_floats, mat7_format);
-            }
-        }
-    }
-  else
-    ret = -1;
-
-  return ret;
-}
-
-static void
-write_mat5_sparse_index_vector (std::ostream& os,
-                                const octave_idx_type *idx,
-                                octave_idx_type nel)
-{
-  int tmp = sizeof (int32_t);
-
-  OCTAVE_LOCAL_BUFFER (int32_t, tmp_idx, nel);
-
-  for (octave_idx_type i = 0; i < nel; i++)
-    tmp_idx[i] = idx[i];
-
-  write_mat5_integer_data (os, tmp_idx, -tmp, nel);
-}
-
-static void
-gripe_dim_too_large (const std::string& name)
-{
-  warning ("save: skipping %s: dimension too large for MAT format",
-           name.c_str ());
-}
-
-// save the data from TC along with the corresponding NAME on stream
-// OS in the MatLab version 5 binary format.  Return true on success.
-
-bool
-save_mat5_binary_element (std::ostream& os,
-                          const octave_value& tc, const std::string& name,
-                          bool mark_as_global, bool mat7_format,
-                          bool save_as_floats, bool compressing)
-{
-  int32_t flags = 0;
-  int32_t nnz_32 = 0;
-  std::string cname = tc.class_name ();
-  size_t max_namelen = (mat7_format ? 63 : 31);
-
-  dim_vector dv = tc.dims ();
-  int nd = tc.ndims ();
-  int dim_len = 4*nd;
-
-  static octave_idx_type max_dim_val = std::numeric_limits<int32_t>::max ();
-
-  for (int i = 0; i < nd; i++)
-    {
-      if (dv(i) > max_dim_val)
-        {
-          gripe_dim_too_large (name);
-          goto skip_to_next;
-        }
-    }
-
-  if (tc.is_sparse_type ())
-    {
-      octave_idx_type nnz;
-      octave_idx_type nc;
-
-      if (tc.is_complex_type ())
-        {
-          SparseComplexMatrix scm = tc.sparse_complex_matrix_value ();
-          nnz = scm.nzmax ();
-          nc = scm.cols ();
-        }
-      else
-        {
-          SparseMatrix sm = tc.sparse_matrix_value ();
-          nnz = sm.nzmax ();
-          nc = sm.cols ();
-        }
-
-      if (nnz > max_dim_val || nc + 1 > max_dim_val)
-        {
-          gripe_dim_too_large (name);
-          goto skip_to_next;
-        }
-
-      nnz_32 = nnz;
-    }
-  else if (dv.numel () > max_dim_val)
-    {
-      gripe_dim_too_large (name);
-      goto skip_to_next;
-    }
-
-#ifdef HAVE_ZLIB
-  if (mat7_format && !compressing)
-    {
-      bool ret = false;
-
-      std::ostringstream buf;
-
-      // The code seeks backwards in the stream to fix the header. Can't
-      // do this with zlib, so use a stringstream.
-      ret = save_mat5_binary_element (buf, tc, name, mark_as_global, true,
-                                      save_as_floats, true);
-
-      if (ret)
-        {
-          // destLen must be at least 0.1% larger than source buffer
-          // + 12 bytes. Reality is it must be larger again than that.
-          std::string buf_str = buf.str ();
-          uLongf srcLen = buf_str.length ();
-          uLongf destLen = srcLen * 101 / 100 + 12;
-          OCTAVE_LOCAL_BUFFER (char, out_buf, destLen);
-
-          if (compress (reinterpret_cast<Bytef *> (out_buf), &destLen,
-                        reinterpret_cast<const Bytef *> (buf_str.c_str ()), srcLen) == Z_OK)
-            {
-              write_mat5_tag (os, miCOMPRESSED,
-                              static_cast<octave_idx_type> (destLen));
-
-              os.write (out_buf, destLen);
-            }
-          else
-            {
-              error ("save: error compressing data element");
-              ret = false;
-            }
-        }
-
-      return ret;
-    }
-#endif
-
-  write_mat5_tag (os, miMATRIX, save_mat5_element_length
-                  (tc, name, save_as_floats, mat7_format));
-
-  // array flags subelement
-  write_mat5_tag (os, miUINT32, 8);
-
-  if (tc.is_bool_type ())
-    flags |= 0x0200;
-
-  if (mark_as_global)
-    flags |= 0x0400;
-
-  if (tc.is_complex_scalar () || tc.is_complex_matrix ())
-    flags |= 0x0800;
-
-  if (tc.is_string ())
-    flags |= MAT_FILE_CHAR_CLASS;
-  else if (cname == "int8")
-    flags |= MAT_FILE_INT8_CLASS;
-  else if (cname == "int16")
-    flags |= MAT_FILE_INT16_CLASS;
-  else if (cname == "int32")
-    flags |= MAT_FILE_INT32_CLASS;
-  else if (cname == "int64")
-    flags |= MAT_FILE_INT64_CLASS;
-  else if (cname == "uint8" || tc.is_bool_type ())
-    flags |= MAT_FILE_UINT8_CLASS;
-  else if (cname == "uint16")
-    flags |= MAT_FILE_UINT16_CLASS;
-  else if (cname == "uint32")
-    flags |= MAT_FILE_UINT32_CLASS;
-  else if (cname == "uint64")
-    flags |= MAT_FILE_UINT64_CLASS;
-  else if (tc.is_sparse_type ())
-    flags |= MAT_FILE_SPARSE_CLASS;
-  else if (tc.is_real_scalar () || tc.is_real_matrix () || tc.is_range ()
-           || tc.is_complex_scalar () || tc.is_complex_matrix ())
-    {
-      if (tc.is_single_type ())
-        flags |= MAT_FILE_SINGLE_CLASS;
-      else
-        flags |= MAT_FILE_DOUBLE_CLASS;
-    }
-  else if (tc.is_map ())
-    flags |= MAT_FILE_STRUCT_CLASS;
-  else if (tc.is_cell ())
-    flags |= MAT_FILE_CELL_CLASS;
-  else if (tc.is_inline_function () || tc.is_object ())
-    flags |= MAT_FILE_OBJECT_CLASS;
-  else
-    {
-      gripe_wrong_type_arg ("save", tc, false);
-      goto error_cleanup;
-    }
-
-  os.write (reinterpret_cast<char *> (&flags), 4);
-  os.write (reinterpret_cast<char *> (&nnz_32), 4);
-
-  write_mat5_tag (os, miINT32, dim_len);
-
-  for (int i = 0; i < nd; i++)
-    {
-      int32_t n = dv(i);
-      os.write (reinterpret_cast<char *> (&n), 4);
-    }
-
-  if (PAD (dim_len) > dim_len)
-    {
-      static char buf[9]="\x00\x00\x00\x00\x00\x00\x00\x00";
-      os.write (buf, PAD (dim_len) - dim_len);
-    }
-
-  // array name subelement
-  {
-    size_t namelen = name.length ();
-
-    if (namelen > max_namelen)
-      namelen = max_namelen; // only 31 or 63 char names permitted in mat file
-
-    int paddedlength = PAD (namelen);
-
-    write_mat5_tag (os, miINT8, namelen);
-    OCTAVE_LOCAL_BUFFER (char, paddedname, paddedlength);
-    memset (paddedname, 0, paddedlength);
-    strncpy (paddedname, name.c_str (), namelen);
-    os.write (paddedname, paddedlength);
-  }
-
-  // data element
-  if (tc.is_string ())
-    {
-      charNDArray chm = tc.char_array_value ();
-      octave_idx_type nel = chm.numel ();
-      octave_idx_type len = nel*2;
-      octave_idx_type paddedlength = PAD (len);
-
-      OCTAVE_LOCAL_BUFFER (int16_t, buf, nel+3);
-      write_mat5_tag (os, miUINT16, len);
-
-      const char *s = chm.data ();
-
-      for (octave_idx_type i = 0; i < nel; i++)
-        buf[i] = *s++ & 0x00FF;
-
-      os.write (reinterpret_cast<char *> (buf), len);
-
-      if (paddedlength > len)
-        {
-          static char padbuf[9]="\x00\x00\x00\x00\x00\x00\x00\x00";
-          os.write (padbuf, paddedlength - len);
-        }
-    }
-  else if (tc.is_sparse_type ())
-    {
-      if (tc.is_complex_type ())
-        {
-          const SparseComplexMatrix m = tc.sparse_complex_matrix_value ();
-          octave_idx_type nnz = m.nnz ();
-          octave_idx_type nc = m.cols ();
-
-          write_mat5_sparse_index_vector (os, m.ridx (), nnz);
-          write_mat5_sparse_index_vector (os, m.cidx (), nc + 1);
-
-          NDArray buf (dim_vector (nnz, 1));
-
-          for (octave_idx_type i = 0; i < nnz; i++)
-            buf (i) = std::real (m.data (i));
-
-          write_mat5_array (os, buf, save_as_floats);
-
-          for (octave_idx_type i = 0; i < nnz; i++)
-            buf (i) = std::imag (m.data (i));
-
-          write_mat5_array (os, buf, save_as_floats);
-        }
-      else
-        {
-          const SparseMatrix m = tc.sparse_matrix_value ();
-          octave_idx_type nnz = m.nnz ();
-          octave_idx_type nc = m.cols ();
-
-          write_mat5_sparse_index_vector (os, m.ridx (), nnz);
-          write_mat5_sparse_index_vector (os, m.cidx (), nc + 1);
-
-          // FIXME
-          // Is there a way to easily do without this buffer
-          NDArray buf (dim_vector (nnz, 1));
-
-          for (int i = 0; i < nnz; i++)
-            buf (i) = m.data (i);
-
-          write_mat5_array (os, buf, save_as_floats);
-        }
-    }
-  else if (cname == "int8")
-    {
-      int8NDArray m = tc.int8_array_value ();
-
-      write_mat5_integer_data (os, m.fortran_vec (), -1, m.numel ());
-    }
-  else if (cname == "int16")
-    {
-      int16NDArray m = tc.int16_array_value ();
-
-      write_mat5_integer_data (os, m.fortran_vec (), -2, m.numel ());
-    }
-  else if (cname == "int32")
-    {
-      int32NDArray m = tc.int32_array_value ();
-
-      write_mat5_integer_data (os, m.fortran_vec (), -4, m.numel ());
-    }
-  else if (cname == "int64")
-    {
-      int64NDArray m = tc.int64_array_value ();
-
-      write_mat5_integer_data (os, m.fortran_vec (), -8, m.numel ());
-    }
-  else if (cname == "uint8")
-    {
-      uint8NDArray m = tc.uint8_array_value ();
-
-      write_mat5_integer_data (os, m.fortran_vec (), 1, m.numel ());
-    }
-  else if (cname == "uint16")
-    {
-      uint16NDArray m = tc.uint16_array_value ();
-
-      write_mat5_integer_data (os, m.fortran_vec (), 2, m.numel ());
-    }
-  else if (cname == "uint32")
-    {
-      uint32NDArray m = tc.uint32_array_value ();
-
-      write_mat5_integer_data (os, m.fortran_vec (), 4, m.numel ());
-    }
-  else if (cname == "uint64")
-    {
-      uint64NDArray m = tc.uint64_array_value ();
-
-      write_mat5_integer_data (os, m.fortran_vec (), 8, m.numel ());
-    }
-  else if (tc.is_bool_type ())
-    {
-      uint8NDArray m (tc.bool_array_value ());
-
-      write_mat5_integer_data (os, m.fortran_vec (), 1, m.numel ());
-    }
-  else if (tc.is_real_scalar () || tc.is_real_matrix () || tc.is_range ())
-    {
-      if (tc.is_single_type ())
-        {
-          FloatNDArray m = tc.float_array_value ();
-
-          write_mat5_array (os, m, save_as_floats);
-        }
-      else
-        {
-          NDArray m = tc.array_value ();
-
-          write_mat5_array (os, m, save_as_floats);
-        }
-    }
-  else if (tc.is_cell ())
-    {
-      Cell cell = tc.cell_value ();
-
-      if (! write_mat5_cell_array (os, cell, mark_as_global, save_as_floats))
-        goto error_cleanup;
-    }
-  else if (tc.is_complex_scalar () || tc.is_complex_matrix ())
-    {
-      if (tc.is_single_type ())
-        {
-          FloatComplexNDArray m_cmplx = tc.float_complex_array_value ();
-
-          write_mat5_array (os, ::real (m_cmplx), save_as_floats);
-          write_mat5_array (os, ::imag (m_cmplx), save_as_floats);
-        }
-      else
-        {
-          ComplexNDArray m_cmplx = tc.complex_array_value ();
-
-          write_mat5_array (os, ::real (m_cmplx), save_as_floats);
-          write_mat5_array (os, ::imag (m_cmplx), save_as_floats);
-        }
-    }
-  else if (tc.is_map () || tc.is_inline_function () || tc.is_object ())
-    {
-      if (tc.is_inline_function () || tc.is_object ())
-        {
-          std::string classname = tc.is_object () ? tc.class_name () : "inline";
-          size_t namelen = classname.length ();
-
-          if (namelen > max_namelen)
-            namelen = max_namelen; // only 31 or 63 char names permitted
-
-          int paddedlength = PAD (namelen);
-
-          write_mat5_tag (os, miINT8, namelen);
-          OCTAVE_LOCAL_BUFFER (char, paddedname, paddedlength);
-          memset (paddedname, 0, paddedlength);
-          strncpy (paddedname, classname.c_str (), namelen);
-          os.write (paddedname, paddedlength);
-        }
-
-      Octave_map m;
-
-      if (tc.is_object () &&
-          load_path::find_method (tc.class_name (), "saveobj") != std::string ())
-        {
-          octave_value_list tmp = feval ("saveobj", tc, 1);
-          if (! error_state)
-            m = tmp(0).map_value ();
-          else
-            goto error_cleanup;
-        }
-      else
-        m = tc.map_value ();
-
-      // an Octave structure */
-      // recursively write each element of the structure
-      {
-        char buf[64];
-        int32_t maxfieldnamelength = max_namelen + 1;
-
-        octave_idx_type nf = m.nfields ();
-
-        write_mat5_tag (os, miINT32, 4);
-        os.write (reinterpret_cast<char *> (&maxfieldnamelength), 4);
-        write_mat5_tag (os, miINT8, nf*maxfieldnamelength);
-
-        // Iterating over the list of keys will preserve the order of
-        // the fields.
-        string_vector keys = m.keys ();
-
-        for (octave_idx_type i = 0; i < nf; i++)
-          {
-            std::string key = keys(i);
-
-            // write the name of each element
-            memset (buf, 0, max_namelen + 1);
-            // only 31 or 63 char names permitted
-            strncpy (buf, key.c_str (), max_namelen);
-            os.write (buf, max_namelen + 1);
-          }
-
-        octave_idx_type len = m.numel ();
-
-        // Create temporary copy of structure contents to avoid
-        // multiple calls of the contents method.
-        std::vector<const octave_value *> elts (nf);
-        for (octave_idx_type i = 0; i < nf; i++)
-          elts[i] = m.contents (keys(i)).data ();
-
-        for (octave_idx_type j = 0; j < len; j++)
-          {
-            // write the data of each element
-
-            // Iterating over the list of keys will preserve the order
-            // of the fields.
-            for (octave_idx_type i = 0; i < nf; i++)
-              {
-                bool retval2 = save_mat5_binary_element (os, elts[i][j], "",
-                                                         mark_as_global,
-                                                         false,
-                                                         save_as_floats);
-                if (! retval2)
-                  goto error_cleanup;
-              }
-          }
-      }
-    }
-  else
-    gripe_wrong_type_arg ("save", tc, false);
-
- skip_to_next:
-  return true;
-
- error_cleanup:
-  error ("save: error while writing `%s' to MAT file", name.c_str ());
-
-  return false;
-}
--- a/src/ls-mat5.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-/*
-
-Copyright (C) 2003-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#if !defined (octave_ls_mat5_h)
-#define octave_ls_mat5_h 1
-
-enum mat5_data_type
-  {
-    miINT8 = 1,                 // 8 bit signed
-    miUINT8,                    // 8 bit unsigned
-    miINT16,                    // 16 bit signed
-    miUINT16,                   // 16 bit unsigned
-    miINT32,                    // 32 bit signed
-    miUINT32,                   // 32 bit unsigned
-    miSINGLE,                   // IEEE 754 single precision float
-    miRESERVE1,
-    miDOUBLE,                   // IEEE 754 double precision float
-    miRESERVE2,
-    miRESERVE3,
-    miINT64,                    // 64 bit signed
-    miUINT64,                   // 64 bit unsigned
-    miMATRIX,                   // MATLAB array
-    miCOMPRESSED,               // Compressed data
-    miUTF8,                     // Unicode UTF-8 Encoded Character Data
-    miUTF16,                    // Unicode UTF-16 Encoded Character Data
-    miUTF32                     // Unicode UTF-32 Encoded Character Data
-  };
-
-extern int
-read_mat5_binary_file_header (std::istream& is, bool& swap,
-                              bool quiet = false,
-                              const std::string& filename = std::string ());
-extern std::string
-read_mat5_binary_element (std::istream& is, const std::string& filename,
-                          bool swap, bool& global, octave_value& tc);
-extern bool
-save_mat5_binary_element (std::ostream& os,
-                          const octave_value& tc, const std::string& name,
-                          bool mark_as_global, bool mat7_format,
-                          bool save_as_floats, bool compressing = false);
-
-#endif
--- a/src/ls-oct-binary.cc	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,307 +0,0 @@
-/*
-
-Copyright (C) 1996-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <cfloat>
-#include <cstring>
-#include <cctype>
-
-#include <fstream>
-#include <iomanip>
-#include <iostream>
-#include <string>
-#include <vector>
-
-#include "byte-swap.h"
-#include "data-conv.h"
-#include "file-ops.h"
-#include "glob-match.h"
-#include "lo-mappers.h"
-#include "mach-info.h"
-#include "oct-env.h"
-#include "oct-time.h"
-#include "quit.h"
-#include "str-vec.h"
-#include "oct-locbuf.h"
-
-#include "Cell.h"
-#include "defun.h"
-#include "error.h"
-#include "gripes.h"
-#include "load-save.h"
-#include "oct-obj.h"
-#include "oct-map.h"
-#include "ov-cell.h"
-#include "pager.h"
-#include "pt-exp.h"
-#include "sysdep.h"
-#include "unwind-prot.h"
-#include "utils.h"
-#include "variables.h"
-#include "version.h"
-#include "dMatrix.h"
-
-#include "ls-utils.h"
-#include "ls-oct-binary.h"
-
-// Extract one value (scalar, matrix, string, etc.) from stream IS and
-// place it in TC, returning the name of the variable.  If the value
-// is tagged as global in the file, return TRUE in GLOBAL.  If SWAP
-// is TRUE, swap bytes after reading.
-//
-// The data is expected to be in the following format:
-//
-// Header (one per file):
-// =====================
-//
-//   object               type            bytes
-//   ------               ----            -----
-//   magic number         string             10
-//
-//   float format         integer             1
-//
-//
-// Data (one set for each item):
-// ============================
-//
-//   object               type            bytes
-//   ------               ----            -----
-//   name_length          integer             4
-//
-//   name                 string    name_length
-//
-//   doc_length           integer             4
-//
-//   doc                  string     doc_length
-//
-//   global flag          integer             1
-//
-//   data type            char                1
-//
-// In general "data type" is 255, and in that case the next arguments
-// in the data set are
-//
-//   object               type            bytes
-//   ------               ----            -----
-//   type_length          integer             4
-//
-//   type                 string    type_length
-//
-// The string "type" is then used with octave_value_typeinfo::lookup_type
-// to create an octave_value of the correct type. The specific load/save
-// function is then called.
-//
-// For backward compatiablity "data type" can also be a value between 1
-// and 7, where this defines a hardcoded octave_value of the type
-//
-//   data type                  octave_value
-//   ---------                  ------------
-//   1                          scalar
-//   2                          matrix
-//   3                          complex scalar
-//   4                          complex matrix
-//   5                          string   (old style storage)
-//   6                          range
-//   7                          string
-//
-// Except for "data type" equal 5 that requires special treatment, these
-// old style "data type" value also cause the specific load/save functions
-// to be called. FILENAME is used for error messages.
-
-std::string
-read_binary_data (std::istream& is, bool swap,
-                  oct_mach_info::float_format fmt,
-                  const std::string& filename, bool& global,
-                  octave_value& tc, std::string& doc)
-{
-  std::string retval;
-
-  unsigned char tmp = 0;
-
-  int32_t name_len = 0;
-  int32_t doc_len = 0;
-
-  doc.resize (0);
-
-  // We expect to fail here, at the beginning of a record, so not
-  // being able to read another name should not result in an error.
-
-  is.read (reinterpret_cast<char *> (&name_len), 4);
-  if (! is)
-    return retval;
-  if (swap)
-    swap_bytes<4> (&name_len);
-
-  {
-    OCTAVE_LOCAL_BUFFER (char, name, name_len+1);
-    name[name_len] = '\0';
-    if (! is.read (reinterpret_cast<char *> (name), name_len))
-      goto data_read_error;
-    retval = name;
-  }
-
-  is.read (reinterpret_cast<char *> (&doc_len), 4);
-  if (! is)
-    goto data_read_error;
-  if (swap)
-    swap_bytes<4> (&doc_len);
-
-  {
-    OCTAVE_LOCAL_BUFFER (char, tdoc, doc_len+1);
-    tdoc[doc_len] = '\0';
-    if (! is.read (reinterpret_cast<char *> (tdoc), doc_len))
-      goto data_read_error;
-    doc = tdoc;
-  }
-
-  if (! is.read (reinterpret_cast<char *> (&tmp), 1))
-    goto data_read_error;
-  global = tmp ? 1 : 0;
-
-  tmp = 0;
-  if (! is.read (reinterpret_cast<char *> (&tmp), 1))
-    goto data_read_error;
-
-  // All cases except 255 kept for backwards compatibility
-  switch (tmp)
-    {
-    case 1:
-      tc = octave_value_typeinfo::lookup_type ("scalar");
-      break;
-
-    case 2:
-      tc = octave_value_typeinfo::lookup_type ("matrix");
-      break;
-
-    case 3:
-      tc = octave_value_typeinfo::lookup_type ("complex scalar");
-      break;
-
-    case 4:
-      tc = octave_value_typeinfo::lookup_type ("complex matrix");
-      break;
-
-    case 5:
-      {
-        // FIXMEX
-        // This is cruft, since its for a save type that is old. Maybe
-        // this is taking backward compatability too far!!
-        int32_t len;
-        if (! is.read (reinterpret_cast<char *> (&len), 4))
-          goto data_read_error;
-        if (swap)
-          swap_bytes<4> (&len);
-        OCTAVE_LOCAL_BUFFER (char, s, len+1);
-        if (! is.read (reinterpret_cast<char *> (s), len))
-          goto data_read_error;
-        s[len] = '\0';
-        tc = s;
-
-        // Early return, since don't want rest of this function
-        return retval;
-      }
-      break;
-
-    case 6:
-      tc = octave_value_typeinfo::lookup_type ("range");
-      break;
-
-    case 7:
-      tc = octave_value_typeinfo::lookup_type ("string");
-      break;
-
-    case 255:
-      {
-        // Read the saved variable type
-        int32_t len;
-        if (! is.read (reinterpret_cast<char *> (&len), 4))
-          goto data_read_error;
-        if (swap)
-          swap_bytes<4> (&len);
-        OCTAVE_LOCAL_BUFFER (char, s, len+1);
-        if (! is.read (s, len))
-          goto data_read_error;
-        s[len] = '\0';
-        std::string typ = s;
-        tc = octave_value_typeinfo::lookup_type (typ);
-      }
-      break;
-    default:
-      goto data_read_error;
-      break;
-    }
-
-  if (!tc.load_binary (is, swap, fmt))
-    {
-    data_read_error:
-      error ("load: trouble reading binary file `%s'", filename.c_str ());
-    }
-
-  return retval;
-}
-
-// Save the data from TC along with the corresponding NAME, help
-// string DOC, and global flag MARK_AS_GLOBAL on stream OS in the
-// binary format described above for read_binary_data.
-
-bool
-save_binary_data (std::ostream& os, const octave_value& tc,
-                  const std::string& name, const std::string& doc,
-                  bool mark_as_global, bool save_as_floats)
-{
-  int32_t name_len = name.length ();
-
-  os.write (reinterpret_cast<char *> (&name_len), 4);
-  os << name;
-
-  int32_t doc_len = doc.length ();
-
-  os.write (reinterpret_cast<char *> (&doc_len), 4);
-  os << doc;
-
-  unsigned char tmp;
-
-  tmp = mark_as_global;
-  os.write (reinterpret_cast<char *> (&tmp), 1);
-
-  // 255 flags the new binary format
-  tmp = 255;
-  os.write (reinterpret_cast<char *> (&tmp), 1);
-
-  // Write the string corresponding to the octave_value type
-  std::string typ = tc.type_name ();
-  int32_t len = typ.length ();
-  os.write (reinterpret_cast<char *> (&len), 4);
-  const char *btmp = typ.data ();
-  os.write (btmp, len);
-
-  // The octave_value of tc is const. Make a copy...
-  octave_value val = tc;
-
-  // Call specific save function
-  bool success = val.save_binary (os, save_as_floats);
-
-  return (os && success);
-}
--- a/src/ls-oct-binary.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-/*
-
-Copyright (C) 2003-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#if !defined (octave_ls_oct_binary_h)
-#define octave_ls_oct_binary_h 1
-
-extern OCTINTERP_API bool
-save_binary_data (std::ostream& os, const octave_value& tc,
-                  const std::string& name, const std::string& doc,
-                  bool mark_as_global, bool save_as_floats);
-
-extern OCTINTERP_API std::string
-read_binary_data (std::istream& is, bool swap,
-                  oct_mach_info::float_format fmt,
-                  const std::string& filename, bool& global,
-                  octave_value& tc, std::string& doc);
-
-#endif
--- a/src/ls-utils.cc	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,88 +0,0 @@
-/*
-
-Copyright (C) 2003-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "data-conv.h"
-
-#include "ls-utils.h"
-
-// MAX_VAL and MIN_VAL are assumed to have integral values even though
-// they are stored in doubles.
-
-save_type
-get_save_type (double /* max_val */, double /* min_val */)
-{
-  save_type st = LS_DOUBLE;
-
-  // Matlab doesn't seem to load the UINT32 type correctly, so let's
-  // avoid it (and the other unsigned types, even though they may not
-  // have the same problem.  And apparently, there are problems with
-  // other smaller types as well.  If we avoid them all, then maybe we
-  // will avoid problems.  Unfortunately, we won't be able to save
-  // space...
-
-  //  if (max_val < 256 && min_val > -1)
-  //    st = LS_U_CHAR;
-  //  else if (max_val < 65536 && min_val > -1)
-  //    st = LS_U_SHORT;
-  //  else if (max_val < 4294967295UL && min_val > -1)
-  //    st = LS_U_INT;
-  //  else if (max_val < 128 && min_val >= -128)
-  //    st = LS_CHAR;
-  //  else if (max_val < 32768 && min_val >= -32768)
-  //    st = LS_SHORT;
-  //  else if (max_val <= 2147483647L && min_val >= -2147483647L)
-  //    st = LS_INT;
-
-  return st;
-}
-
-save_type
-get_save_type (float /* max_val */, float /* min_val */)
-{
-  save_type st = LS_FLOAT;
-
-  // Matlab doesn't seem to load the UINT32 type correctly, so let's
-  // avoid it (and the other unsigned types, even though they may not
-  // have the same problem.  And apparently, there are problems with
-  // other smaller types as well.  If we avoid them all, then maybe we
-  // will avoid problems.  Unfortunately, we won't be able to save
-  // space...
-
-  //  if (max_val < 256 && min_val > -1)
-  //    st = LS_U_CHAR;
-  //  else if (max_val < 65536 && min_val > -1)
-  //    st = LS_U_SHORT;
-  //  else if (max_val < 4294967295UL && min_val > -1)
-  //    st = LS_U_INT;
-  //  else if (max_val < 128 && min_val >= -128)
-  //    st = LS_CHAR;
-  //  else if (max_val < 32768 && min_val >= -32768)
-  //    st = LS_SHORT;
-  //  else if (max_val <= 2147483647L && min_val >= -2147483647L)
-  //    st = LS_INT;
-
-  return st;
-}
--- a/src/ls-utils.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-/*
-
-Copyright (C) 2003-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#if !defined (octave_ls_utils_h)
-#define octave_ls_utils 1
-
-extern save_type
-get_save_type (double max_val, double min_val);
-
-extern save_type
-get_save_type (float max_val, float min_val);
-
-#endif
--- a/src/matherr.c	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/*
-
-Copyright (C) 1997-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#if defined (EXCEPTION_IN_MATH)
-
-#include "lo-math.h"
-
-int
-matherr (struct exception *x)
-{
-  /* Possibly print our own message someday.  Should probably be
-     user-switchable. */
-
-  switch (x->type)
-    {
-    case DOMAIN:
-    case SING:
-    case OVERFLOW:
-    case UNDERFLOW:
-    case TLOSS:
-    case PLOSS:
-    default:
-      break;
-    }
-
-  /* But don't print the system message. */
-
-  return 1;
-}
-#endif
--- a/src/mex.cc	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3540 +0,0 @@
-/*
-
-Copyright (C) 2006-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#include <config.h>
-
-#include <cfloat>
-#include <csetjmp>
-#include <cstdarg>
-#include <cstdlib>
-#include <cstring>
-#include <cctype>
-
-#include <set>
-
-#include "f77-fcn.h"
-#include "lo-ieee.h"
-#include "oct-locbuf.h"
-
-// mxArray must be declared as a class before including mexproto.h.
-class mxArray;
-#include "Cell.h"
-#include "mexproto.h"
-#include "oct-map.h"
-#include "oct-obj.h"
-#include "ov.h"
-#include "ov-mex-fcn.h"
-#include "ov-usr-fcn.h"
-#include "pager.h"
-#include "parse.h"
-#include "toplev.h"
-#include "unwind-prot.h"
-#include "utils.h"
-#include "variables.h"
-#include "graphics.h"
-
-// #define DEBUG 1
-
-static void
-xfree (void *ptr)
-{
-  ::free (ptr);
-}
-
-static mwSize
-max_str_len (mwSize m, const char **str)
-{
-  int max_len = 0;
-
-  for (mwSize i = 0; i < m; i++)
-    {
-      mwSize tmp = strlen (str[i]);
-
-      if (tmp > max_len)
-        max_len = tmp;
-    }
-
-  return max_len;
-}
-
-static int
-valid_key (const char *key)
-{
-  int retval = 0;
-
-  int nel = strlen (key);
-
-  if (nel > 0)
-    {
-      if (isalpha (key[0]))
-        {
-          for (int i = 1; i < nel; i++)
-            {
-              if (! (isalnum (key[i]) || key[i] == '_'))
-                goto done;
-            }
-
-          retval = 1;
-        }
-    }
-
- done:
-
-  return retval;
-}
-
-// ------------------------------------------------------------------
-
-// A class to provide the default implemenation of some of the virtual
-// functions declared in the mxArray class.
-
-class mxArray_base : public mxArray
-{
-protected:
-
-  mxArray_base (void) : mxArray (xmxArray ()) { }
-
-public:
-
-  mxArray *dup (void) const = 0;
-
-  ~mxArray_base (void) { }
-
-  bool is_octave_value (void) const { return false; }
-
-  int is_cell (void) const = 0;
-
-  int is_char (void) const = 0;
-
-  int is_class (const char *name_arg) const
-  {
-    int retval = 0;
-
-    const char *cname = get_class_name ();
-
-    if (cname && name_arg)
-      retval = ! strcmp (cname, name_arg);
-
-    return retval;
-  }
-
-  int is_complex (void) const = 0;
-
-  int is_double (void) const = 0;
-
-  int is_function_handle (void) const = 0;
-
-  int is_int16 (void) const = 0;
-
-  int is_int32 (void) const = 0;
-
-  int is_int64 (void) const = 0;
-
-  int is_int8 (void) const = 0;
-
-  int is_logical (void) const = 0;
-
-  int is_numeric (void) const = 0;
-
-  int is_single (void) const = 0;
-
-  int is_sparse (void) const = 0;
-
-  int is_struct (void) const = 0;
-
-  int is_uint16 (void) const = 0;
-
-  int is_uint32 (void) const = 0;
-
-  int is_uint64 (void) const = 0;
-
-  int is_uint8 (void) const = 0;
-
-  int is_logical_scalar (void) const
-  {
-    return is_logical () && get_number_of_elements () == 1;
-  }
-
-  int is_logical_scalar_true (void) const = 0;
-
-  mwSize get_m (void) const = 0;
-
-  mwSize get_n (void) const = 0;
-
-  mwSize *get_dimensions (void) const = 0;
-
-  mwSize get_number_of_dimensions (void) const = 0;
-
-  void set_m (mwSize m) = 0;
-
-  void set_n (mwSize n) = 0;
-
-  void set_dimensions (mwSize *dims_arg, mwSize ndims_arg) = 0;
-
-  mwSize get_number_of_elements (void) const = 0;
-
-  int is_empty (void) const = 0;
-
-  mxClassID get_class_id (void) const = 0;
-
-  const char *get_class_name (void) const = 0;
-
-  void set_class_name (const char *name_arg) = 0;
-
-  mxArray *get_cell (mwIndex /*idx*/) const
-  {
-    invalid_type_error ();
-    return 0;
-  }
-
-  void set_cell (mwIndex idx, mxArray *val) = 0;
-
-  double get_scalar (void) const = 0;
-
-  void *get_data (void) const = 0;
-
-  void *get_imag_data (void) const = 0;
-
-  void set_data (void *pr) = 0;
-
-  void set_imag_data (void *pi) = 0;
-
-  mwIndex *get_ir (void) const = 0;
-
-  mwIndex *get_jc (void) const = 0;
-
-  mwSize get_nzmax (void) const = 0;
-
-  void set_ir (mwIndex *ir) = 0;
-
-  void set_jc (mwIndex *jc) = 0;
-
-  void set_nzmax (mwSize nzmax) = 0;
-
-  int add_field (const char *key) = 0;
-
-  void remove_field (int key_num) = 0;
-
-  mxArray *get_field_by_number (mwIndex index, int key_num) const = 0;
-
-  void set_field_by_number (mwIndex index, int key_num, mxArray *val) = 0;
-
-  int get_number_of_fields (void) const = 0;
-
-  const char *get_field_name_by_number (int key_num) const = 0;
-
-  int get_field_number (const char *key) const = 0;
-
-  int get_string (char *buf, mwSize buflen) const = 0;
-
-  char *array_to_string (void) const = 0;
-
-  mwIndex calc_single_subscript (mwSize nsubs, mwIndex *subs) const = 0;
-
-  size_t get_element_size (void) const = 0;
-
-  bool mutation_needed (void) const { return false; }
-
-  mxArray *mutate (void) const { return 0; }
-
-protected:
-
-  octave_value as_octave_value (void) const = 0;
-
-  mxArray_base (const mxArray_base&) : mxArray (xmxArray ()) { }
-
-  void invalid_type_error (void) const
-  {
-    error ("invalid type for operation");
-  }
-
-  void error (const char *msg) const
-  {
-    // FIXME
-    ::error ("%s", msg);
-  }
-};
-
-static mwIndex
-calc_single_subscript_internal (mwSize ndims, const mwSize *dims,
-                                mwSize nsubs, const mwIndex *subs)
-{
-  mwIndex retval = 0;
-
-  switch (nsubs)
-    {
-    case 0:
-      break;
-
-    case 1:
-      retval = subs[0];
-      break;
-
-    default:
-      {
-        // Both nsubs and ndims should be at least 2 here.
-
-        mwSize n = nsubs <= ndims ? nsubs : ndims;
-
-        retval = subs[--n];
-
-        while (--n >= 0)
-          retval = dims[n] * retval + subs[n];
-      }
-      break;
-    }
-
-  return retval;
-}
-
-// The object that handles values pass to MEX files from Octave.  Some
-// methods in this class may set mutate_flag to TRUE to tell the
-// mxArray class to convert to the Matlab-style representation and
-// then invoke the method on that object instead (for example, getting
-// a pointer to real or imaginary data from a complex object requires
-// a mutation but getting a pointer to real data from a real object
-// does not).  Changing the representation causes a copy so we try to
-// avoid it unless it is really necessary.  Once the conversion
-// happens, we delete this representation, so the conversion can only
-// happen once per call to a MEX file.
-
-static inline void *maybe_mark_foreign (void *ptr);
-
-class mxArray_octave_value : public mxArray_base
-{
-public:
-
-  mxArray_octave_value (const octave_value& ov)
-    : mxArray_base (), val (ov), mutate_flag (false),
-      id (mxUNKNOWN_CLASS), class_name (0), ndims (-1), dims (0) { }
-
-  mxArray *dup (void) const
-  {
-    mxArray *retval = val.as_mxArray ();
-
-    if (! retval)
-      retval = new mxArray_octave_value (*this);
-
-    return retval;
-  }
-
-  ~mxArray_octave_value (void)
-  {
-    mxFree (class_name);
-    mxFree (dims);
-  }
-
-  bool is_octave_value (void) const { return true; }
-
-  int is_cell (void) const { return val.is_cell (); }
-
-  int is_char (void) const { return val.is_string (); }
-
-  int is_complex (void) const { return val.is_complex_type (); }
-
-  int is_double (void) const { return val.is_double_type (); }
-
-  int is_function_handle (void) const { return val.is_function_handle (); }
-
-  int is_int16 (void) const { return val.is_int16_type (); }
-
-  int is_int32 (void) const { return val.is_int32_type (); }
-
-  int is_int64 (void) const { return val.is_int64_type (); }
-
-  int is_int8 (void) const { return val.is_int8_type (); }
-
-  int is_logical (void) const { return val.is_bool_type (); }
-
-  int is_numeric (void) const { return val.is_numeric_type (); }
-
-  int is_single (void) const { return val.is_single_type (); }
-
-  int is_sparse (void) const { return val.is_sparse_type (); }
-
-  int is_struct (void) const { return val.is_map (); }
-
-  int is_uint16 (void) const { return val.is_uint16_type (); }
-
-  int is_uint32 (void) const { return val.is_uint32_type (); }
-
-  int is_uint64 (void) const { return val.is_uint64_type (); }
-
-  int is_uint8 (void) const { return val.is_uint8_type (); }
-
-  int is_range (void) const { return val.is_range (); }
-
-  int is_real_type (void) const { return val.is_real_type (); }
-
-  int is_logical_scalar_true (void) const
-  {
-    return (is_logical_scalar () && val.is_true ());
-  }
-
-  mwSize get_m (void) const { return val.rows (); }
-
-  mwSize get_n (void) const
-  {
-    mwSize n = 1;
-
-    // Force dims and ndims to be cached.
-    get_dimensions ();
-
-    for (mwIndex i = ndims - 1; i > 0; i--)
-      n *= dims[i];
-
-    return n;
-  }
-
-  mwSize *get_dimensions (void) const
-  {
-    if (! dims)
-      {
-        ndims = val.ndims ();
-
-        dims = static_cast<mwSize *> (malloc (ndims * sizeof (mwSize)));
-
-        dim_vector dv = val.dims ();
-
-        for (mwIndex i = 0; i < ndims; i++)
-          dims[i] = dv(i);
-      }
-
-    return dims;
-  }
-
-  mwSize get_number_of_dimensions (void) const
-  {
-    // Force dims and ndims to be cached.
-    get_dimensions ();
-
-    return ndims;
-  }
-
-  void set_m (mwSize /*m*/) { request_mutation (); }
-
-  void set_n (mwSize /*n*/) { request_mutation (); }
-
-  void set_dimensions (mwSize */*dims_arg*/, mwSize /*ndims_arg*/)
-  {
-    request_mutation ();
-  }
-
-  mwSize get_number_of_elements (void) const { return val.numel (); }
-
-  int is_empty (void) const { return val.is_empty (); }
-
-  mxClassID get_class_id (void) const
-  {
-    id = mxUNKNOWN_CLASS;
-
-    std::string cn = val.class_name ();
-
-    if (cn == "cell")
-      id = mxCELL_CLASS;
-    else if (cn == "struct")
-      id = mxSTRUCT_CLASS;
-    else if (cn == "logical")
-      id = mxLOGICAL_CLASS;
-    else if (cn == "char")
-      id = mxCHAR_CLASS;
-    else if (cn == "double")
-      id = mxDOUBLE_CLASS;
-    else if (cn == "single")
-      id = mxSINGLE_CLASS;
-    else if (cn == "int8")
-      id = mxINT8_CLASS;
-    else if (cn == "uint8")
-      id = mxUINT8_CLASS;
-    else if (cn == "int16")
-      id = mxINT16_CLASS;
-    else if (cn == "uint16")
-      id = mxUINT16_CLASS;
-    else if (cn == "int32")
-      id = mxINT32_CLASS;
-    else if (cn == "uint32")
-      id = mxUINT32_CLASS;
-    else if (cn == "int64")
-      id = mxINT64_CLASS;
-    else if (cn == "uint64")
-      id = mxUINT64_CLASS;
-    else if (cn == "function_handle")
-      id = mxFUNCTION_CLASS;
-
-    return id;
-  }
-
-  const char *get_class_name (void) const
-  {
-    if (! class_name)
-      {
-        std::string s = val.class_name ();
-        class_name = strsave (s.c_str ());
-      }
-
-    return class_name;
-  }
-
-  // Not allowed.
-  void set_class_name (const char */*name_arg*/) { request_mutation (); }
-
-  mxArray *get_cell (mwIndex /*idx*/) const
-  {
-    request_mutation ();
-    return 0;
-  }
-
-  // Not allowed.
-  void set_cell (mwIndex /*idx*/, mxArray */*val*/) { request_mutation (); }
-
-  double get_scalar (void) const { return val.scalar_value (true); }
-
-  void *get_data (void) const
-  {
-    void *retval = val.mex_get_data ();
-
-    if (retval)
-      maybe_mark_foreign (retval);
-    else
-      request_mutation ();
-
-    return retval;
-  }
-
-  void *get_imag_data (void) const
-  {
-    void *retval = 0;
-
-    if (is_numeric () && is_real_type ())
-      retval = 0;
-    else
-      request_mutation ();
-
-    return retval;
-  }
-
-  // Not allowed.
-  void set_data (void */*pr*/) { request_mutation (); }
-
-  // Not allowed.
-  void set_imag_data (void */*pi*/) { request_mutation (); }
-
-  mwIndex *get_ir (void) const
-  {
-    return static_cast<mwIndex *> (maybe_mark_foreign (val.mex_get_ir ()));
-  }
-
-  mwIndex *get_jc (void) const
-  {
-    return static_cast<mwIndex *> (maybe_mark_foreign (val.mex_get_jc ()));
-  }
-
-  mwSize get_nzmax (void) const { return val.nzmax (); }
-
-  // Not allowed.
-  void set_ir (mwIndex */*ir*/) { request_mutation (); }
-
-  // Not allowed.
-  void set_jc (mwIndex */*jc*/) { request_mutation (); }
-
-  // Not allowed.
-  void set_nzmax (mwSize /*nzmax*/) { request_mutation (); }
-
-  // Not allowed.
-  int add_field (const char */*key*/)
-  {
-    request_mutation ();
-    return 0;
-  }
-
-  // Not allowed.
-  void remove_field (int /*key_num*/) { request_mutation (); }
-
-  mxArray *get_field_by_number (mwIndex /*index*/, int /*key_num*/) const
-  {
-    request_mutation ();
-    return 0;
-  }
-
-  // Not allowed.
-  void set_field_by_number (mwIndex /*index*/, int /*key_num*/, mxArray */*val*/)
-  {
-    request_mutation ();
-  }
-
-  int get_number_of_fields (void) const { return val.nfields (); }
-
-  const char *get_field_name_by_number (int /*key_num*/) const
-  {
-    request_mutation ();
-    return 0;
-  }
-
-  int get_field_number (const char */*key*/) const
-  {
-    request_mutation ();
-    return 0;
-  }
-
-  int get_string (char *buf, mwSize buflen) const
-  {
-    int retval = 1;
-
-    mwSize nel = get_number_of_elements ();
-
-    if (val.is_string () && nel < buflen)
-      {
-        charNDArray tmp = val.char_array_value ();
-
-        const char *p = tmp.data ();
-
-        for (mwIndex i = 0; i < nel; i++)
-          buf[i] = p[i];
-
-        buf[nel] = 0;
-
-        retval = 0;
-      }
-
-    return retval;
-  }
-
-  char *array_to_string (void) const
-  {
-    // FIXME -- this is suposed to handle multi-byte character
-    // strings.
-
-    char *buf = 0;
-
-    if (val.is_string ())
-      {
-        mwSize nel = get_number_of_elements ();
-
-        buf = static_cast<char *> (malloc (nel + 1));
-
-        if (buf)
-          {
-            charNDArray tmp = val.char_array_value ();
-
-            const char *p = tmp.data ();
-
-            for (mwIndex i = 0; i < nel; i++)
-              buf[i] = p[i];
-
-            buf[nel] = '\0';
-          }
-      }
-
-    return buf;
-  }
-
-  mwIndex calc_single_subscript (mwSize nsubs, mwIndex *subs) const
-  {
-    // Force ndims, dims to be cached.
-    get_dimensions ();
-
-    return calc_single_subscript_internal (ndims, dims, nsubs, subs);
-  }
-
-  size_t get_element_size (void) const
-  {
-    // Force id to be cached.
-    get_class_id ();
-
-    switch (id)
-      {
-      case mxCELL_CLASS: return sizeof (mxArray *);
-      case mxSTRUCT_CLASS: return sizeof (mxArray *);
-      case mxLOGICAL_CLASS: return sizeof (mxLogical);
-      case mxCHAR_CLASS: return sizeof (mxChar);
-      case mxDOUBLE_CLASS: return sizeof (double);
-      case mxSINGLE_CLASS: return sizeof (float);
-      case mxINT8_CLASS: return 1;
-      case mxUINT8_CLASS: return 1;
-      case mxINT16_CLASS: return 2;
-      case mxUINT16_CLASS: return 2;
-      case mxINT32_CLASS: return 4;
-      case mxUINT32_CLASS: return 4;
-      case mxINT64_CLASS: return 8;
-      case mxUINT64_CLASS: return 8;
-      case mxFUNCTION_CLASS: return 0;
-      default: return 0;
-      }
-  }
-
-  bool mutation_needed (void) const { return mutate_flag; }
-
-  void request_mutation (void) const
-  {
-    if (mutate_flag)
-      panic_impossible ();
-
-    mutate_flag = true;
-  }
-
-  mxArray *mutate (void) const { return val.as_mxArray (); }
-
-protected:
-
-  octave_value as_octave_value (void) const { return val; }
-
-  mxArray_octave_value (const mxArray_octave_value& arg)
-    : mxArray_base (arg), val (arg.val), mutate_flag (arg.mutate_flag),
-      id (arg.id), class_name (strsave (arg.class_name)), ndims (arg.ndims),
-      dims (ndims > 0 ? static_cast<mwSize *> (malloc (ndims * sizeof (mwSize))) : 0)
-  {
-    if (dims)
-      {
-        for (mwIndex i = 0; i < ndims; i++)
-          dims[i] = arg.dims[i];
-      }
-  }
-
-private:
-
-  octave_value val;
-
-  mutable bool mutate_flag;
-
-  // Caching these does not cost much or lead to much duplicated
-  // code.  For other things, we just request mutation to a
-  // Matlab-style mxArray object.
-
-  mutable mxClassID id;
-  mutable char *class_name;
-  mutable mwSize ndims;
-  mutable mwSize *dims;
-
-  // No assignment!  FIXME -- should this be implemented?  Note that we
-  // do have a copy constructor.
-
-  mxArray_octave_value& operator = (const mxArray_octave_value&);
-};
-
-// The base class for the Matlab-style representation, used to handle
-// things that are common to all Matlab-style objects.
-
-class mxArray_matlab : public mxArray_base
-{
-protected:
-
-  mxArray_matlab (mxClassID id_arg = mxUNKNOWN_CLASS)
-    : mxArray_base (), class_name (0), id (id_arg), ndims (0), dims (0) { }
-
-  mxArray_matlab (mxClassID id_arg, mwSize ndims_arg, const mwSize *dims_arg)
-    : mxArray_base (), class_name (0), id (id_arg),
-      ndims (ndims_arg < 2 ? 2 : ndims_arg),
-      dims (static_cast<mwSize *> (malloc (ndims * sizeof (mwSize))))
-  {
-    if (ndims_arg < 2)
-      {
-        dims[0] = 1;
-        dims[1] = 1;
-      }
-
-    for (mwIndex i = 0; i < ndims_arg; i++)
-      dims[i] = dims_arg[i];
-
-    for (mwIndex i = ndims - 1; i > 1; i--)
-      {
-        if (dims[i] == 1)
-          ndims--;
-        else
-          break;
-      }
-  }
-
-  mxArray_matlab (mxClassID id_arg, const dim_vector& dv)
-    : mxArray_base (), class_name (0), id (id_arg),
-      ndims (dv.length ()),
-      dims (static_cast<mwSize *> (malloc (ndims * sizeof (mwSize))))
-  {
-    for (mwIndex i = 0; i < ndims; i++)
-      dims[i] = dv(i);
-
-    for (mwIndex i = ndims - 1; i > 1; i--)
-      {
-        if (dims[i] == 1)
-          ndims--;
-        else
-          break;
-      }
-  }
-
-  mxArray_matlab (mxClassID id_arg, mwSize m, mwSize n)
-    : mxArray_base (), class_name (0), id (id_arg), ndims (2),
-      dims (static_cast<mwSize *> (malloc (ndims * sizeof (mwSize))))
-  {
-    dims[0] = m;
-    dims[1] = n;
-  }
-
-public:
-
-  ~mxArray_matlab (void)
-  {
-    mxFree (class_name);
-    mxFree (dims);
-  }
-
-  int is_cell (void) const { return id == mxCELL_CLASS; }
-
-  int is_char (void) const { return id == mxCHAR_CLASS; }
-
-  int is_complex (void) const { return 0; }
-
-  int is_double (void) const { return id == mxDOUBLE_CLASS; }
-
-  int is_function_handle (void) const { return id == mxFUNCTION_CLASS; }
-
-  int is_int16 (void) const { return id == mxINT16_CLASS; }
-
-  int is_int32 (void) const { return id == mxINT32_CLASS; }
-
-  int is_int64 (void) const { return id == mxINT64_CLASS; }
-
-  int is_int8 (void) const { return id == mxINT8_CLASS; }
-
-  int is_logical (void) const { return id == mxLOGICAL_CLASS; }
-
-  int is_numeric (void) const
-  {
-    return (id == mxDOUBLE_CLASS || id == mxSINGLE_CLASS
-            || id == mxINT8_CLASS || id == mxUINT8_CLASS
-            || id == mxINT16_CLASS || id == mxUINT16_CLASS
-            || id == mxINT32_CLASS || id == mxUINT32_CLASS
-            || id == mxINT64_CLASS || id == mxUINT64_CLASS);
-  }
-
-  int is_single (void) const { return id == mxSINGLE_CLASS; }
-
-  int is_sparse (void) const { return 0; }
-
-  int is_struct (void) const { return id == mxSTRUCT_CLASS; }
-
-  int is_uint16 (void) const { return id == mxUINT16_CLASS; }
-
-  int is_uint32 (void) const { return id == mxUINT32_CLASS; }
-
-  int is_uint64 (void) const { return id == mxUINT64_CLASS; }
-
-  int is_uint8 (void) const { return id == mxUINT8_CLASS; }
-
-  int is_logical_scalar_true (void) const
-  {
-    return (is_logical_scalar ()
-            && static_cast<mxLogical *> (get_data ())[0] != 0);
-  }
-
-  mwSize get_m (void) const { return dims[0]; }
-
-  mwSize get_n (void) const
-  {
-    mwSize n = 1;
-
-    for (mwSize i = ndims - 1 ; i > 0 ; i--)
-      n *= dims[i];
-
-    return n;
-  }
-
-  mwSize *get_dimensions (void) const { return dims; }
-
-  mwSize get_number_of_dimensions (void) const { return ndims; }
-
-  void set_m (mwSize m) { dims[0] = m; }
-
-  void set_n (mwSize n) { dims[1] = n; }
-
-  void set_dimensions (mwSize *dims_arg, mwSize ndims_arg)
-  {
-    dims = dims_arg;
-    ndims = ndims_arg;
-  }
-
-  mwSize get_number_of_elements (void) const
-  {
-    mwSize retval = dims[0];
-
-    for (mwIndex i = 1; i < ndims; i++)
-      retval *= dims[i];
-
-    return retval;
-  }
-
-  int is_empty (void) const { return get_number_of_elements () == 0; }
-
-  mxClassID get_class_id (void) const { return id; }
-
-  const char *get_class_name (void) const
-  {
-    switch (id)
-      {
-      case mxCELL_CLASS: return "cell";
-      case mxSTRUCT_CLASS: return "struct";
-      case mxLOGICAL_CLASS: return "logical";
-      case mxCHAR_CLASS: return "char";
-      case mxDOUBLE_CLASS: return "double";
-      case mxSINGLE_CLASS: return "single";
-      case mxINT8_CLASS: return "int8";
-      case mxUINT8_CLASS: return "uint8";
-      case mxINT16_CLASS: return "int16";
-      case mxUINT16_CLASS: return "uint16";
-      case mxINT32_CLASS: return "int32";
-      case mxUINT32_CLASS: return "uint32";
-      case mxINT64_CLASS: return "int64";
-      case mxUINT64_CLASS: return "uint64";
-      case mxFUNCTION_CLASS: return "function_handle";
-      default: return "unknown";
-      }
-  }
-
-  void set_class_name (const char *name_arg)
-  {
-    mxFree (class_name);
-    class_name = static_cast<char *> (malloc (strlen (name_arg) + 1));
-    strcpy (class_name, name_arg);
-  }
-
-  mxArray *get_cell (mwIndex /*idx*/) const
-  {
-    invalid_type_error ();
-    return 0;
-  }
-
-  void set_cell (mwIndex /*idx*/, mxArray */*val*/)
-  {
-    invalid_type_error ();
-  }
-
-  double get_scalar (void) const
-  {
-    invalid_type_error ();
-    return 0;
-  }
-
-  void *get_data (void) const
-  {
-    invalid_type_error ();
-    return 0;
-  }
-
-  void *get_imag_data (void) const
-  {
-    invalid_type_error ();
-    return 0;
-  }
-
-  void set_data (void */*pr*/)
-  {
-    invalid_type_error ();
-  }
-
-  void set_imag_data (void */*pi*/)
-  {
-    invalid_type_error ();
-  }
-
-  mwIndex *get_ir (void) const
-  {
-    invalid_type_error ();
-    return 0;
-  }
-
-  mwIndex *get_jc (void) const
-  {
-    invalid_type_error ();
-    return 0;
-  }
-
-  mwSize get_nzmax (void) const
-  {
-    invalid_type_error ();
-    return 0;
-  }
-
-  void set_ir (mwIndex */*ir*/)
-  {
-    invalid_type_error ();
-  }
-
-  void set_jc (mwIndex */*jc*/)
-  {
-    invalid_type_error ();
-  }
-
-  void set_nzmax (mwSize /*nzmax*/)
-  {
-    invalid_type_error ();
-  }
-
-  int add_field (const char */*key*/)
-  {
-    invalid_type_error ();
-    return -1;
-  }
-
-  void remove_field (int /*key_num*/)
-  {
-    invalid_type_error ();
-  }
-
-  mxArray *get_field_by_number (mwIndex /*index*/, int /*key_num*/) const
-  {
-    invalid_type_error ();
-    return 0;
-  }
-
-  void set_field_by_number (mwIndex /*index*/, int /*key_num*/, mxArray */*val*/)
-  {
-    invalid_type_error ();
-  }
-
-  int get_number_of_fields (void) const
-  {
-    invalid_type_error ();
-    return 0;
-  }
-
-  const char *get_field_name_by_number (int /*key_num*/) const
-  {
-    invalid_type_error ();
-    return 0;
-  }
-
-  int get_field_number (const char */*key*/) const
-  {
-    return -1;
-  }
-
-  int get_string (char */*buf*/, mwSize /*buflen*/) const
-  {
-    invalid_type_error ();
-    return 0;
-  }
-
-  char *array_to_string (void) const
-  {
-    invalid_type_error ();
-    return 0;
-  }
-
-  mwIndex calc_single_subscript (mwSize nsubs, mwIndex *subs) const
-  {
-    return calc_single_subscript_internal (ndims, dims, nsubs, subs);
-  }
-
-  size_t get_element_size (void) const
-  {
-    switch (id)
-      {
-      case mxCELL_CLASS: return sizeof (mxArray *);
-      case mxSTRUCT_CLASS: return sizeof (mxArray *);
-      case mxLOGICAL_CLASS: return sizeof (mxLogical);
-      case mxCHAR_CLASS: return sizeof (mxChar);
-      case mxDOUBLE_CLASS: return sizeof (double);
-      case mxSINGLE_CLASS: return sizeof (float);
-      case mxINT8_CLASS: return 1;
-      case mxUINT8_CLASS: return 1;
-      case mxINT16_CLASS: return 2;
-      case mxUINT16_CLASS: return 2;
-      case mxINT32_CLASS: return 4;
-      case mxUINT32_CLASS: return 4;
-      case mxINT64_CLASS: return 8;
-      case mxUINT64_CLASS: return 8;
-      case mxFUNCTION_CLASS: return 0;
-      default: return 0;
-      }
-  }
-
-protected:
-
-  mxArray_matlab (const mxArray_matlab& val)
-    : mxArray_base (val), class_name (strsave (val.class_name)),
-      id (val.id), ndims (val.ndims),
-      dims (static_cast<mwSize *> (malloc (ndims * sizeof (mwSize))))
-  {
-    for (mwIndex i = 0; i < ndims; i++)
-      dims[i] = val.dims[i];
-  }
-
-  dim_vector
-  dims_to_dim_vector (void) const
-  {
-    mwSize nd = get_number_of_dimensions ();
-
-    mwSize *d = get_dimensions ();
-
-    dim_vector dv;
-    dv.resize (nd);
-
-    for (mwIndex i = 0; i < nd; i++)
-      dv(i) = d[i];
-
-    return dv;
-  }
-
-private:
-
-  char *class_name;
-
-  mxClassID id;
-
-  mwSize ndims;
-  mwSize *dims;
-
-  void invalid_type_error (void) const
-  {
-    error ("invalid type for operation");
-  }
-
-  // No assignment!  FIXME -- should this be implemented?  Note that we
-  // do have a copy constructor.
-
-  mxArray_matlab& operator = (const mxArray_matlab&);
-};
-
-// Matlab-style numeric, character, and logical data.
-
-class mxArray_number : public mxArray_matlab
-{
-public:
-
-  mxArray_number (mxClassID id_arg, mwSize ndims_arg, const mwSize *dims_arg,
-                  mxComplexity flag = mxREAL)
-    : mxArray_matlab (id_arg, ndims_arg, dims_arg),
-      pr (calloc (get_number_of_elements (), get_element_size ())),
-      pi (flag == mxCOMPLEX ? calloc (get_number_of_elements (), get_element_size ()) : 0) { }
-
-  mxArray_number (mxClassID id_arg, const dim_vector& dv,
-                  mxComplexity flag = mxREAL)
-    : mxArray_matlab (id_arg, dv),
-      pr (calloc (get_number_of_elements (), get_element_size ())),
-      pi (flag == mxCOMPLEX ? calloc (get_number_of_elements (), get_element_size ()) : 0) { }
-
-  mxArray_number (mxClassID id_arg, mwSize m, mwSize n, mxComplexity flag = mxREAL)
-    : mxArray_matlab (id_arg, m, n),
-      pr (calloc (get_number_of_elements (), get_element_size ())),
-      pi (flag == mxCOMPLEX ? calloc (get_number_of_elements (), get_element_size ()) : 0) { }
-
-  mxArray_number (mxClassID id_arg, double val)
-    : mxArray_matlab (id_arg, 1, 1),
-      pr (calloc (get_number_of_elements (), get_element_size ())),
-      pi (0)
-  {
-    double *dpr = static_cast<double *> (pr);
-    dpr[0] = val;
-  }
-
-  mxArray_number (mxClassID id_arg, mxLogical val)
-    : mxArray_matlab (id_arg, 1, 1),
-      pr (calloc (get_number_of_elements (), get_element_size ())),
-      pi (0)
-  {
-    mxLogical *lpr = static_cast<mxLogical *> (pr);
-    lpr[0] = val;
-  }
-
-  mxArray_number (const char *str)
-    : mxArray_matlab (mxCHAR_CLASS,
-                      str ? (strlen (str) ? 1 : 0) : 0,
-                      str ? strlen (str) : 0),
-      pr (calloc (get_number_of_elements (), get_element_size ())),
-      pi (0)
-  {
-    mxChar *cpr = static_cast<mxChar *> (pr);
-    mwSize nel = get_number_of_elements ();
-    for (mwIndex i = 0; i < nel; i++)
-      cpr[i] = str[i];
-  }
-
-  // FIXME??
-  mxArray_number (mwSize m, const char **str)
-    : mxArray_matlab (mxCHAR_CLASS, m, max_str_len (m, str)),
-      pr (calloc (get_number_of_elements (), get_element_size ())),
-      pi (0)
-  {
-    mxChar *cpr = static_cast<mxChar *> (pr);
-
-    mwSize *dv = get_dimensions ();
-
-    mwSize nc = dv[1];
-
-    for (mwIndex j = 0; j < m; j++)
-      {
-        const char *ptr = str[j];
-
-        size_t tmp_len = strlen (ptr);
-
-        for (size_t i = 0; i < tmp_len; i++)
-          cpr[m*i+j] = static_cast<mxChar> (ptr[i]);
-
-        for (size_t i = tmp_len; i < static_cast<size_t>(nc); i++)
-          cpr[m*i+j] = static_cast<mxChar> (' ');
-      }
-  }
-
-  mxArray_number *dup (void) const { return new mxArray_number (*this); }
-
-  ~mxArray_number (void)
-  {
-    mxFree (pr);
-    mxFree (pi);
-  }
-
-  int is_complex (void) const { return pi != 0; }
-
-  double get_scalar (void) const
-  {
-    double retval = 0;
-
-    switch (get_class_id ())
-      {
-      case mxLOGICAL_CLASS:
-        retval = *(static_cast<bool *> (pr));
-        break;
-
-      case mxCHAR_CLASS:
-        retval = *(static_cast<mxChar *> (pr));
-        break;
-
-      case mxSINGLE_CLASS:
-        retval = *(static_cast<float *> (pr));
-        break;
-
-      case mxDOUBLE_CLASS:
-        retval = *(static_cast<double *> (pr));
-        break;
-
-      case mxINT8_CLASS:
-        retval = *(static_cast<int8_t *> (pr));
-        break;
-
-      case mxUINT8_CLASS:
-        retval = *(static_cast<uint8_t *> (pr));
-        break;
-
-      case mxINT16_CLASS:
-        retval = *(static_cast<int16_t *> (pr));
-        break;
-
-      case mxUINT16_CLASS:
-        retval = *(static_cast<uint16_t *> (pr));
-        break;
-
-      case mxINT32_CLASS:
-        retval = *(static_cast<int32_t *> (pr));
-        break;
-
-      case mxUINT32_CLASS:
-        retval = *(static_cast<uint32_t *> (pr));
-        break;
-
-      case mxINT64_CLASS:
-        retval = *(static_cast<int64_t *> (pr));
-        break;
-
-      case mxUINT64_CLASS:
-        retval = *(static_cast<uint64_t *> (pr));
-        break;
-
-      default:
-        panic_impossible ();
-      }
-
-    return retval;
-  }
-
-  void *get_data (void) const { return pr; }
-
-  void *get_imag_data (void) const { return pi; }
-
-  void set_data (void *pr_arg) { pr = pr_arg; }
-
-  void set_imag_data (void *pi_arg) { pi = pi_arg; }
-
-  int get_string (char *buf, mwSize buflen) const
-  {
-    int retval = 0;
-
-    mwSize nel = get_number_of_elements ();
-
-    if (! (nel < buflen))
-      {
-        retval = 1;
-        if (buflen > 0)
-          nel = buflen-1;
-      }
-
-    if (nel < buflen)
-      {
-        mxChar *ptr = static_cast<mxChar *> (pr);
-
-        for (mwIndex i = 0; i < nel; i++)
-          buf[i] = static_cast<char> (ptr[i]);
-
-        buf[nel] = 0;
-      }
-
-    return retval;
-  }
-
-  char *array_to_string (void) const
-  {
-    // FIXME -- this is suposed to handle multi-byte character
-    // strings.
-
-    mwSize nel = get_number_of_elements ();
-
-    char *buf = static_cast<char *> (malloc (nel + 1));
-
-    if (buf)
-      {
-        mxChar *ptr = static_cast<mxChar *> (pr);
-
-        for (mwIndex i = 0; i < nel; i++)
-          buf[i] = static_cast<char> (ptr[i]);
-
-        buf[nel] = '\0';
-      }
-
-    return buf;
-  }
-
-protected:
-
-  template <typename ELT_T, typename ARRAY_T, typename ARRAY_ELT_T>
-  octave_value
-  int_to_ov (const dim_vector& dv) const
-  {
-    octave_value retval;
-
-    mwSize nel = get_number_of_elements ();
-
-    ELT_T *ppr = static_cast<ELT_T *> (pr);
-
-    if (pi)
-      error ("complex integer types are not supported");
-    else
-      {
-        ARRAY_T val (dv);
-
-        ARRAY_ELT_T *ptr = val.fortran_vec ();
-
-        for (mwIndex i = 0; i < nel; i++)
-          ptr[i] = ppr[i];
-
-        retval = val;
-      }
-
-    return retval;
-  }
-
-  octave_value as_octave_value (void) const
-  {
-    octave_value retval;
-
-    dim_vector dv = dims_to_dim_vector ();
-
-    switch (get_class_id ())
-      {
-      case mxLOGICAL_CLASS:
-        retval = int_to_ov<bool, boolNDArray, bool> (dv);
-        break;
-
-      case mxCHAR_CLASS:
-        {
-          mwSize nel = get_number_of_elements ();
-
-          mxChar *ppr = static_cast<mxChar *> (pr);
-
-          charNDArray val (dv);
-
-          char *ptr = val.fortran_vec ();
-
-          for (mwIndex i = 0; i < nel; i++)
-            ptr[i] = static_cast<char> (ppr[i]);
-
-          retval = val;
-        }
-        break;
-
-      case mxSINGLE_CLASS:
-        {
-          mwSize nel = get_number_of_elements ();
-
-          float *ppr = static_cast<float *> (pr);
-
-          if (pi)
-            {
-              FloatComplexNDArray val (dv);
-
-              FloatComplex *ptr = val.fortran_vec ();
-
-              float *ppi = static_cast<float *> (pi);
-
-              for (mwIndex i = 0; i < nel; i++)
-                ptr[i] = FloatComplex (ppr[i], ppi[i]);
-
-              retval = val;
-            }
-          else
-            {
-              FloatNDArray val (dv);
-
-              float *ptr = val.fortran_vec ();
-
-              for (mwIndex i = 0; i < nel; i++)
-                ptr[i] = ppr[i];
-
-              retval = val;
-            }
-        }
-        break;
-
-      case mxDOUBLE_CLASS:
-        {
-          mwSize nel = get_number_of_elements ();
-
-          double *ppr = static_cast<double *> (pr);
-
-          if (pi)
-            {
-              ComplexNDArray val (dv);
-
-              Complex *ptr = val.fortran_vec ();
-
-              double *ppi = static_cast<double *> (pi);
-
-              for (mwIndex i = 0; i < nel; i++)
-                ptr[i] = Complex (ppr[i], ppi[i]);
-
-              retval = val;
-            }
-          else
-            {
-              NDArray val (dv);
-
-              double *ptr = val.fortran_vec ();
-
-              for (mwIndex i = 0; i < nel; i++)
-                ptr[i] = ppr[i];
-
-              retval = val;
-            }
-        }
-        break;
-
-      case mxINT8_CLASS:
-        retval = int_to_ov<int8_t, int8NDArray, octave_int8> (dv);
-        break;
-
-      case mxUINT8_CLASS:
-        retval = int_to_ov<uint8_t, uint8NDArray, octave_uint8> (dv);
-        break;
-
-      case mxINT16_CLASS:
-        retval = int_to_ov<int16_t, int16NDArray, octave_int16> (dv);
-        break;
-
-      case mxUINT16_CLASS:
-        retval = int_to_ov<uint16_t, uint16NDArray, octave_uint16> (dv);
-        break;
-
-      case mxINT32_CLASS:
-        retval = int_to_ov<int32_t, int32NDArray, octave_int32> (dv);
-        break;
-
-      case mxUINT32_CLASS:
-        retval = int_to_ov<uint32_t, uint32NDArray, octave_uint32> (dv);
-        break;
-
-      case mxINT64_CLASS:
-        retval = int_to_ov<int64_t, int64NDArray, octave_int64> (dv);
-        break;
-
-      case mxUINT64_CLASS:
-        retval = int_to_ov<uint64_t, uint64NDArray, octave_uint64> (dv);
-        break;
-
-      default:
-        panic_impossible ();
-      }
-
-    return retval;
-  }
-
-  mxArray_number (const mxArray_number& val)
-    : mxArray_matlab (val),
-      pr (malloc (get_number_of_elements () * get_element_size ())),
-      pi (val.pi ? malloc (get_number_of_elements () * get_element_size ()) : 0)
-  {
-    size_t nbytes = get_number_of_elements () * get_element_size ();
-
-    if (pr)
-      memcpy (pr, val.pr, nbytes);
-
-    if (pi)
-      memcpy (pi, val.pi, nbytes);
-  }
-
-private:
-
-  void *pr;
-  void *pi;
-
-  // No assignment!  FIXME -- should this be implemented?  Note that we
-  // do have a copy constructor.
-
-  mxArray_number& operator = (const mxArray_number&);
-};
-
-// Matlab-style sparse arrays.
-
-class mxArray_sparse : public mxArray_matlab
-{
-public:
-
-  mxArray_sparse (mxClassID id_arg, mwSize m, mwSize n, mwSize nzmax_arg,
-                  mxComplexity flag = mxREAL)
-    : mxArray_matlab (id_arg, m, n), nzmax (nzmax_arg),
-      pr (calloc (nzmax, get_element_size ())),
-      pi (flag == mxCOMPLEX ? calloc (nzmax, get_element_size ()) : 0),
-      ir (static_cast<mwIndex *> (calloc (nzmax, sizeof (mwIndex)))),
-      jc (static_cast<mwIndex *> (calloc (n + 1, sizeof (mwIndex))))
-    { }
-
-  mxArray_sparse *dup (void) const { return new mxArray_sparse (*this); }
-
-  ~mxArray_sparse (void)
-  {
-    mxFree (pr);
-    mxFree (pi);
-    mxFree (ir);
-    mxFree (jc);
-  }
-
-  int is_complex (void) const { return pi != 0; }
-
-  int is_sparse (void) const { return 1; }
-
-  void *get_data (void) const { return pr; }
-
-  void *get_imag_data (void) const { return pi; }
-
-  void set_data (void *pr_arg) { pr = pr_arg; }
-
-  void set_imag_data (void *pi_arg) { pi = pi_arg; }
-
-  mwIndex *get_ir (void) const { return ir; }
-
-  mwIndex *get_jc (void) const { return jc; }
-
-  mwSize get_nzmax (void) const { return nzmax; }
-
-  void set_ir (mwIndex *ir_arg) { ir = ir_arg; }
-
-  void set_jc (mwIndex *jc_arg) { jc = jc_arg; }
-
-  void set_nzmax (mwSize nzmax_arg) { nzmax = nzmax_arg; }
-
-protected:
-
-  octave_value as_octave_value (void) const
-  {
-    octave_value retval;
-
-    dim_vector dv = dims_to_dim_vector ();
-
-    switch (get_class_id ())
-      {
-      case mxLOGICAL_CLASS:
-        {
-          bool *ppr = static_cast<bool *> (pr);
-
-          SparseBoolMatrix val (get_m (), get_n (),
-                                static_cast<octave_idx_type> (nzmax));
-
-          for (mwIndex i = 0; i < nzmax; i++)
-            {
-              val.xdata (i) = ppr[i];
-              val.xridx (i) = ir[i];
-            }
-
-          for (mwIndex i = 0; i < get_n () + 1; i++)
-            val.xcidx (i) = jc[i];
-
-          retval = val;
-        }
-        break;
-
-      case mxSINGLE_CLASS:
-        error ("single precision sparse data type not supported");
-        break;
-
-      case mxDOUBLE_CLASS:
-        {
-          if (pi)
-            {
-              double *ppr = static_cast<double *> (pr);
-              double *ppi = static_cast<double *> (pi);
-
-              SparseComplexMatrix val (get_m (), get_n (),
-                                       static_cast<octave_idx_type> (nzmax));
-
-              for (mwIndex i = 0; i < nzmax; i++)
-                {
-                  val.xdata (i) = Complex (ppr[i], ppi[i]);
-                  val.xridx (i) = ir[i];
-                }
-
-              for (mwIndex i = 0; i < get_n () + 1; i++)
-                val.xcidx (i) = jc[i];
-
-              retval = val;
-            }
-          else
-            {
-              double *ppr = static_cast<double *> (pr);
-
-              SparseMatrix val (get_m (), get_n (),
-                                static_cast<octave_idx_type> (nzmax));
-
-              for (mwIndex i = 0; i < nzmax; i++)
-                {
-                  val.xdata (i) = ppr[i];
-                  val.xridx (i) = ir[i];
-                }
-
-              for (mwIndex i = 0; i < get_n () + 1; i++)
-                val.xcidx (i) = jc[i];
-
-              retval = val;
-            }
-        }
-        break;
-
-      default:
-        panic_impossible ();
-      }
-
-    return retval;
-  }
-
-private:
-
-  mwSize nzmax;
-
-  void *pr;
-  void *pi;
-  mwIndex *ir;
-  mwIndex *jc;
-
-  mxArray_sparse (const mxArray_sparse& val)
-    : mxArray_matlab (val), nzmax (val.nzmax),
-      pr (malloc (nzmax * get_element_size ())),
-      pi (val.pi ? malloc (nzmax * get_element_size ()) : 0),
-      ir (static_cast<mwIndex *> (malloc (nzmax * sizeof (mwIndex)))),
-      jc (static_cast<mwIndex *> (malloc (nzmax * sizeof (mwIndex))))
-  {
-    size_t nbytes = nzmax * get_element_size ();
-
-    if (pr)
-      memcpy (pr, val.pr, nbytes);
-
-    if (pi)
-      memcpy (pi, val.pi, nbytes);
-
-    if (ir)
-      memcpy (ir, val.ir, nzmax * sizeof (mwIndex));
-
-    if (jc)
-      memcpy (jc, val.jc, (val.get_n () + 1) * sizeof (mwIndex));
-  }
-
-  // No assignment!  FIXME -- should this be implemented?  Note that we
-  // do have a copy constructor.
-
-  mxArray_sparse& operator = (const mxArray_sparse&);
-};
-
-// Matlab-style struct arrays.
-
-class mxArray_struct : public mxArray_matlab
-{
-public:
-
-  mxArray_struct (mwSize ndims_arg, const mwSize *dims_arg, int num_keys_arg,
-                  const char **keys)
-    : mxArray_matlab (mxSTRUCT_CLASS, ndims_arg, dims_arg), nfields (num_keys_arg),
-      fields (static_cast<char **> (calloc (nfields, sizeof (char *)))),
-      data (static_cast<mxArray **> (calloc (nfields * get_number_of_elements (), sizeof (mxArray *))))
-  {
-    init (keys);
-  }
-
-  mxArray_struct (const dim_vector& dv, int num_keys_arg, const char **keys)
-    : mxArray_matlab (mxSTRUCT_CLASS, dv), nfields (num_keys_arg),
-      fields (static_cast<char **> (calloc (nfields, sizeof (char *)))),
-      data (static_cast<mxArray **> (calloc (nfields * get_number_of_elements (), sizeof (mxArray *))))
-  {
-    init (keys);
-  }
-
-  mxArray_struct (mwSize m, mwSize n, int num_keys_arg, const char **keys)
-    : mxArray_matlab (mxSTRUCT_CLASS, m, n), nfields (num_keys_arg),
-      fields (static_cast<char **> (calloc (nfields, sizeof (char *)))),
-      data (static_cast<mxArray **> (calloc (nfields * get_number_of_elements (), sizeof (mxArray *))))
-  {
-    init (keys);
-  }
-
-  void init (const char **keys)
-  {
-    for (int i = 0; i < nfields; i++)
-      fields[i] = strsave (keys[i]);
-  }
-
-  mxArray_struct *dup (void) const { return new mxArray_struct (*this); }
-
-  ~mxArray_struct (void)
-  {
-    for (int i = 0; i < nfields; i++)
-      mxFree (fields[i]);
-
-    mxFree (fields);
-
-    mwSize ntot = nfields * get_number_of_elements ();
-
-    for  (mwIndex i = 0; i < ntot; i++)
-      delete data[i];
-
-    mxFree (data);
-  }
-
-  int add_field (const char *key)
-  {
-    int retval = -1;
-
-    if (valid_key (key))
-      {
-        nfields++;
-
-        fields = static_cast<char **> (mxRealloc (fields, nfields * sizeof (char *)));
-
-        if (fields)
-          {
-            fields[nfields-1] = strsave (key);
-
-            mwSize nel = get_number_of_elements ();
-
-            mwSize ntot = nfields * nel;
-
-            mxArray **new_data = static_cast<mxArray **> (malloc (ntot * sizeof (mxArray *)));
-
-            if (new_data)
-              {
-                mwIndex j = 0;
-                mwIndex k = 0;
-                mwIndex n = 0;
-
-                for (mwIndex i = 0; i < ntot; i++)
-                  {
-                    if (++n == nfields)
-                      {
-                        new_data[j++] = 0;
-                        n = 0;
-                      }
-                    else
-                      new_data[j++] = data[k++];
-                  }
-
-                mxFree (data);
-
-                data = new_data;
-
-                retval = nfields - 1;
-              }
-          }
-      }
-
-    return retval;
-  }
-
-  void remove_field (int key_num)
-  {
-    if (key_num >= 0 && key_num < nfields)
-      {
-        mwSize nel = get_number_of_elements ();
-
-        mwSize ntot = nfields * nel;
-
-        int new_nfields = nfields - 1;
-
-        char **new_fields = static_cast<char **> (malloc (new_nfields * sizeof (char *)));
-
-        mxArray **new_data = static_cast<mxArray **> (malloc (new_nfields * nel * sizeof (mxArray *)));
-
-        for (int i = 0; i < key_num; i++)
-          new_fields[i] = fields[i];
-
-        for (int i = key_num + 1; i < nfields; i++)
-          new_fields[i-1] = fields[i];
-
-        if (new_nfields > 0)
-          {
-            mwIndex j = 0;
-            mwIndex k = 0;
-            mwIndex n = 0;
-
-            for (mwIndex i = 0; i < ntot; i++)
-              {
-                if (n == key_num)
-                  k++;
-                else
-                  new_data[j++] = data[k++];
-
-                if (++n == nfields)
-                  n = 0;
-              }
-          }
-
-        nfields = new_nfields;
-
-        mxFree (fields);
-        mxFree (data);
-
-        fields = new_fields;
-        data = new_data;
-      }
-  }
-
-  mxArray *get_field_by_number (mwIndex index, int key_num) const
-  {
-    return key_num >= 0 && key_num < nfields
-      ? data[nfields * index + key_num] : 0;
-  }
-
-  void set_field_by_number (mwIndex index, int key_num, mxArray *val);
-
-  int get_number_of_fields (void) const { return nfields; }
-
-  const char *get_field_name_by_number (int key_num) const
-  {
-    return key_num >= 0 && key_num < nfields ? fields[key_num] : 0;
-  }
-
-  int get_field_number (const char *key) const
-  {
-    int retval = -1;
-
-    for (int i = 0; i < nfields; i++)
-      {
-        if (! strcmp (key, fields[i]))
-          {
-            retval = i;
-            break;
-          }
-      }
-
-    return retval;
-  }
-
-  void *get_data (void) const { return data; }
-
-  void set_data (void *data_arg) { data = static_cast<mxArray **> (data_arg); }
-
-protected:
-
-  octave_value as_octave_value (void) const
-  {
-    dim_vector dv = dims_to_dim_vector ();
-
-    string_vector keys (fields, nfields);
-
-    octave_map m;
-
-    mwSize ntot = nfields * get_number_of_elements ();
-
-    for (int i = 0; i < nfields; i++)
-      {
-        Cell c (dv);
-
-        octave_value *p = c.fortran_vec ();
-
-        mwIndex k = 0;
-        for (mwIndex j = i; j < ntot; j += nfields)
-          p[k++] = mxArray::as_octave_value (data[j]);
-
-        m.assign (keys[i], c);
-      }
-
-    return m;
-  }
-
-private:
-
-  int nfields;
-
-  char **fields;
-
-  mxArray **data;
-
-  mxArray_struct (const mxArray_struct& val)
-    : mxArray_matlab (val), nfields (val.nfields),
-      fields (static_cast<char **> (malloc (nfields * sizeof (char *)))),
-      data (static_cast<mxArray **> (malloc (nfields * get_number_of_elements () * sizeof (mxArray *))))
-  {
-    for (int i = 0; i < nfields; i++)
-      fields[i] = strsave (val.fields[i]);
-
-    mwSize nel = get_number_of_elements ();
-
-    for (mwIndex i = 0; i < nel * nfields; i++)
-      {
-        mxArray *ptr = val.data[i];
-        data[i] = ptr ? ptr->dup () : 0;
-      }
-  }
-
-  // No assignment!  FIXME -- should this be implemented?  Note that we
-  // do have a copy constructor.
-
-  mxArray_struct& operator = (const mxArray_struct& val);
-};
-
-// Matlab-style cell arrays.
-
-class mxArray_cell : public mxArray_matlab
-{
-public:
-
-  mxArray_cell (mwSize ndims_arg, const mwSize *dims_arg)
-    : mxArray_matlab (mxCELL_CLASS, ndims_arg, dims_arg),
-      data (static_cast<mxArray **> (calloc (get_number_of_elements (), sizeof (mxArray *)))) { }
-
-  mxArray_cell (const dim_vector& dv)
-    : mxArray_matlab (mxCELL_CLASS, dv),
-      data (static_cast<mxArray **> (calloc (get_number_of_elements (), sizeof (mxArray *)))) { }
-
-  mxArray_cell (mwSize m, mwSize n)
-    : mxArray_matlab (mxCELL_CLASS, m, n),
-      data (static_cast<mxArray **> (calloc (get_number_of_elements (), sizeof (mxArray *)))) { }
-
-  mxArray_cell *dup (void) const { return new mxArray_cell (*this); }
-
-  ~mxArray_cell (void)
-  {
-    mwSize nel = get_number_of_elements ();
-
-    for  (mwIndex i = 0; i < nel; i++)
-      delete data[i];
-
-    mxFree (data);
-  }
-
-  mxArray *get_cell (mwIndex idx) const
-  {
-    return idx >= 0 && idx < get_number_of_elements () ? data[idx] : 0;
-  }
-
-  void set_cell (mwIndex idx, mxArray *val);
-
-  void *get_data (void) const { return data; }
-
-  void set_data (void *data_arg) { data = static_cast<mxArray **> (data_arg); }
-
-protected:
-
-  octave_value as_octave_value (void) const
-  {
-    dim_vector dv = dims_to_dim_vector ();
-
-    Cell c (dv);
-
-    mwSize nel = get_number_of_elements ();
-
-    octave_value *p = c.fortran_vec ();
-
-    for (mwIndex i = 0; i < nel; i++)
-      p[i] = mxArray::as_octave_value (data[i]);
-
-    return c;
-  }
-
-private:
-
-  mxArray **data;
-
-  mxArray_cell (const mxArray_cell& val)
-    : mxArray_matlab (val),
-      data (static_cast<mxArray **> (malloc (get_number_of_elements () * sizeof (mxArray *))))
-  {
-    mwSize nel = get_number_of_elements ();
-
-    for (mwIndex i = 0; i < nel; i++)
-      {
-        mxArray *ptr = val.data[i];
-        data[i] = ptr ? ptr->dup () : 0;
-      }
-  }
-
-  // No assignment!  FIXME -- should this be implemented?  Note that we
-  // do have a copy constructor.
-
-  mxArray_cell& operator = (const mxArray_cell&);
-};
-
-// ------------------------------------------------------------------
-
-mxArray::mxArray (const octave_value& ov)
-  : rep (new mxArray_octave_value (ov)), name (0) { }
-
-mxArray::mxArray (mxClassID id, mwSize ndims, const mwSize *dims, mxComplexity flag)
-  : rep (new mxArray_number (id, ndims, dims, flag)), name (0) { }
-
-mxArray::mxArray (mxClassID id, const dim_vector& dv, mxComplexity flag)
-  : rep (new mxArray_number (id, dv, flag)), name (0) { }
-
-mxArray::mxArray (mxClassID id, mwSize m, mwSize n, mxComplexity flag)
-  : rep (new mxArray_number (id, m, n, flag)), name (0) { }
-
-mxArray::mxArray (mxClassID id, double val)
-  : rep (new mxArray_number (id, val)), name (0) { }
-
-mxArray::mxArray (mxClassID id, mxLogical val)
-  : rep (new mxArray_number (id, val)), name (0) { }
-
-mxArray::mxArray (const char *str)
-  : rep (new mxArray_number (str)), name (0) { }
-
-mxArray::mxArray (mwSize m, const char **str)
-  : rep (new mxArray_number (m, str)), name (0) { }
-
-mxArray::mxArray (mxClassID id, mwSize m, mwSize n, mwSize nzmax, mxComplexity flag)
-  : rep (new mxArray_sparse (id, m, n, nzmax, flag)), name (0) { }
-
-mxArray::mxArray (mwSize ndims, const mwSize *dims, int num_keys, const char **keys)
-  : rep (new mxArray_struct (ndims, dims, num_keys, keys)), name (0) { }
-
-mxArray::mxArray (const dim_vector& dv, int num_keys, const char **keys)
-  : rep (new mxArray_struct (dv, num_keys, keys)), name (0) { }
-
-mxArray::mxArray (mwSize m, mwSize n, int num_keys, const char **keys)
-  : rep (new mxArray_struct (m, n, num_keys, keys)), name (0) { }
-
-mxArray::mxArray (mwSize ndims, const mwSize *dims)
-  : rep (new mxArray_cell (ndims, dims)), name (0) { }
-
-mxArray::mxArray (const dim_vector& dv)
-  : rep (new mxArray_cell (dv)), name (0) { }
-
-mxArray::mxArray (mwSize m, mwSize n)
-  : rep (new mxArray_cell (m, n)), name (0) { }
-
-mxArray::~mxArray (void)
-{
-  mxFree (name);
-
-  delete rep;
-}
-
-void
-mxArray::set_name (const char *name_arg)
-{
-  mxFree (name);
-  name = strsave (name_arg);
-}
-
-octave_value
-mxArray::as_octave_value (mxArray *ptr)
-{
-  return ptr ? ptr->as_octave_value () : octave_value (Matrix ());
-}
-
-octave_value
-mxArray::as_octave_value (void) const
-{
-  return rep->as_octave_value ();
-}
-
-void
-mxArray::maybe_mutate (void) const
-{
-  if (rep->is_octave_value ())
-    {
-      // The mutate function returns a pointer to a complete new
-      // mxArray object (or 0, if no mutation happened).  We just want
-      // to replace the existing rep with the rep from the new object.
-
-      mxArray *new_val = rep->mutate ();
-
-      if (new_val)
-        {
-          delete rep;
-          rep = new_val->rep;
-          new_val->rep = 0;
-          delete new_val;
-        }
-    }
-}
-
-// ------------------------------------------------------------------
-
-// A class to manage calls to MEX functions.  Mostly deals with memory
-// management.
-
-class mex
-{
-public:
-
-  mex (octave_mex_function *f)
-    : curr_mex_fcn (f), memlist (), arraylist (), fname (0) { }
-
-  ~mex (void)
-  {
-    if (! memlist.empty ())
-      error ("mex: %s: cleanup failed", function_name ());
-
-    mxFree (fname);
-  }
-
-  const char *function_name (void) const
-  {
-    if (! fname)
-      {
-        octave_function *fcn = octave_call_stack::current ();
-
-        if (fcn)
-          {
-            std::string nm = fcn->name ();
-            fname = mxArray::strsave (nm.c_str ());
-          }
-        else
-          fname = mxArray::strsave ("unknown");
-      }
-
-    return fname;
-  }
-
-  // Free all unmarked pointers obtained from malloc and calloc.
-  static void cleanup (void *ptr)
-  {
-    mex *context = static_cast<mex *> (ptr);
-
-    // We can't use mex::free here because it modifies memlist.
-    for (std::set<void *>::iterator p = context->memlist.begin ();
-         p != context->memlist.end (); p++)
-      xfree (*p);
-
-    context->memlist.clear ();
-
-    // We can't use mex::free_value here because it modifies arraylist.
-    for (std::set<mxArray *>::iterator p = context->arraylist.begin ();
-         p != context->arraylist.end (); p++)
-      delete *p;
-
-    context->arraylist.clear ();
-  }
-
-  // Allocate memory.
-  void *malloc_unmarked (size_t n)
-  {
-    void *ptr = gnulib::malloc (n);
-
-    if (! ptr)
-      {
-        // FIXME -- could use "octave_new_handler();" instead
-
-        error ("%s: failed to allocate %d bytes of memory",
-               function_name (), n);
-
-        abort ();
-      }
-
-    global_mark (ptr);
-
-    return ptr;
-  }
-
-  // Allocate memory to be freed on exit.
-  void *malloc (size_t n)
-  {
-    void *ptr = malloc_unmarked (n);
-
-    mark (ptr);
-
-    return ptr;
-  }
-
-  // Allocate memory and initialize to 0.
-  void *calloc_unmarked (size_t n, size_t t)
-  {
-    void *ptr = malloc_unmarked (n*t);
-
-    memset (ptr, 0, n*t);
-
-    return ptr;
-  }
-
-  // Allocate memory to be freed on exit and initialize to 0.
-  void *calloc (size_t n, size_t t)
-  {
-    void *ptr = calloc_unmarked (n, t);
-
-    mark (ptr);
-
-    return ptr;
-  }
-
-  // Reallocate a pointer obtained from malloc or calloc. If the
-  // pointer is NULL, allocate using malloc.  We don't need an
-  // "unmarked" version of this.
-  void *realloc (void *ptr, size_t n)
-  {
-    void *v;
-
-    if (ptr)
-      {
-        v = gnulib::realloc (ptr, n);
-
-        std::set<void *>::iterator p = memlist.find (ptr);
-
-        if (v && p != memlist.end ())
-          {
-            memlist.erase (p);
-            memlist.insert (v);
-          }
-
-        p = global_memlist.find (ptr);
-
-        if (v && p != global_memlist.end ())
-          {
-            global_memlist.erase (p);
-            global_memlist.insert (v);
-          }
-      }
-    else
-      v = malloc (n);
-
-    return v;
-  }
-
-  // Free a pointer obtained from malloc or calloc.
-  void free (void *ptr)
-  {
-    if (ptr)
-      {
-        unmark (ptr);
-
-        std::set<void *>::iterator p = global_memlist.find (ptr);
-
-        if (p != global_memlist.end ())
-          {
-            global_memlist.erase (p);
-
-            xfree (ptr);
-          }
-        else
-          {
-            p = foreign_memlist.find (ptr);
-
-            if (p != foreign_memlist.end ())
-              foreign_memlist.erase (p);
-#ifdef DEBUG
-            else
-              warning ("mxFree: skipping memory not allocated by mxMalloc, mxCalloc, or mxRealloc");
-#endif
-          }
-      }
-  }
-
-  // Mark a pointer to be freed on exit.
-  void mark (void *ptr)
-  {
-#ifdef DEBUG
-    if (memlist.find (ptr) != memlist.end ())
-      warning ("%s: double registration ignored", function_name ());
-#endif
-
-    memlist.insert (ptr);
-  }
-
-  // Unmark a pointer to be freed on exit, either because it was
-  // made persistent, or because it was already freed.
-  void unmark (void *ptr)
-  {
-    std::set<void *>::iterator p = memlist.find (ptr);
-
-    if (p != memlist.end ())
-      memlist.erase (p);
-#ifdef DEBUG
-    else
-      warning ("%s: value not marked", function_name ());
-#endif
-  }
-
-  mxArray *mark_array (mxArray *ptr)
-  {
-    arraylist.insert (ptr);
-    return ptr;
-  }
-
-  void unmark_array (mxArray *ptr)
-  {
-    std::set<mxArray *>::iterator p = arraylist.find (ptr);
-
-    if (p != arraylist.end ())
-      arraylist.erase (p);
-  }
-
-  // Mark a pointer as one we allocated.
-  void mark_foreign (void *ptr)
-  {
-#ifdef DEBUG
-    if (foreign_memlist.find (ptr) != foreign_memlist.end ())
-      warning ("%s: double registration ignored", function_name ());
-#endif
-
-    foreign_memlist.insert (ptr);
-  }
-
-  // Unmark a pointer as one we allocated.
-  void unmark_foreign (void *ptr)
-  {
-    std::set<void *>::iterator p = foreign_memlist.find (ptr);
-
-    if (p != foreign_memlist.end ())
-      foreign_memlist.erase (p);
-#ifdef DEBUG
-    else
-      warning ("%s: value not marked", function_name ());
-#endif
-
-  }
-
-  // Make a new array value and initialize from an octave value; it will be
-  // freed on exit unless marked as persistent.
-  mxArray *make_value (const octave_value& ov)
-  {
-    return mark_array (new mxArray (ov));
-  }
-
-  // Free an array and its contents.
-  bool free_value (mxArray *ptr)
-  {
-    bool inlist = false;
-
-    std::set<mxArray *>::iterator p = arraylist.find (ptr);
-
-    if (p != arraylist.end ())
-      {
-        inlist = true;
-        arraylist.erase (p);
-        delete ptr;
-      }
-#ifdef DEBUG
-    else
-      warning ("mex::free_value: skipping memory not allocated by mex::make_value");
-#endif
-
-    return inlist;
-  }
-
-  octave_mex_function *current_mex_function (void) const
-  {
-    return curr_mex_fcn;
-  }
-
-  // 1 if error should be returned to MEX file, 0 if abort.
-  int trap_feval_error;
-
-  // longjmp return point if mexErrMsgTxt or error.
-  jmp_buf jump;
-
-  // Trigger a long jump back to the mex calling function.
-  void abort (void) { longjmp (jump, 1); }
-
-private:
-
-  // Pointer to the mex function that corresponds to this mex context.
-  octave_mex_function *curr_mex_fcn;
-
-  // List of memory resources that need to be freed upon exit.
-  std::set<void *> memlist;
-
-  // List of mxArray objects that need to be freed upon exit.
-  std::set<mxArray *> arraylist;
-
-  // List of memory resources we know about, but that were allocated
-  // elsewhere.
-  std::set<void *> foreign_memlist;
-
-  // The name of the currently executing function.
-  mutable char *fname;
-
-  // List of memory resources we allocated.
-  static std::set<void *> global_memlist;
-
-  // Mark a pointer as one we allocated.
-  void global_mark (void *ptr)
-  {
-#ifdef DEBUG
-    if (global_memlist.find (ptr) != global_memlist.end ())
-      warning ("%s: double registration ignored", function_name ());
-#endif
-
-    global_memlist.insert (ptr);
-  }
-
-  // Unmark a pointer as one we allocated.
-  void global_unmark (void *ptr)
-  {
-    std::set<void *>::iterator p = global_memlist.find (ptr);
-
-    if (p != global_memlist.end ())
-      global_memlist.erase (p);
-#ifdef DEBUG
-    else
-      warning ("%s: value not marked", function_name ());
-#endif
-
-  }
-
-  // No copying!
-
-  mex (const mex&);
-
-  mex& operator = (const mex&);
-};
-
-// List of memory resources we allocated.
-std::set<void *> mex::global_memlist;
-
-// Current context.
-mex *mex_context = 0;
-
-void *
-mxArray::malloc (size_t n)
-{
-  return mex_context ? mex_context->malloc_unmarked (n) : gnulib::malloc (n);
-}
-
-void *
-mxArray::calloc (size_t n, size_t t)
-{
-  return mex_context ? mex_context->calloc_unmarked (n, t) : ::calloc (n, t);
-}
-
-static inline void *
-maybe_mark_foreign (void *ptr)
-{
-  if (mex_context)
-    mex_context->mark_foreign (ptr);
-
-  return ptr;
-}
-
-static inline mxArray *
-maybe_unmark_array (mxArray *ptr)
-{
-  if (mex_context)
-    mex_context->unmark_array (ptr);
-
-  return ptr;
-}
-
-static inline void *
-maybe_unmark (void *ptr)
-{
-  if (mex_context)
-    mex_context->unmark (ptr);
-
-  return ptr;
-}
-
-void
-mxArray_struct::set_field_by_number (mwIndex index, int key_num, mxArray *val)
-{
-  if (key_num >= 0 && key_num < nfields)
-    data[nfields * index + key_num] = maybe_unmark_array (val);
-}
-
-void
-mxArray_cell::set_cell (mwIndex idx, mxArray *val)
-{
-  if (idx >= 0 && idx < get_number_of_elements ())
-    data[idx] = maybe_unmark_array (val);
-}
-
-// ------------------------------------------------------------------
-
-// C interface to mxArray objects:
-
-// Floating point predicates.
-
-int
-mxIsFinite (const double v)
-{
-  return lo_ieee_finite (v) != 0;
-}
-
-int
-mxIsInf (const double v)
-{
-  return lo_ieee_isinf (v) != 0;
-}
-
-int
-mxIsNaN (const double v)
-{
-  return lo_ieee_isnan (v) != 0;
-}
-
-double
-mxGetEps (void)
-{
-  return DBL_EPSILON;
-}
-
-double
-mxGetInf (void)
-{
-  return lo_ieee_inf_value ();
-}
-
-double
-mxGetNaN (void)
-{
-  return lo_ieee_nan_value ();
-}
-
-// Memory management.
-void *
-mxCalloc (size_t n, size_t size)
-{
-  return mex_context ? mex_context->calloc (n, size) : calloc (n, size);
-}
-
-void *
-mxMalloc (size_t n)
-{
-  return mex_context ? mex_context->malloc (n) : gnulib::malloc (n);
-}
-
-void *
-mxRealloc (void *ptr, size_t size)
-{
-  return mex_context ? mex_context->realloc (ptr, size) : gnulib::realloc (ptr, size);
-}
-
-void
-mxFree (void *ptr)
-{
-  if (mex_context)
-    mex_context->free (ptr);
-  else
-    xfree (ptr);
-}
-
-static inline mxArray *
-maybe_mark_array (mxArray *ptr)
-{
-  return mex_context ? mex_context->mark_array (ptr) : ptr;
-}
-
-// Constructors.
-mxArray *
-mxCreateCellArray (mwSize ndims, const mwSize *dims)
-{
-  return maybe_mark_array (new mxArray (ndims, dims));
-}
-
-mxArray *
-mxCreateCellMatrix (mwSize m, mwSize n)
-{
-  return maybe_mark_array (new mxArray (m, n));
-}
-
-mxArray *
-mxCreateCharArray (mwSize ndims, const mwSize *dims)
-{
-  return maybe_mark_array (new mxArray (mxCHAR_CLASS, ndims, dims));
-}
-
-mxArray *
-mxCreateCharMatrixFromStrings (mwSize m, const char **str)
-{
-  return maybe_mark_array (new mxArray (m, str));
-}
-
-mxArray *
-mxCreateDoubleMatrix (mwSize m, mwSize n, mxComplexity flag)
-{
-  return maybe_mark_array (new mxArray (mxDOUBLE_CLASS, m, n, flag));
-}
-
-mxArray *
-mxCreateDoubleScalar (double val)
-{
-  return maybe_mark_array (new mxArray (mxDOUBLE_CLASS, val));
-}
-
-mxArray *
-mxCreateLogicalArray (mwSize ndims, const mwSize *dims)
-{
-  return maybe_mark_array (new mxArray (mxLOGICAL_CLASS, ndims, dims));
-}
-
-mxArray *
-mxCreateLogicalMatrix (mwSize m, mwSize n)
-{
-  return maybe_mark_array (new mxArray (mxLOGICAL_CLASS, m, n));
-}
-
-mxArray *
-mxCreateLogicalScalar (mxLogical val)
-{
-  return maybe_mark_array (new mxArray (mxLOGICAL_CLASS, val));
-}
-
-mxArray *
-mxCreateNumericArray (mwSize ndims, const mwSize *dims, mxClassID class_id,
-                      mxComplexity flag)
-{
-  return maybe_mark_array (new mxArray (class_id, ndims, dims, flag));
-}
-
-mxArray *
-mxCreateNumericMatrix (mwSize m, mwSize n, mxClassID class_id, mxComplexity flag)
-{
-  return maybe_mark_array (new mxArray (class_id, m, n, flag));
-}
-
-mxArray *
-mxCreateSparse (mwSize m, mwSize n, mwSize nzmax, mxComplexity flag)
-{
-  return maybe_mark_array (new mxArray (mxDOUBLE_CLASS, m, n, nzmax, flag));
-}
-
-mxArray *
-mxCreateSparseLogicalMatrix (mwSize m, mwSize n, mwSize nzmax)
-{
-  return maybe_mark_array (new mxArray (mxLOGICAL_CLASS, m, n, nzmax));
-}
-
-mxArray *
-mxCreateString (const char *str)
-{
-  return maybe_mark_array (new mxArray (str));
-}
-
-mxArray *
-mxCreateStructArray (mwSize ndims, const mwSize *dims, int num_keys, const char **keys)
-{
-  return maybe_mark_array (new mxArray (ndims, dims, num_keys, keys));
-}
-
-mxArray *
-mxCreateStructMatrix (mwSize m, mwSize n, int num_keys, const char **keys)
-{
-  return maybe_mark_array (new mxArray (m, n, num_keys, keys));
-}
-
-// Copy constructor.
-mxArray *
-mxDuplicateArray (const mxArray *ptr)
-{
-  return maybe_mark_array (ptr->dup ());
-}
-
-// Destructor.
-void
-mxDestroyArray (mxArray *ptr)
-{
-  if (! (mex_context && mex_context->free_value (ptr)))
-    delete ptr;
-}
-
-// Type Predicates.
-int
-mxIsCell (const mxArray *ptr)
-{
-  return ptr->is_cell ();
-}
-
-int
-mxIsChar (const mxArray *ptr)
-{
-  return ptr->is_char ();
-}
-
-int
-mxIsClass (const mxArray *ptr, const char *name)
-{
-  return ptr->is_class (name);
-}
-
-int
-mxIsComplex (const mxArray *ptr)
-{
-  return ptr->is_complex ();
-}
-
-int
-mxIsDouble (const mxArray *ptr)
-{
-  return ptr->is_double ();
-}
-
-int
-mxIsFunctionHandle (const mxArray *ptr)
-{
-  return ptr->is_function_handle ();
-}
-
-int
-mxIsInt16 (const mxArray *ptr)
-{
-  return ptr->is_int16 ();
-}
-
-int
-mxIsInt32 (const mxArray *ptr)
-{
-  return ptr->is_int32 ();
-}
-
-int
-mxIsInt64 (const mxArray *ptr)
-{
-  return ptr->is_int64 ();
-}
-
-int
-mxIsInt8 (const mxArray *ptr)
-{
-  return ptr->is_int8 ();
-}
-
-int
-mxIsLogical (const mxArray *ptr)
-{
-  return ptr->is_logical ();
-}
-
-int
-mxIsNumeric (const mxArray *ptr)
-{
-  return ptr->is_numeric ();
-}
-
-int
-mxIsSingle (const mxArray *ptr)
-{
-  return ptr->is_single ();
-}
-
-int
-mxIsSparse (const mxArray *ptr)
-{
-  return ptr->is_sparse ();
-}
-
-int
-mxIsStruct (const mxArray *ptr)
-{
-  return ptr->is_struct ();
-}
-
-int
-mxIsUint16 (const mxArray *ptr)
-{
-  return ptr->is_uint16 ();
-}
-
-int
-mxIsUint32 (const mxArray *ptr)
-{
-  return ptr->is_uint32 ();
-}
-
-int
-mxIsUint64 (const mxArray *ptr)
-{
-  return ptr->is_uint64 ();
-}
-
-int
-mxIsUint8 (const mxArray *ptr)
-{
-  return ptr->is_uint8 ();
-}
-
-// Odd type+size predicate.
-int
-mxIsLogicalScalar (const mxArray *ptr)
-{
-  return ptr->is_logical_scalar ();
-}
-
-// Odd type+size+value predicate.
-int
-mxIsLogicalScalarTrue (const mxArray *ptr)
-{
-  return ptr->is_logical_scalar_true ();
-}
-
-// Size predicate.
-int
-mxIsEmpty (const mxArray *ptr)
-{
-  return ptr->is_empty ();
-}
-
-// Just plain odd thing to ask of a value.
-int
-mxIsFromGlobalWS (const mxArray */*ptr*/)
-{
-  // FIXME
-  abort ();
-  return 0;
-}
-
-// Dimension extractors.
-size_t
-mxGetM (const mxArray *ptr)
-{
-  return ptr->get_m ();
-}
-
-size_t
-mxGetN (const mxArray *ptr)
-{
-  return ptr->get_n ();
-}
-
-mwSize *
-mxGetDimensions (const mxArray *ptr)
-{
-  return ptr->get_dimensions ();
-}
-
-mwSize
-mxGetNumberOfDimensions (const mxArray *ptr)
-{
-  return ptr->get_number_of_dimensions ();
-}
-
-size_t
-mxGetNumberOfElements (const mxArray *ptr)
-{
-  return ptr->get_number_of_elements ();
-}
-
-// Dimension setters.
-void
-mxSetM (mxArray *ptr, mwSize m)
-{
-  ptr->set_m (m);
-}
-
-void
-mxSetN (mxArray *ptr, mwSize n)
-{
-  ptr->set_n (n);
-}
-
-void
-mxSetDimensions (mxArray *ptr, const mwSize *dims, mwSize ndims)
-{
-  ptr->set_dimensions (static_cast<mwSize *> (
-                         maybe_unmark (const_cast<mwSize *> (dims))),
-                       ndims);
-}
-
-// Data extractors.
-double *
-mxGetPr (const mxArray *ptr)
-{
-  return static_cast<double *> (ptr->get_data ());
-}
-
-double *
-mxGetPi (const mxArray *ptr)
-{
-  return static_cast<double *> (ptr->get_imag_data ());
-}
-
-double
-mxGetScalar (const mxArray *ptr)
-{
-  return ptr->get_scalar ();
-}
-
-mxChar *
-mxGetChars (const mxArray *ptr)
-{
-  return static_cast<mxChar *> (ptr->get_data ());
-}
-
-mxLogical *
-mxGetLogicals (const mxArray *ptr)
-{
-  return static_cast<mxLogical *> (ptr->get_data ());
-}
-
-void *
-mxGetData (const mxArray *ptr)
-{
-  return ptr->get_data ();
-}
-
-void *
-mxGetImagData (const mxArray *ptr)
-{
-  return ptr->get_imag_data ();
-}
-
-// Data setters.
-void
-mxSetPr (mxArray *ptr, double *pr)
-{
-  ptr->set_data (maybe_unmark (pr));
-}
-
-void
-mxSetPi (mxArray *ptr, double *pi)
-{
-  ptr->set_imag_data (maybe_unmark (pi));
-}
-
-void
-mxSetData (mxArray *ptr, void *pr)
-{
-  ptr->set_data (maybe_unmark (pr));
-}
-
-void
-mxSetImagData (mxArray *ptr, void *pi)
-{
-  ptr->set_imag_data (maybe_unmark (pi));
-}
-
-// Classes.
-mxClassID
-mxGetClassID (const mxArray *ptr)
-{
-  return ptr->get_class_id ();
-}
-
-const char *
-mxGetClassName (const mxArray *ptr)
-{
-  return ptr->get_class_name ();
-}
-
-void
-mxSetClassName (mxArray *ptr, const char *name)
-{
-  ptr->set_class_name (name);
-}
-
-// Cell support.
-mxArray *
-mxGetCell (const mxArray *ptr, mwIndex idx)
-{
-  return ptr->get_cell (idx);
-}
-
-void
-mxSetCell (mxArray *ptr, mwIndex idx, mxArray *val)
-{
-  ptr->set_cell (idx, val);
-}
-
-// Sparse support.
-mwIndex *
-mxGetIr (const mxArray *ptr)
-{
-  return ptr->get_ir ();
-}
-
-mwIndex *
-mxGetJc (const mxArray *ptr)
-{
-  return ptr->get_jc ();
-}
-
-mwSize
-mxGetNzmax (const mxArray *ptr)
-{
-  return ptr->get_nzmax ();
-}
-
-void
-mxSetIr (mxArray *ptr, mwIndex *ir)
-{
-  ptr->set_ir (static_cast <mwIndex *> (maybe_unmark (ir)));
-}
-
-void
-mxSetJc (mxArray *ptr, mwIndex *jc)
-{
-  ptr->set_jc (static_cast<mwIndex *> (maybe_unmark (jc)));
-}
-
-void
-mxSetNzmax (mxArray *ptr, mwSize nzmax)
-{
-  ptr->set_nzmax (nzmax);
-}
-
-// Structure support.
-int
-mxAddField (mxArray *ptr, const char *key)
-{
-  return ptr->add_field (key);
-}
-
-void
-mxRemoveField (mxArray *ptr, int key_num)
-{
-  ptr->remove_field (key_num);
-}
-
-mxArray *
-mxGetField (const mxArray *ptr, mwIndex index, const char *key)
-{
-  int key_num = mxGetFieldNumber (ptr, key);
-  return mxGetFieldByNumber (ptr, index, key_num);
-}
-
-mxArray *
-mxGetFieldByNumber (const mxArray *ptr, mwIndex index, int key_num)
-{
-  return ptr->get_field_by_number (index, key_num);
-}
-
-void
-mxSetField (mxArray *ptr, mwIndex index, const char *key, mxArray *val)
-{
-  int key_num = mxGetFieldNumber (ptr, key);
-  mxSetFieldByNumber (ptr, index, key_num, val);
-}
-
-void
-mxSetFieldByNumber (mxArray *ptr, mwIndex index, int key_num, mxArray *val)
-{
-  ptr->set_field_by_number (index, key_num, val);
-}
-
-int
-mxGetNumberOfFields (const mxArray *ptr)
-{
-  return ptr->get_number_of_fields ();
-}
-
-const char *
-mxGetFieldNameByNumber (const mxArray *ptr, int key_num)
-{
-  return ptr->get_field_name_by_number (key_num);
-}
-
-int
-mxGetFieldNumber (const mxArray *ptr, const char *key)
-{
-  return ptr->get_field_number (key);
-}
-
-int
-mxGetString (const mxArray *ptr, char *buf, mwSize buflen)
-{
-  return ptr->get_string (buf, buflen);
-}
-
-char *
-mxArrayToString (const mxArray *ptr)
-{
-  return ptr->array_to_string ();
-}
-
-mwIndex
-mxCalcSingleSubscript (const mxArray *ptr, mwSize nsubs, mwIndex *subs)
-{
-  return ptr->calc_single_subscript (nsubs, subs);
-}
-
-size_t
-mxGetElementSize (const mxArray *ptr)
-{
-  return ptr->get_element_size ();
-}
-
-// ------------------------------------------------------------------
-
-typedef void (*cmex_fptr) (int nlhs, mxArray **plhs, int nrhs, mxArray **prhs);
-typedef F77_RET_T (*fmex_fptr) (int& nlhs, mxArray **plhs, int& nrhs, mxArray **prhs);
-
-octave_value_list
-call_mex (bool have_fmex, void *f, const octave_value_list& args,
-          int nargout_arg, octave_mex_function *curr_mex_fcn)
-{
-  // Use at least 1 for nargout since even for zero specified args,
-  // still want to be able to return an ans.
-
-  volatile int nargout = nargout_arg;
-
-  int nargin = args.length ();
-  OCTAVE_LOCAL_BUFFER (mxArray *, argin, nargin);
-  for (int i = 0; i < nargin; i++)
-    argin[i] = 0;
-
-  int nout = nargout == 0 ? 1 : nargout;
-  OCTAVE_LOCAL_BUFFER (mxArray *, argout, nout);
-  for (int i = 0; i < nout; i++)
-    argout[i] = 0;
-
-  unwind_protect_safe frame;
-
-  // Save old mex pointer.
-  frame.protect_var (mex_context);
-
-  mex context (curr_mex_fcn);
-
-  frame.add (mex::cleanup, static_cast<void *> (&context));
-
-  for (int i = 0; i < nargin; i++)
-    argin[i] = context.make_value (args(i));
-
-  if (setjmp (context.jump) == 0)
-    {
-      mex_context = &context;
-
-      if (have_fmex)
-        {
-          fmex_fptr fcn = FCN_PTR_CAST (fmex_fptr, f);
-
-          int tmp_nargout = nargout;
-          int tmp_nargin = nargin;
-
-          fcn (tmp_nargout, argout, tmp_nargin, argin);
-        }
-      else
-        {
-          cmex_fptr fcn = FCN_PTR_CAST (cmex_fptr, f);
-
-          fcn (nargout, argout, nargin, argin);
-        }
-    }
-
-  // Convert returned array entries back into octave values.
-
-  octave_value_list retval;
-
-  if (! error_state)
-    {
-      if (nargout == 0 && argout[0])
-        {
-          // We have something for ans.
-          nargout = 1;
-        }
-
-      retval.resize (nargout);
-
-      for (int i = 0; i < nargout; i++)
-        retval(i) = mxArray::as_octave_value (argout[i]);
-    }
-
-  // Clean up mex resources.
-  frame.run ();
-
-  return retval;
-}
-
-// C interface to mex functions:
-
-const char *
-mexFunctionName (void)
-{
-  return mex_context ? mex_context->function_name () : "unknown";
-}
-
-int
-mexCallMATLAB (int nargout, mxArray *argout[], int nargin, mxArray *argin[],
-               const char *fname)
-{
-  octave_value_list args;
-
-  // FIXME -- do we need unwind protect to clean up args?  Off hand, I
-  // would say that this problem is endemic to Octave and we will
-  // continue to have memory leaks after Ctrl-C until proper exception
-  // handling is implemented.  longjmp() only clears the stack, so any
-  // class which allocates data on the heap is going to leak.
-
-  args.resize (nargin);
-
-  for (int i = 0; i < nargin; i++)
-    args(i) = mxArray::as_octave_value (argin[i]);
-
-  octave_value_list retval = feval (fname, args, nargout);
-
-  if (error_state && mex_context->trap_feval_error == 0)
-    {
-      // FIXME -- is this the correct way to clean up?  abort() is
-      // going to trigger a long jump, so the normal class destructors
-      // will not be called.  Hopefully this will reduce things to a
-      // tiny leak.  Maybe create a new octave memory tracer type
-      // which prints a friendly message every time it is
-      // created/copied/deleted to check this.
-
-      args.resize (0);
-      retval.resize (0);
-      mex_context->abort ();
-    }
-
-  int num_to_copy = retval.length ();
-
-  if (nargout < retval.length ())
-    num_to_copy = nargout;
-
-  for (int i = 0; i < num_to_copy; i++)
-    {
-      // FIXME -- it would be nice to avoid copying the value here,
-      // but there is no way to steal memory from a matrix, never mind
-      // that matrix memory is allocated by new[] and mxArray memory
-      // is allocated by malloc().
-      argout[i] = mex_context->make_value (retval (i));
-    }
-
-  while (num_to_copy < nargout)
-    argout[num_to_copy++] = 0;
-
-  if (error_state)
-    {
-      error_state = 0;
-      return 1;
-    }
-  else
-    return 0;
-}
-
-void
-mexSetTrapFlag (int flag)
-{
-  if (mex_context)
-    mex_context->trap_feval_error = flag;
-}
-
-int
-mexEvalString (const char *s)
-{
-  int retval = 0;
-
-  int parse_status;
-
-  octave_value_list ret;
-
-  ret = eval_string (s, false, parse_status, 0);
-
-  if (parse_status || error_state)
-    {
-      error_state = 0;
-
-      retval = 1;
-    }
-
-  return retval;
-}
-
-void
-mexErrMsgTxt (const char *s)
-{
-  if (s && strlen (s) > 0)
-    error ("%s: %s", mexFunctionName (), s);
-  else
-    // Just set the error state; don't print msg.
-    error ("");
-
-  mex_context->abort ();
-}
-
-void
-mexErrMsgIdAndTxt (const char *id, const char *fmt, ...)
-{
-  if (fmt && strlen (fmt) > 0)
-    {
-      const char *fname = mexFunctionName ();
-      size_t len = strlen (fname) + 2 + strlen (fmt) + 1;
-      OCTAVE_LOCAL_BUFFER (char, tmpfmt, len);
-      sprintf (tmpfmt, "%s: %s", fname, fmt);
-      va_list args;
-      va_start (args, fmt);
-      verror_with_id (id, tmpfmt, args);
-      va_end (args);
-    }
-  else
-    // Just set the error state; don't print msg.
-    error ("");
-
-  mex_context->abort ();
-}
-
-void
-mexWarnMsgTxt (const char *s)
-{
-  warning ("%s", s);
-}
-
-void
-mexWarnMsgIdAndTxt (const char *id, const char *fmt, ...)
-{
-  // FIXME -- is this right?  What does Matlab do if fmt is NULL or
-  // an empty string?
-
-  if (fmt && strlen (fmt) > 0)
-    {
-      const char *fname = mexFunctionName ();
-      size_t len = strlen (fname) + 2 + strlen (fmt) + 1;
-      OCTAVE_LOCAL_BUFFER (char, tmpfmt, len);
-      sprintf (tmpfmt, "%s: %s", fname, fmt);
-      va_list args;
-      va_start (args, fmt);
-      vwarning_with_id (id, tmpfmt, args);
-      va_end (args);
-    }
-}
-
-int
-mexPrintf (const char *fmt, ...)
-{
-  int retval;
-  va_list args;
-  va_start (args, fmt);
-  retval = octave_vformat (octave_stdout, fmt, args);
-  va_end (args);
-  return retval;
-}
-
-mxArray *
-mexGetVariable (const char *space, const char *name)
-{
-  mxArray *retval = 0;
-
-  octave_value val;
-
-  if (! strcmp (space, "global"))
-    val = get_global_value (name);
-  else
-    {
-      // FIXME -- should this be in variables.cc?
-
-      unwind_protect frame;
-
-      bool caller = ! strcmp (space, "caller");
-      bool base = ! strcmp (space, "base");
-
-      if (caller || base)
-        {
-          if (caller)
-            octave_call_stack::goto_caller_frame ();
-          else
-            octave_call_stack::goto_base_frame ();
-
-          if (! error_state)
-            frame.add_fcn (octave_call_stack::pop);
-
-          val = symbol_table::varval (name);
-        }
-      else
-        mexErrMsgTxt ("mexGetVariable: symbol table does not exist");
-    }
-
-  if (val.is_defined ())
-    {
-      retval = mex_context->make_value (val);
-
-      retval->set_name (name);
-    }
-
-  return retval;
-}
-
-const mxArray *
-mexGetVariablePtr (const char *space, const char *name)
-{
-  return mexGetVariable (space, name);
-}
-
-int
-mexPutVariable (const char *space, const char *name, mxArray *ptr)
-{
-  if (! ptr)
-    return 1;
-
-  if (! name)
-    return 1;
-
-  if (name[0] == '\0')
-    name = ptr->get_name ();
-
-  if (! name || name[0] == '\0')
-    return 1;
-
-  if (! strcmp (space, "global"))
-    set_global_value (name, mxArray::as_octave_value (ptr));
-  else
-    {
-      // FIXME -- should this be in variables.cc?
-
-      unwind_protect frame;
-
-      bool caller = ! strcmp (space, "caller");
-      bool base = ! strcmp (space, "base");
-
-      if (caller || base)
-        {
-          if (caller)
-            octave_call_stack::goto_caller_frame ();
-          else
-            octave_call_stack::goto_base_frame ();
-
-          if (! error_state)
-            frame.add_fcn (octave_call_stack::pop);
-
-          symbol_table::varref (name) = mxArray::as_octave_value (ptr);
-        }
-      else
-        mexErrMsgTxt ("mexPutVariable: symbol table does not exist");
-    }
-
-  return 0;
-}
-
-void
-mexMakeArrayPersistent (mxArray *ptr)
-{
-  maybe_unmark_array (ptr);
-}
-
-void
-mexMakeMemoryPersistent (void *ptr)
-{
-  maybe_unmark (ptr);
-}
-
-int
-mexAtExit (void (*f) (void))
-{
-  if (mex_context)
-    {
-      octave_mex_function *curr_mex_fcn = mex_context->current_mex_function ();
-
-      assert (curr_mex_fcn);
-
-      curr_mex_fcn->atexit (f);
-    }
-
-  return 0;
-}
-
-const mxArray *
-mexGet (double handle, const char *property)
-{
-  mxArray *m = 0;
-  octave_value ret = get_property_from_handle (handle, property, "mexGet");
-
-  if (!error_state && ret.is_defined ())
-    m = ret.as_mxArray ();
-  return m;
-}
-
-int
-mexIsGlobal (const mxArray *ptr)
-{
-  return mxIsFromGlobalWS (ptr);
-}
-
-int
-mexIsLocked (void)
-{
-  int retval = 0;
-
-  if (mex_context)
-    {
-      const char *fname = mexFunctionName ();
-
-      retval = mislocked (fname);
-    }
-
-  return retval;
-}
-
-std::map<std::string,int> mex_lock_count;
-
-void
-mexLock (void)
-{
-  if (mex_context)
-    {
-      const char *fname = mexFunctionName ();
-
-      if (mex_lock_count.find (fname) == mex_lock_count.end ())
-        mex_lock_count[fname] = 1;
-      else
-        mex_lock_count[fname]++;
-
-      mlock ();
-    }
-}
-
-int
-mexSet (double handle, const char *property, mxArray *val)
-{
-  bool ret =
-    set_property_in_handle (handle, property, mxArray::as_octave_value (val),
-                            "mexSet");
-  return (ret ? 0 : 1);
-}
-
-void
-mexUnlock (void)
-{
-  if (mex_context)
-    {
-      const char *fname = mexFunctionName ();
-
-      std::map<std::string,int>::iterator p = mex_lock_count.find (fname);
-
-      if (p != mex_lock_count.end ())
-        {
-          int count = --mex_lock_count[fname];
-
-          if (count == 0)
-            {
-              munlock (fname);
-
-              mex_lock_count.erase (p);
-            }
-        }
-    }
-}
--- a/src/mex.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,175 +0,0 @@
-/*
-
-Copyright (C) 2001-2012 Paul Kienzle
-
-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/>.
-
-*/
-
-/*
-
-This code was originally distributed as part of Octave Forge under
-the following terms:
-
-Author: Paul Kienzle
-I grant this code to the public domain.
-2001-03-22
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGE.
-
-*/
-
-/* mex.h is for use in C-programs only; do NOT include it in mex.cc */
-
-#if ! defined (MEX_H)
-#define MEX_H
-
-#define HAVE_OCTAVE
-
-typedef void mxArray;
-
-#if ! defined (__cplusplus)
-typedef int bool;
-#endif
-
-/* -V4 stuff */
-#if defined (V4)
-#define Matrix mxArray
-#define REAL mxREAL
-#endif
-
-#define mxMAXNAME 64
-
-#if defined (__cplusplus)
-extern "C" {
-#endif
-
-#if defined (V4)
-void mexFunction (int nlhs, mxArray* plhs[], int nrhs, mxArray *prhs[]);
-#else
-void mexFunction (int nlhs, mxArray* plhs[], int nrhs, const mxArray *prhs[]);
-#endif
-
-#include "mexproto.h"
-
-/* V4 floating point routines renamed in V5.  */
-#define mexIsNaN mxIsNaN
-#define mexIsFinite mxIsFinite
-#define mexIsInf mxIsInf
-#define mexGetEps mxGetEps
-#define mexGetInf mxGetInf
-#define mexGetNaN mxGetNan
-
-#define mexGetGlobal(nm) mexGetArray (nm, "global")
-#define mexGetMatrix(nm) mexGetArray (nm, "caller")
-#define mexGetMatrixPtr(nm) mexGetArrayPtr (nm, "caller")
-
-#define mexGetArray(nm, space) mexGetVariable (space, nm)
-#define mexGetArrayPtr(nm, space) mexGetVariablePtr (space, nm)
-
-#define mexPutMatrix(ptr) mexPutVariable ("caller", "", ptr)
-#define mexPutArray(ptr, space) mexPutVariable (space, "", ptr)
-
-#define mxCreateFull mxCreateDoubleMatrix
-
-#define mxCreateScalarDouble mxCreateDoubleScalar
-
-#define mxFreeMatrix mxDestroyArray
-
-#define mxIsString mxIsChar
-
-/* Apparently these are also defined.  */
-
-#ifndef UINT64_T
-#define UINT64_T uint64_t
-#endif
-
-#ifndef uint64_T
-#define uint64_T uint64_t
-#endif
-
-#ifndef INT64_T
-#define INT64_T int64_t
-#endif
-
-#ifndef int64_T
-#define int64_T int64_t
-#endif
-
-#ifndef UINT32_T
-#define UINT32_T uint32_t
-#endif
-
-#ifndef uint32_T
-#define uint32_T uint32_t
-#endif
-
-#ifndef INT32_T
-#define INT32_T int32_t
-#endif
-
-#ifndef int32_T
-#define int32_T int32_t
-#endif
-
-#ifndef UINT16_T
-#define UINT16_T uint16_t
-#endif
-
-#ifndef uint16_T
-#define uint16_T uint16_t
-#endif
-
-#ifndef INT16_T
-#define INT16_T int16_t
-#endif
-
-#ifndef int16_T
-#define int16_T int16_t
-#endif
-
-#ifndef UINT8_T
-#define UINT8_T uint8_t
-#endif
-
-#ifndef uint8_T
-#define uint8_T uint8_t
-#endif
-
-#ifndef INT8_T
-#define INT8_T int8_t
-#endif
-
-#ifndef int8_T
-#define int8_T int8_t
-#endif
-
-#if defined (__cplusplus)
-}
-#endif
-
-#endif
--- a/src/mexproto.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,279 +0,0 @@
-/*
-
-Copyright (C) 2006-2012 Paul Kienzle
-
-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/>.
-
-*/
-
-/*
-
-This code was originally distributed as part of Octave Forge under
-the following terms:
-
-Author: Paul Kienzle
-I grant this code to the public domain.
-2001-03-22
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGE.
-
-*/
-
-/* mex.h is for use in C-programs only; do NOT include it in mex.cc */
-
-#if ! defined (MEXPROTO_H)
-#define MEXPROTO_H
-
-#if defined (__cplusplus)
-#include <cstdlib>
-extern "C" {
-#else
-#include <stdlib.h>
-#endif
-
-/* The definition of OCTINTERP_API is normally provided by Octave's
-   config.h file.  This is provided for the case of mex.h included by
-   user programs that don't use Octave's config.h.  */
-#if ! defined (OCTINTERP_API)
-#if defined (_MSC_VER)
-#define OCTINTERP_API __declspec(dllimport)
-#else
-/* All other compilers, at least for now.  */
-#define OCTINTERP_API
-#endif
-#endif
-
-#define MXARRAY_TYPEDEFS_ONLY
-#include "mxarray.h"
-#undef MXARRAY_TYPEDEFS_ONLY
-
-/* Interface to the interpreter.  */
-extern OCTINTERP_API const char *mexFunctionName (void);
-
-extern OCTINTERP_API int mexCallMATLAB (int nargout, mxArray *argout[], int nargin, mxArray *argin[], const char *fname);
-
-extern OCTINTERP_API void mexSetTrapFlag (int flag);
-extern OCTINTERP_API int mexEvalString (const char *s);
-extern OCTINTERP_API void mexErrMsgTxt (const char *s);
-extern OCTINTERP_API void mexErrMsgIdAndTxt (const char *id, const char *s, ...);
-extern OCTINTERP_API void mexWarnMsgTxt (const char *s);
-extern OCTINTERP_API void mexWarnMsgIdAndTxt (const char *id, const char *s, ...);
-extern OCTINTERP_API int mexPrintf (const char *fmt, ...);
-
-extern OCTINTERP_API mxArray *mexGetVariable (const char *space, const char *name);
-extern OCTINTERP_API const mxArray *mexGetVariablePtr (const char *space, const char *name);
-
-extern OCTINTERP_API int mexPutVariable (const char *space, const char *name, mxArray *ptr);
-
-extern OCTINTERP_API void mexMakeArrayPersistent (mxArray *ptr);
-extern OCTINTERP_API void mexMakeMemoryPersistent (void *ptr);
-
-extern OCTINTERP_API int mexAtExit (void (*f) (void));
-extern OCTINTERP_API const mxArray *mexGet (double handle, const char *property);
-extern OCTINTERP_API int mexIsGlobal (const mxArray *ptr);
-extern OCTINTERP_API int mexIsLocked (void);
-extern OCTINTERP_API void mexLock (void);
-extern OCTINTERP_API int mexSet (double handle, const char *property, mxArray *val);
-extern OCTINTERP_API void mexUnlock (void);
-
-/* Floating point predicates.  */
-extern OCTINTERP_API int mxIsFinite (double v);
-extern OCTINTERP_API int mxIsInf (double v);
-extern OCTINTERP_API int mxIsNaN (double v);
-
-/* Floating point values.  */
-extern OCTINTERP_API double mxGetEps (void);
-extern OCTINTERP_API double mxGetInf (void);
-extern OCTINTERP_API double mxGetNaN (void);
-
-/* Memory management.  */
-extern OCTINTERP_API void *mxCalloc (size_t n, size_t size);
-extern OCTINTERP_API void *mxMalloc (size_t n);
-extern OCTINTERP_API void *mxRealloc (void *ptr, size_t size);
-extern OCTINTERP_API void mxFree (void *ptr);
-
-/* Constructors.  */
-extern OCTINTERP_API mxArray *mxCreateCellArray (mwSize ndims, const mwSize *dims);
-extern OCTINTERP_API mxArray *mxCreateCellMatrix (mwSize m, mwSize n);
-extern OCTINTERP_API mxArray *mxCreateCharArray (mwSize ndims, const mwSize *dims);
-extern OCTINTERP_API mxArray *mxCreateCharMatrixFromStrings (mwSize m, const char **str);
-extern OCTINTERP_API mxArray *mxCreateDoubleMatrix (mwSize nr, mwSize nc, mxComplexity flag);
-extern OCTINTERP_API mxArray *mxCreateDoubleScalar (double val);
-extern OCTINTERP_API mxArray *mxCreateLogicalArray (mwSize ndims, const mwSize *dims);
-extern OCTINTERP_API mxArray *mxCreateLogicalMatrix (mwSize m, mwSize n);
-extern OCTINTERP_API mxArray *mxCreateLogicalScalar (mxLogical val);
-extern OCTINTERP_API mxArray *mxCreateNumericArray (mwSize ndims, const mwSize *dims, mxClassID class_id, mxComplexity flag);
-extern OCTINTERP_API mxArray *mxCreateNumericMatrix (mwSize m, mwSize n, mxClassID class_id, mxComplexity flag);
-extern OCTINTERP_API mxArray *mxCreateSparse (mwSize m, mwSize n, mwSize nzmax, mxComplexity flag);
-extern OCTINTERP_API mxArray *mxCreateSparseLogicalMatrix (mwSize m, mwSize n, mwSize nzmax);
-extern OCTINTERP_API mxArray *mxCreateString (const char *str);
-extern OCTINTERP_API mxArray *mxCreateStructArray (mwSize ndims, const mwSize *dims, int num_keys, const char **keys);
-extern OCTINTERP_API mxArray *mxCreateStructMatrix (mwSize rows, mwSize cols, int num_keys, const char **keys);
-
-/* Copy constructor.  */
-extern OCTINTERP_API mxArray *mxDuplicateArray (const mxArray *v);
-
-/* Destructor.  */
-extern OCTINTERP_API void mxDestroyArray (mxArray *v);
-
-/* Type Predicates.  */
-extern OCTINTERP_API int mxIsCell (const mxArray *ptr);
-extern OCTINTERP_API int mxIsChar (const mxArray *ptr);
-extern OCTINTERP_API int mxIsClass (const mxArray *ptr, const char *name);
-extern OCTINTERP_API int mxIsComplex (const mxArray *ptr);
-extern OCTINTERP_API int mxIsDouble (const mxArray *ptr);
-extern OCTINTERP_API int mxIsFunctionHandle (const mxArray *ptr);
-extern OCTINTERP_API int mxIsInt16 (const mxArray *ptr);
-extern OCTINTERP_API int mxIsInt32 (const mxArray *ptr);
-extern OCTINTERP_API int mxIsInt64 (const mxArray *ptr);
-extern OCTINTERP_API int mxIsInt8 (const mxArray *ptr);
-extern OCTINTERP_API int mxIsLogical (const mxArray *ptr);
-extern OCTINTERP_API int mxIsNumeric (const mxArray *ptr);
-extern OCTINTERP_API int mxIsSingle (const mxArray *ptr);
-extern OCTINTERP_API int mxIsSparse (const mxArray *ptr);
-extern OCTINTERP_API int mxIsStruct (const mxArray *ptr);
-extern OCTINTERP_API int mxIsUint16 (const mxArray *ptr);
-extern OCTINTERP_API int mxIsUint32 (const mxArray *ptr);
-extern OCTINTERP_API int mxIsUint64 (const mxArray *ptr);
-extern OCTINTERP_API int mxIsUint8 (const mxArray *ptr);
-
-/* Odd type+size predicate.  */
-extern OCTINTERP_API int mxIsLogicalScalar (const mxArray *ptr);
-
-/* Odd type+size+value predicate.  */
-extern OCTINTERP_API int mxIsLogicalScalarTrue (const mxArray *ptr);
-
-/* Size predicate.  */
-extern OCTINTERP_API int mxIsEmpty (const mxArray *ptr);
-
-/* Just plain odd thing to ask of a value.  */
-extern OCTINTERP_API int mxIsFromGlobalWS (const mxArray *ptr);
-
-/* Dimension extractors.  */
-extern OCTINTERP_API size_t mxGetM (const mxArray *ptr);
-extern OCTINTERP_API size_t mxGetN (const mxArray *ptr);
-extern OCTINTERP_API mwSize *mxGetDimensions (const mxArray *ptr);
-extern OCTINTERP_API mwSize mxGetNumberOfDimensions (const mxArray *ptr);
-extern OCTINTERP_API size_t mxGetNumberOfElements (const mxArray *ptr);
-
-/* Dimension setters.  */
-extern OCTINTERP_API void mxSetM (mxArray *ptr, mwSize M);
-extern OCTINTERP_API void mxSetN (mxArray *ptr, mwSize N);
-extern OCTINTERP_API void mxSetDimensions (mxArray *ptr, const mwSize *dims, mwSize ndims);
-
-/* Data extractors.  */
-extern OCTINTERP_API double *mxGetPi (const mxArray *ptr);
-extern OCTINTERP_API double *mxGetPr (const mxArray *ptr);
-extern OCTINTERP_API double mxGetScalar (const mxArray *ptr);
-extern OCTINTERP_API mxChar *mxGetChars (const mxArray *ptr);
-extern OCTINTERP_API mxLogical *mxGetLogicals (const mxArray *ptr);
-extern OCTINTERP_API void *mxGetData (const mxArray *ptr);
-extern OCTINTERP_API void *mxGetImagData (const mxArray *ptr);
-
-/* Data setters.  */
-extern OCTINTERP_API void mxSetPr (mxArray *ptr, double *pr);
-extern OCTINTERP_API void mxSetPi (mxArray *ptr, double *pi);
-extern OCTINTERP_API void mxSetData (mxArray *ptr, void *data);
-extern OCTINTERP_API void mxSetImagData (mxArray *ptr, void *pi);
-
-/* Classes.  */
-extern OCTINTERP_API mxClassID mxGetClassID (const mxArray *ptr);
-extern OCTINTERP_API const char *mxGetClassName (const mxArray *ptr);
-
-extern OCTINTERP_API void mxSetClassName (mxArray *ptr, const char *name);
-
-/* Cell support.  */
-extern OCTINTERP_API mxArray *mxGetCell (const mxArray *ptr, mwIndex idx);
-
-extern OCTINTERP_API void mxSetCell (mxArray *ptr, mwIndex idx, mxArray *val);
-
-/* Sparse support.  */
-extern OCTINTERP_API mwIndex *mxGetIr (const mxArray *ptr);
-extern OCTINTERP_API mwIndex *mxGetJc (const mxArray *ptr);
-extern OCTINTERP_API mwSize mxGetNzmax (const mxArray *ptr);
-
-extern OCTINTERP_API void mxSetIr (mxArray *ptr, mwIndex *ir);
-extern OCTINTERP_API void mxSetJc (mxArray *ptr, mwIndex *jc);
-extern OCTINTERP_API void mxSetNzmax (mxArray *ptr, mwSize nzmax);
-
-/* Structure support.  */
-extern OCTINTERP_API int mxAddField (mxArray *ptr, const char *key);
-
-extern OCTINTERP_API void mxRemoveField (mxArray *ptr, int key_num);
-
-extern OCTINTERP_API mxArray *mxGetField (const mxArray *ptr, mwIndex index, const char *key);
-extern OCTINTERP_API mxArray *mxGetFieldByNumber (const mxArray *ptr, mwIndex index, int key_num);
-
-extern OCTINTERP_API void mxSetField (mxArray *ptr, mwIndex index, const char *key, mxArray *val);
-extern OCTINTERP_API void mxSetFieldByNumber (mxArray *ptr, mwIndex index, int key_num, mxArray *val);
-
-extern OCTINTERP_API int mxGetNumberOfFields (const mxArray *ptr);
-
-extern OCTINTERP_API const char *mxGetFieldNameByNumber (const mxArray *ptr, int key_num);
-extern OCTINTERP_API int mxGetFieldNumber (const mxArray *ptr, const char *key);
-
-extern OCTINTERP_API int mxGetString (const mxArray *ptr, char *buf, mwSize buflen);
-extern OCTINTERP_API char *mxArrayToString (const mxArray *ptr);
-
-/* Miscellaneous.  */
-#ifdef NDEBUG
-#define mxAssert(expr, msg) \
-  do \
-    { \
-      if (! expr) \
-        { \
-          mexPrintf ("Assertion failed: %s, at line %d of file \"%s\".\n%s\n", \
-                     #expr, __LINE__, __FILE__, msg); \
-        } \
-    } \
-  while (0)
-
-#define mxAssertS(expr, msg) \
-  do \
-    { \
-      if (! expr) \
-        { \
-          mexPrintf ("Assertion failed at line %d of file \"%s\".\n%s\n", \
-                     __LINE__, __FILE__, msg); \
-          abort (); \
-        } \
-    } \
-  while (0)
-#else
-#define mxAssert(expr, msg)
-#define mxAssertS(expr, msg)
-#endif
-
-extern OCTINTERP_API mwIndex mxCalcSingleSubscript (const mxArray *ptr, mwSize nsubs, mwIndex *subs);
-
-extern OCTINTERP_API size_t mxGetElementSize (const mxArray *ptr);
-
-#if defined (__cplusplus)
-}
-#endif
-
-#endif
--- a/src/mxarray.in.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,348 +0,0 @@
-// DO NOT EDIT!  Generated automatically from mxarray.in.h by configure
-/*
-
-Copyright (C) 2001-2012 Paul Kienzle
-
-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/>.
-
-*/
-
-/*
-
-Part of this code was originally distributed as part of Octave Forge under
-the following terms:
-
-Author: Paul Kienzle
-I grant this code to the public domain.
-2001-03-22
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGE.
-
-*/
-
-#if ! defined (MXARRAY_H)
-#define MXARRAY_H
-
-typedef enum
-  {
-    mxREAL = 0,
-    mxCOMPLEX = 1
-  }
-  mxComplexity;
-
-typedef enum
-  {
-    mxUNKNOWN_CLASS = 0,
-    mxCELL_CLASS,
-    mxSTRUCT_CLASS,
-    mxLOGICAL_CLASS,
-    mxCHAR_CLASS,
-    mxUNUSED_CLASS,
-    mxDOUBLE_CLASS,
-    mxSINGLE_CLASS,
-    mxINT8_CLASS,
-    mxUINT8_CLASS,
-    mxINT16_CLASS,
-    mxUINT16_CLASS,
-    mxINT32_CLASS,
-    mxUINT32_CLASS,
-    mxINT64_CLASS,
-    mxUINT64_CLASS,
-    mxFUNCTION_CLASS
-  }
-  mxClassID;
-
-typedef unsigned char mxLogical;
-
-/* typedef Uint16 mxChar; */
-typedef char mxChar;
-
-/*
- * FIXME? Mathworks says these should be size_t on 64-bit system and when
- * mex is used with the -largearraydims flag, but why do that? Its better
- * to conform to the same indexing as the rest of Octave
- */
-typedef %OCTAVE_IDX_TYPE% mwSize;
-typedef %OCTAVE_IDX_TYPE% mwIndex;
-
-#if ! defined (MXARRAY_TYPEDEFS_ONLY)
-
-#include <cstring>
-
-class octave_value;
-
-#define DO_MUTABLE_METHOD(RET_T, METHOD_CALL) \
-  RET_T retval = rep->METHOD_CALL; \
- \
-  if (rep->mutation_needed ()) \
-    { \
-      maybe_mutate (); \
-      retval = rep->METHOD_CALL; \
-    } \
- \
-  return retval
-
-#define DO_VOID_MUTABLE_METHOD(METHOD_CALL) \
-  rep->METHOD_CALL; \
- \
-  if (rep->mutation_needed ()) \
-    { \
-      maybe_mutate (); \
-      rep->METHOD_CALL; \
-    }
-
-// This just provides a way to avoid infinite recursion when building
-// mxArray objects.
-
-struct
-xmxArray
-{
-  xmxArray (void) { }
-};
-
-// The main interface class.  The representation can be based on an
-// octave_value object or a separate object that tries to reproduce
-// the semantics of mxArray objects in Matlab more directly.
-
-class mxArray
-{
-public:
-
-  mxArray (const octave_value& ov);
-
-  mxArray (mxClassID id, mwSize ndims, const mwSize *dims,
-           mxComplexity flag = mxREAL);
-
-  mxArray (mxClassID id, const dim_vector& dv, mxComplexity flag = mxREAL);
-
-  mxArray (mxClassID id, mwSize m, mwSize n, mxComplexity flag = mxREAL);
-
-  mxArray (mxClassID id, double val);
-
-  mxArray (mxClassID id, mxLogical val);
-
-  mxArray (const char *str);
-
-  mxArray (mwSize m, const char **str);
-
-  mxArray (mxClassID id, mwSize m, mwSize n, mwSize nzmax,
-           mxComplexity flag = mxREAL);
-
-  mxArray (mwSize ndims, const mwSize *dims, int num_keys, const char **keys);
-
-  mxArray (const dim_vector& dv, int num_keys, const char **keys);
-
-  mxArray (mwSize m, mwSize n, int num_keys, const char **keys);
-
-  mxArray (mwSize ndims, const mwSize *dims);
-
-  mxArray (const dim_vector& dv);
-
-  mxArray (mwSize m, mwSize n);
-
-  virtual mxArray *dup (void) const
-  {
-    mxArray *new_rep = rep->dup ();
-
-    return new mxArray (new_rep, name);
-  }
-
-  virtual ~mxArray (void);
-
-  virtual bool is_octave_value (void) const { return rep->is_octave_value (); }
-
-  virtual int is_cell (void) const { return rep->is_cell (); }
-
-  virtual int is_char (void) const { return rep->is_char (); }
-
-  virtual int is_class (const char *name_arg) const { return rep->is_class (name_arg); }
-
-  virtual int is_complex (void) const { return rep->is_complex (); }
-
-  virtual int is_double (void) const { return rep->is_double (); }
-
-  virtual int is_function_handle (void) const { return rep->is_function_handle (); }
-
-  virtual int is_int16 (void) const { return rep->is_int16 (); }
-
-  virtual int is_int32 (void) const { return rep->is_int32 (); }
-
-  virtual int is_int64 (void) const { return rep->is_int64 (); }
-
-  virtual int is_int8 (void) const { return rep->is_int8 (); }
-
-  virtual int is_logical (void) const { return rep->is_logical (); }
-
-  virtual int is_numeric (void) const { return rep->is_numeric (); }
-
-  virtual int is_single (void) const { return rep->is_single (); }
-
-  virtual int is_sparse (void) const { return rep->is_sparse (); }
-
-  virtual int is_struct (void) const { return rep->is_struct (); }
-
-  virtual int is_uint16 (void) const { return rep->is_uint16 (); }
-
-  virtual int is_uint32 (void) const { return rep->is_uint32 (); }
-
-  virtual int is_uint64 (void) const { return rep->is_uint64 (); }
-
-  virtual int is_uint8 (void) const { return rep->is_uint8 (); }
-
-  virtual int is_logical_scalar (void) const { return rep->is_logical_scalar (); }
-
-  virtual int is_logical_scalar_true (void) const { return rep->is_logical_scalar_true (); }
-
-  virtual mwSize get_m (void) const { return rep->get_m (); }
-
-  virtual mwSize get_n (void) const { return rep->get_n (); }
-
-  virtual mwSize *get_dimensions (void) const { return rep->get_dimensions (); }
-
-  virtual mwSize get_number_of_dimensions (void) const { return rep->get_number_of_dimensions (); }
-
-  virtual void set_m (mwSize m) { DO_VOID_MUTABLE_METHOD (set_m (m)); }
-
-  virtual void set_n (mwSize n) { DO_VOID_MUTABLE_METHOD (set_n (n)); }
-
-  virtual void set_dimensions (mwSize *dims_arg, mwSize ndims_arg) { DO_VOID_MUTABLE_METHOD (set_dimensions (dims_arg, ndims_arg)); }
-
-  virtual mwSize get_number_of_elements (void) const { return rep->get_number_of_elements (); }
-
-  virtual int is_empty (void) const { return get_number_of_elements () == 0; }
-
-  const char *get_name (void) const { return name; }
-
-  void set_name (const char *name_arg);
-
-  virtual mxClassID get_class_id (void) const { return rep->get_class_id (); }
-
-  virtual const char *get_class_name (void) const { return rep->get_class_name (); }
-
-  virtual void set_class_name (const char *name_arg) { DO_VOID_MUTABLE_METHOD (set_class_name (name_arg)); }
-
-  virtual mxArray *get_cell (mwIndex idx) const { DO_MUTABLE_METHOD (mxArray *, get_cell (idx)); }
-
-  virtual void set_cell (mwIndex idx, mxArray *val) { DO_VOID_MUTABLE_METHOD (set_cell (idx, val)); }
-
-  virtual double get_scalar (void) const { return rep->get_scalar (); }
-
-  virtual void *get_data (void) const { DO_MUTABLE_METHOD (void *, get_data ()); }
-
-  virtual void *get_imag_data (void) const { DO_MUTABLE_METHOD (void *, get_imag_data ()); }
-
-  virtual void set_data (void *pr) { DO_VOID_MUTABLE_METHOD (set_data (pr)); }
-
-  virtual void set_imag_data (void *pi) { DO_VOID_MUTABLE_METHOD (set_imag_data (pi)); }
-
-  virtual mwIndex *get_ir (void) const { DO_MUTABLE_METHOD (mwIndex *, get_ir ()); }
-
-  virtual mwIndex *get_jc (void) const { DO_MUTABLE_METHOD (mwIndex *, get_jc ()); }
-
-  virtual mwSize get_nzmax (void) const { return rep->get_nzmax (); }
-
-  virtual void set_ir (mwIndex *ir) { DO_VOID_MUTABLE_METHOD (set_ir (ir)); }
-
-  virtual void set_jc (mwIndex *jc) { DO_VOID_MUTABLE_METHOD (set_jc (jc)); }
-
-  virtual void set_nzmax (mwSize nzmax) { DO_VOID_MUTABLE_METHOD (set_nzmax (nzmax)); }
-
-  virtual int add_field (const char *key) { DO_MUTABLE_METHOD (int, add_field (key)); }
-
-  virtual void remove_field (int key_num) { DO_VOID_MUTABLE_METHOD (remove_field (key_num)); }
-
-  virtual mxArray *get_field_by_number (mwIndex index, int key_num) const { DO_MUTABLE_METHOD (mxArray *, get_field_by_number (index, key_num)); }
-
-  virtual void set_field_by_number (mwIndex index, int key_num, mxArray *val) { DO_VOID_MUTABLE_METHOD (set_field_by_number (index, key_num, val)); }
-
-  virtual int get_number_of_fields (void) const { return rep->get_number_of_fields (); }
-
-  virtual const char *get_field_name_by_number (int key_num) const { DO_MUTABLE_METHOD (const char*, get_field_name_by_number (key_num)); }
-
-  virtual int get_field_number (const char *key) const { DO_MUTABLE_METHOD (int, get_field_number (key)); }
-
-  virtual int get_string (char *buf, mwSize buflen) const { return rep->get_string (buf, buflen); }
-
-  virtual char *array_to_string (void) const { return rep->array_to_string (); }
-
-  virtual mwIndex calc_single_subscript (mwSize nsubs, mwIndex *subs) const { return rep->calc_single_subscript (nsubs, subs); }
-
-  virtual size_t get_element_size (void) const { return rep->get_element_size (); }
-
-  virtual bool mutation_needed (void) const { return rep->mutation_needed (); }
-
-  virtual mxArray *mutate (void) const { return rep->mutate (); }
-
-  static void *malloc (size_t n);
-
-  static void *calloc (size_t n, size_t t);
-
-  static char *strsave (const char *str)
-  {
-    char *retval = 0;
-
-    if (str)
-      {
-        mwSize sz =  sizeof (mxChar) * (strlen (str) + 1);
-        retval = static_cast<char *> (mxArray::malloc (sz));
-        strcpy (retval, str);
-      }
-
-    return retval;
-  }
-
-  static octave_value as_octave_value (mxArray *ptr);
-
-protected:
-
-  virtual octave_value as_octave_value (void) const;
-
-  mxArray (const xmxArray&) : rep (0), name (0) { }
-
-private:
-
-  mutable mxArray *rep;
-
-  char *name;
-
-  mxArray (mxArray *r, const char *n)
-    : rep (r), name (strsave (n)) { }
-
-  void maybe_mutate (void) const;
-
-  // No copying!
-
-  mxArray (const mxArray&);
-
-  mxArray& operator = (const mxArray&);
-};
-
-#undef DO_MUTABLE_METHOD
-#undef DO_VOID_MUTABLE_METHOD
-
-#endif
-#endif
--- a/src/oct-errno.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-// oct-errno.h.in
-/*
-
-Copyright (C) 2005-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#if !defined (octave_errno_h)
-#define octave_errno_h 1
-
-#include <cerrno>
-#include <map>
-#include <string>
-
-#include "oct-map.h"
-
-class
-octave_errno
-{
-protected:
-
-  octave_errno (void);
-
-public:
-
-  ~octave_errno (void) { }
-
-  static bool instance_ok (void);
-
-  static void cleanup_instance (void) { delete instance; instance = 0; }
-
-  static int lookup (const std::string& name);
-
-  static octave_scalar_map list (void);
-
-  static int get (void) { return errno; }
-
-  static int set (int val)
-  {
-    int retval = errno;
-    errno = val;
-    return retval;
-  }
-
-private:
-
-  std::map<std::string, int> errno_tbl;
-
-  static octave_errno *instance;
-
-  int do_lookup (const std::string& name);
-
-  octave_scalar_map do_list (void);
-};
-
-#endif
--- a/src/oct-errno.in.cc	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,345 +0,0 @@
-// oct-errno.cc.in
-/*
-
-Copyright (C) 2005-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <cerrno>
-
-#include "singleton-cleanup.h"
-
-#include "oct-errno.h"
-#include "oct-map.h"
-#include "error.h"
-
-octave_errno *octave_errno::instance = 0;
-
-octave_errno::octave_errno (void)
-{
-  struct errno_struct
-  {
-    const char *name;
-    int value;
-  };
-
-  static errno_struct errno_codes[] =
-  {
-    // POSIX.
-
-#if defined (E2BIG)
-    { "E2BIG", E2BIG, },
-#endif
-#if defined (EACCES)
-    { "EACCES", EACCES, },
-#endif
-#if defined (EADDRINUSE)
-    { "EADDRINUSE", EADDRINUSE, },
-#endif
-#if defined (EADDRNOTAVAIL)
-    { "EADDRNOTAVAIL", EADDRNOTAVAIL, },
-#endif
-#if defined (EAFNOSUPPORT)
-    { "EAFNOSUPPORT", EAFNOSUPPORT, },
-#endif
-#if defined (EAGAIN)
-    { "EAGAIN", EAGAIN, },
-#endif
-#if defined (EALREADY)
-    { "EALREADY", EALREADY, },
-#endif
-#if defined (EBADF)
-    { "EBADF", EBADF, },
-#endif
-#if defined (EBUSY)
-    { "EBUSY", EBUSY, },
-#endif
-#if defined (ECHILD)
-    { "ECHILD", ECHILD, },
-#endif
-#if defined (ECONNABORTED)
-    { "ECONNABORTED", ECONNABORTED, },
-#endif
-#if defined (ECONNREFUSED)
-    { "ECONNREFUSED", ECONNREFUSED, },
-#endif
-#if defined (ECONNRESET)
-    { "ECONNRESET", ECONNRESET, },
-#endif
-#if defined (EDEADLK)
-    { "EDEADLK", EDEADLK, },
-#endif
-#if defined (EDESTADDRREQ)
-    { "EDESTADDRREQ", EDESTADDRREQ, },
-#endif
-#if defined (EDOM)
-    { "EDOM", EDOM, },
-#endif
-#if defined (EDQUOT)
-    { "EDQUOT", EDQUOT, },
-#endif
-#if defined (EEXIST)
-    { "EEXIST", EEXIST, },
-#endif
-#if defined (EFAULT)
-    { "EFAULT", EFAULT, },
-#endif
-#if defined (EFBIG)
-    { "EFBIG", EFBIG, },
-#endif
-#if defined (EHOSTDOWN)
-    { "EHOSTDOWN", EHOSTDOWN, },
-#endif
-#if defined (EHOSTUNREACH)
-    { "EHOSTUNREACH", EHOSTUNREACH, },
-#endif
-#if defined (EINPROGRESS)
-    { "EINPROGRESS", EINPROGRESS, },
-#endif
-#if defined (EINTR)
-    { "EINTR", EINTR, },
-#endif
-#if defined (EINVAL)
-    { "EINVAL", EINVAL, },
-#endif
-#if defined (EIO)
-    { "EIO", EIO, },
-#endif
-#if defined (EISCONN)
-    { "EISCONN", EISCONN, },
-#endif
-#if defined (EISDIR)
-    { "EISDIR", EISDIR, },
-#endif
-#if defined (ELOOP)
-    { "ELOOP", ELOOP, },
-#endif
-#if defined (EMFILE)
-    { "EMFILE", EMFILE, },
-#endif
-#if defined (EMLINK)
-    { "EMLINK", EMLINK, },
-#endif
-#if defined (EMSGSIZE)
-    { "EMSGSIZE", EMSGSIZE, },
-#endif
-#if defined (ENAMETOOLONG)
-    { "ENAMETOOLONG", ENAMETOOLONG, },
-#endif
-#if defined (ENETDOWN)
-    { "ENETDOWN", ENETDOWN, },
-#endif
-#if defined (ENETRESET)
-    { "ENETRESET", ENETRESET, },
-#endif
-#if defined (ENETUNREACH)
-    { "ENETUNREACH", ENETUNREACH, },
-#endif
-#if defined (ENFILE)
-    { "ENFILE", ENFILE, },
-#endif
-#if defined (ENOBUFS)
-    { "ENOBUFS", ENOBUFS, },
-#endif
-#if defined (ENODEV)
-    { "ENODEV", ENODEV, },
-#endif
-#if defined (ENOENT)
-    { "ENOENT", ENOENT, },
-#endif
-#if defined (ENOEXEC)
-    { "ENOEXEC", ENOEXEC, },
-#endif
-#if defined (ENOLCK)
-    { "ENOLCK", ENOLCK, },
-#endif
-#if defined (ENOMEM)
-    { "ENOMEM", ENOMEM, },
-#endif
-#if defined (ENOPROTOOPT)
-    { "ENOPROTOOPT", ENOPROTOOPT, },
-#endif
-#if defined (ENOSPC)
-    { "ENOSPC", ENOSPC, },
-#endif
-#if defined (ENOSYS)
-    { "ENOSYS", ENOSYS, },
-#endif
-#if defined (ENOTBLK)
-    { "ENOTBLK", ENOTBLK, },
-#endif
-#if defined (ENOTCONN)
-    { "ENOTCONN", ENOTCONN, },
-#endif
-#if defined (ENOTDIR)
-    { "ENOTDIR", ENOTDIR, },
-#endif
-#if defined (ENOTEMPTY)
-    { "ENOTEMPTY", ENOTEMPTY, },
-#endif
-#if defined (ENOTSOCK)
-    { "ENOTSOCK", ENOTSOCK, },
-#endif
-#if defined (ENOTTY)
-    { "ENOTTY", ENOTTY, },
-#endif
-#if defined (ENXIO)
-    { "ENXIO", ENXIO, },
-#endif
-#if defined (EOPNOTSUPP)
-    { "EOPNOTSUPP", EOPNOTSUPP, },
-#endif
-#if defined (EPERM)
-    { "EPERM", EPERM, },
-#endif
-#if defined (EPFNOSUPPORT)
-    { "EPFNOSUPPORT", EPFNOSUPPORT, },
-#endif
-#if defined (EPIPE)
-    { "EPIPE", EPIPE, },
-#endif
-#if defined (EPROTONOSUPPORT)
-    { "EPROTONOSUPPORT", EPROTONOSUPPORT, },
-#endif
-#if defined (EPROTOTYPE)
-    { "EPROTOTYPE", EPROTOTYPE, },
-#endif
-#if defined (ERANGE)
-    { "ERANGE", ERANGE, },
-#endif
-#if defined (EREMOTE)
-    { "EREMOTE", EREMOTE, },
-#endif
-#if defined (ERESTART)
-    { "ERESTART", ERESTART, },
-#endif
-#if defined (EROFS)
-    { "EROFS", EROFS, },
-#endif
-#if defined (ESHUTDOWN)
-    { "ESHUTDOWN", ESHUTDOWN, },
-#endif
-#if defined (ESOCKTNOSUPPORT)
-    { "ESOCKTNOSUPPORT", ESOCKTNOSUPPORT, },
-#endif
-#if defined (ESPIPE)
-    { "ESPIPE", ESPIPE, },
-#endif
-#if defined (ESRCH)
-    { "ESRCH", ESRCH, },
-#endif
-#if defined (ESTALE)
-    { "ESTALE", ESTALE, },
-#endif
-#if defined (ETIMEDOUT)
-    { "ETIMEDOUT", ETIMEDOUT, },
-#endif
-#if defined (ETOOMANYREFS)
-    { "ETOOMANYREFS", ETOOMANYREFS, },
-#endif
-#if defined (ETXTBSY)
-    { "ETXTBSY", ETXTBSY, },
-#endif
-#if defined (EUSERS)
-    { "EUSERS", EUSERS, },
-#endif
-#if defined (EWOULDBLOCK)
-    { "EWOULDBLOCK", EWOULDBLOCK, },
-#endif
-#if defined (EXDEV)
-    { "EXDEV", EXDEV, },
-#endif
-
-    // Others (duplicates are OK).
-
-@SYSDEP_ERRNO_LIST@
-
-    { 0, 0, },
-  };
-
-  // Stuff them all in a map for fast access.
-
-  errno_struct *ptr = errno_codes;
-
-  while (ptr->name)
-    {
-      errno_tbl[ptr->name] = ptr->value;
-      ptr++;
-    }
-}
-
-bool
-octave_errno::instance_ok (void)
-{
-  bool retval = true;
-
-  if (! instance)
-    {
-      instance = new octave_errno ();
-
-      if (instance)
-        singleton_cleanup_list::add (cleanup_instance);
-    }
-
-  if (! instance)
-    {
-      ::error ("unable to create errno object!");
-
-      retval = false;
-    }
-
-  return retval;
-}
-
-int
-octave_errno::lookup (const std::string& name)
-{
-  return (instance_ok ()) ? instance->do_lookup (name) : -1;
-}
-
-octave_scalar_map
-octave_errno::list (void)
-{
-  return (instance_ok ()) ? instance->do_list () : octave_scalar_map ();
-}
-
-int
-octave_errno::do_lookup (const std::string& name)
-{
-  return (errno_tbl.find (name) != errno_tbl.end ()) ? errno_tbl[name] : -1;
-}
-
-octave_scalar_map
-octave_errno::do_list (void)
-{
-  octave_scalar_map retval;
-
-  for (std::map<std::string, int>::const_iterator p = errno_tbl.begin ();
-       p != errno_tbl.end ();
-       p++)
-    {
-      retval.assign (p->first, p->second);
-    }
-
-  return retval;
-}
--- a/src/oct-fstrm.cc	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,114 +0,0 @@
-/*
-
-Copyright (C) 1996-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <cerrno>
-#include <cstring>
-
-#include "error.h"
-#include "oct-fstrm.h"
-
-octave_stream
-octave_fstream::create (const std::string& nm_arg, std::ios::openmode arg_md,
-                        oct_mach_info::float_format ff)
-{
-  return octave_stream (new octave_fstream (nm_arg, arg_md, ff));
-}
-
-octave_fstream::octave_fstream (const std::string& nm_arg,
-                                std::ios::openmode arg_md,
-                                oct_mach_info::float_format ff)
-  : octave_base_stream (arg_md, ff), nm (nm_arg)
-{
-
-#if CXX_ISO_COMPLIANT_LIBRARY
-
-  fs.open (nm.c_str (), arg_md);
-
-#else
-  // Override default protection of 0664 so that umask will appear to
-  // do the right thing.
-
-  fs.open (nm.c_str (), arg_md, 0666);
-
-#endif
-
-  if (! fs)
-    error (gnulib::strerror (errno));
-}
-
-// Position a stream at OFFSET relative to ORIGIN.
-
-int
-octave_fstream::seek (long, int)
-{
-  error ("fseek: invalid_operation");
-  return -1;
-}
-
-// Return current stream position.
-
-long
-octave_fstream::tell (void)
-{
-  error ("ftell: invalid_operation");
-  return -1;
-}
-
-// Return non-zero if EOF has been reached on this stream.
-
-bool
-octave_fstream::eof (void) const
-{
-  return fs.eof ();
-}
-
-void
-octave_fstream::do_close (void)
-{
-  fs.close ();
-}
-
-std::istream *
-octave_fstream::input_stream (void)
-{
-  std::istream *retval = 0;
-
-  if (mode () & std::ios::in)
-    retval = &fs;
-
-  return retval;
-}
-
-std::ostream *
-octave_fstream::output_stream (void)
-{
-  std::ostream *retval = 0;
-
-  if (mode () & std::ios::out)
-    retval = &fs;
-
-  return retval;
-}
--- a/src/oct-fstrm.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,86 +0,0 @@
-/*
-
-Copyright (C) 1996-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#if !defined (octave_octave_fstream_h)
-#define octave_octave_fstream_h 1
-
-#include <fstream>
-#include <string>
-
-#include "oct-stream.h"
-
-class
-octave_fstream : public octave_base_stream
-{
-public:
-
-  octave_fstream (const std::string& nm_arg,
-                  std::ios::openmode arg_md = std::ios::in|std::ios::out,
-                  oct_mach_info::float_format flt_fmt
-                    = oct_mach_info::native_float_format ());
-
-  static octave_stream
-  create (const std::string& nm_arg,
-          std::ios::openmode arg_md = std::ios::in|std::ios::out,
-          oct_mach_info::float_format flt_fmt
-            = oct_mach_info::native_float_format ());
-
-  // Position a stream at OFFSET relative to ORIGIN.
-
-  int seek (long offset, int origin);
-
-  // Return current stream position.
-
-  long tell (void);
-
-  // Return non-zero if EOF has been reached on this stream.
-
-  bool eof (void) const;
-
-  void do_close (void);
-
-  // The name of the file.
-
-  std::string name (void) const { return nm; }
-
-  std::istream *input_stream (void);
-
-  std::ostream *output_stream (void);
-
-protected:
-
-  ~octave_fstream (void) { }
-
-private:
-
-  std::string nm;
-
-  std::fstream fs;
-
-  // No copying!
-
-  octave_fstream (const octave_fstream&);
-
-  octave_fstream& operator = (const octave_fstream&);
-};
-
-#endif
--- a/src/oct-hdf5.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-/*
-
-Copyright (C) 2009-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#if !defined (octave__hdf5_h)
-#define octave_hdf5_h 1
-
-#if defined (HAVE_HDF5)
-#include <hdf5.h>
-#endif
-
-#endif
--- a/src/oct-iostrm.cc	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,89 +0,0 @@
-/*
-
-Copyright (C) 1996-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "error.h"
-#include "oct-iostrm.h"
-
-// Position a stream at OFFSET relative to ORIGIN.
-
-int
-octave_base_iostream::seek (long, int)
-{
-  invalid_operation ();
-  return -1;
-}
-
-// Return current stream position.
-
-long
-octave_base_iostream::tell (void)
-{
-  invalid_operation ();
-  return -1;
-}
-
-// Return non-zero if EOF has been reached on this stream.
-
-bool
-octave_base_iostream::eof (void) const
-{
-  invalid_operation ();
-  return false;
-}
-
-void
-octave_base_iostream::invalid_operation (void) const
-{
-  ::error ("%s: invalid operation", stream_type ());
-}
-
-// Return non-zero if EOF has been reached on this stream.
-
-bool
-octave_istream::eof (void) const
-{
-  return is && is->eof ();
-}
-
-octave_stream
-octave_istream::create (std::istream *arg, const std::string& n)
-{
-  return octave_stream (new octave_istream (arg, n));
-}
-
-// Return non-zero if EOF has been reached on this stream.
-
-bool
-octave_ostream::eof (void) const
-{
-  return os && os->eof ();
-}
-
-octave_stream
-octave_ostream::create (std::ostream *arg, const std::string& n)
-{
-  return octave_stream (new octave_ostream (arg, n));
-}
--- a/src/oct-iostrm.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,154 +0,0 @@
-/*
-
-Copyright (C) 1996-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#if !defined (octave_octave_iostream_h)
-#define octave_octave_iostream_h 1
-
-#include <iosfwd>
-
-#include "oct-stream.h"
-
-class
-octave_base_iostream : public octave_base_stream
-{
-public:
-
-  octave_base_iostream (const std::string& n = std::string (),
-                        std::ios::openmode m = std::ios::in|std::ios::out,
-                        oct_mach_info::float_format ff
-                          = oct_mach_info::native_float_format ())
-    : octave_base_stream (m, ff), nm (n) { }
-
-  // Position a stream at OFFSET relative to ORIGIN.
-
-  int seek (long offset, int origin);
-
-  // Return current stream position.
-
-  long tell (void);
-
-  // Return non-zero if EOF has been reached on this stream.
-
-  bool eof (void) const;
-
-  // The name of the file.
-
-  std::string name (void) const { return nm; }
-
-protected:
-
-  ~octave_base_iostream (void) { }
-
-  void invalid_operation (void) const;
-
-private:
-
-  std::string nm;
-
-  virtual const char *stream_type (void) const = 0;
-
-  // No copying!
-
-  octave_base_iostream (const octave_base_iostream&);
-
-  octave_base_iostream& operator = (const octave_base_iostream&);
-};
-
-class
-octave_istream : public octave_base_iostream
-{
-public:
-
-  octave_istream (std::istream *arg = 0, const std::string& n = std::string ())
-    : octave_base_iostream (n, std::ios::in,
-                            oct_mach_info::native_float_format ()),
-      is (arg)
-  { }
-
-  static octave_stream
-  create (std::istream *arg = 0, const std::string& n = std::string ());
-
-  // Return non-zero if EOF has been reached on this stream.
-
-  bool eof (void) const;
-
-  std::istream *input_stream (void) { return is; }
-
-  std::ostream *output_stream (void) { return 0; }
-
-protected:
-
-  ~octave_istream (void) { }
-
-private:
-
-  std::istream *is;
-
-  const char *stream_type (void) const { return "octave_istream"; }
-
-  // No copying!
-
-  octave_istream (const octave_istream&);
-
-  octave_istream& operator = (const octave_istream&);
-};
-
-class
-octave_ostream : public octave_base_iostream
-{
-public:
-
-  octave_ostream (std::ostream *arg, const std::string& n = std::string ())
-    : octave_base_iostream (n, std::ios::out,
-                            oct_mach_info::native_float_format ()),
-      os (arg)
-  { }
-
-  static octave_stream
-  create (std::ostream *arg, const std::string& n = std::string ());
-
-  // Return non-zero if EOF has been reached on this stream.
-
-  bool eof (void) const;
-
-  std::istream *input_stream (void) { return 0; }
-
-  std::ostream *output_stream (void) { return os; }
-
-protected:
-
-  ~octave_ostream (void) { }
-
-private:
-
-  std::ostream *os;
-
-  const char *stream_type (void) const { return "octave_ostream"; }
-
-  // No copying!
-
-  octave_ostream (const octave_ostream&);
-
-  octave_ostream& operator = (const octave_ostream&);
-};
-
-#endif
--- a/src/oct-lvalue.cc	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,94 +0,0 @@
-/*
-
-Copyright (C) 1996-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "error.h"
-#include "oct-obj.h"
-#include "oct-lvalue.h"
-#include "ov.h"
-
-void
-octave_lvalue::assign (octave_value::assign_op op, const octave_value& rhs)
-{
-  if (val)
-    {
-      if (idx.empty ())
-        val->assign (op, rhs);
-      else
-        val->assign (op, type, idx, rhs);
-    }
-}
-
-void
-octave_lvalue::set_index (const std::string& t,
-                          const std::list<octave_value_list>& i)
-{
-  if (idx.empty ())
-    {
-      type = t;
-      idx = i;
-    }
-  else
-    error ("invalid index expression in assignment");
-}
-
-void
-octave_lvalue::do_unary_op (octave_value::unary_op op)
-{
-  if (val)
-    {
-      if (idx.empty ())
-        val->do_non_const_unary_op (op);
-      else
-        val->do_non_const_unary_op (op, type, idx);
-    }
-  else
-    error ("internal: invalid operation on ~");
-}
-
-octave_value
-octave_lvalue::value (void)
-{
-  octave_value retval;
-
-  if (val)
-    {
-      if (idx.empty ())
-        retval = *val;
-      else
-        {
-          if (val->is_constant ())
-            retval = val->subsref (type, idx);
-          else
-            {
-              octave_value_list t = val->subsref (type, idx, 1);
-              if (t.length () > 0)
-                retval = t(0);
-            }
-        }
-    }
-
-  return retval;
-}
--- a/src/oct-lvalue.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,104 +0,0 @@
-/*
-
-Copyright (C) 1996-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#if !defined (octave_lvalue_h)
-#define octave_lvalue_h 1
-
-class octave_value;
-class octave_value_list;
-
-#include <string>
-
-#include "oct-obj.h"
-#include "pt-idx.h"
-
-class
-octave_lvalue
-{
-public:
-
-  octave_lvalue (octave_value *v = 0)
-    : val (v), type (), idx (), nel (1)
-    { }
-
-  octave_lvalue (const octave_lvalue& vr)
-    : val (vr.val), type (vr.type), idx (vr.idx), nel (vr.nel)
-    {
-    }
-
-  octave_lvalue& operator = (const octave_lvalue& vr)
-    {
-      if (this != &vr)
-        {
-          val = vr.val;
-          type = vr.type;
-          idx = vr.idx;
-          nel = vr.nel;
-        }
-
-      return *this;
-    }
-
-  ~octave_lvalue (void) { }
-
-  bool is_black_hole (void) const { return val == 0; }
-
-  bool is_defined (void) const { return val && val->is_defined (); }
-
-  bool is_undefined (void) const { return ! val || val->is_undefined (); }
-
-  bool is_map (void) const { return val && val->is_map (); }
-
-  void define (const octave_value& v)
-    {
-      if (val)
-        *val = v;
-    }
-
-  void assign (octave_value::assign_op, const octave_value&);
-
-  void numel (octave_idx_type n) { nel = n; }
-
-  octave_idx_type numel (void) const { return nel; }
-
-  void set_index (const std::string& t, const std::list<octave_value_list>& i);
-
-  void clear_index (void) { type = std::string (); idx.clear (); }
-
-  void do_unary_op (octave_value::unary_op op);
-
-  octave_value value (void);
-
-  const octave_value *object (void) const { return val; }
-
-private:
-
-  octave_value *val;
-
-  std::string type;
-
-  std::list<octave_value_list> idx;
-
-  octave_idx_type nel;
-};
-
-#endif
--- a/src/oct-map.cc	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1779 +0,0 @@
-/*
-
-Copyright (C) 1995-2012 John W. Eaton
-Copyright (C) 2010 VZLU Prague
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "error.h"
-#include "str-vec.h"
-
-#include "oct-map.h"
-#include "utils.h"
-
-octave_fields::octave_fields (const string_vector& fields)
-  : rep (new fields_rep)
-{
-  octave_idx_type n = fields.numel ();
-  for (octave_idx_type i = 0; i < n; i++)
-    (*rep)[fields(i)] = i;
-}
-
-octave_fields::octave_fields (const char * const *fields)
-  : rep (new fields_rep)
-{
-  octave_idx_type n = 0;
-  while (*fields)
-    (*rep)[std::string (*fields++)] = n++;
-}
-
-bool
-octave_fields::isfield (const std::string& field) const
-{
-  return rep->find (field) != rep->end ();
-}
-
-octave_idx_type
-octave_fields::getfield (const std::string& field) const
-{
-  fields_rep::iterator p = rep->find (field);
-  return (p != rep->end ()) ? p->second : -1;
-}
-
-octave_idx_type
-octave_fields::getfield (const std::string& field)
-{
-  fields_rep::iterator p = rep->find (field);
-  if (p != rep->end ())
-    return p->second;
-  else
-    {
-      make_unique ();
-      octave_idx_type n = rep->size ();
-      return (*rep)[field] = n;
-    }
-}
-
-octave_idx_type
-octave_fields::rmfield (const std::string& field)
-{
-  fields_rep::iterator p = rep->find (field);
-  if (p == rep->end ())
-    return -1;
-  else
-    {
-      octave_idx_type n = p->second;
-      make_unique ();
-      rep->erase (field);
-      for (fields_rep::iterator q = rep->begin (); q != rep->end (); q++)
-        {
-          if (q->second >= n)
-            q->second--;
-        }
-
-      return n;
-    }
-}
-
-void
-octave_fields::orderfields (Array<octave_idx_type>& perm)
-{
-  octave_idx_type n = rep->size ();
-  perm.clear (n, 1);
-
-  make_unique ();
-  octave_idx_type i = 0;
-  for (fields_rep::iterator q = rep->begin (); q != rep->end (); q++)
-    {
-      octave_idx_type j = q->second;
-      q->second = i;
-      perm(i++) = j;
-    }
-}
-
-bool
-octave_fields::equal_up_to_order (const octave_fields& other,
-                                  octave_idx_type* perm) const
-{
-  bool retval = true;
-
-  iterator p = begin (), q = other.begin ();
-  for (; p != end () && q != other.end (); p++, q++)
-    {
-      if (p->first == q->first)
-        perm[p->second] = q->second;
-      else
-        {
-          retval = false;
-          break;
-        }
-    }
-
-  retval = (p == end () && q == other.end ());
-
-  return retval;
-}
-
-bool
-octave_fields::equal_up_to_order (const octave_fields& other,
-                                  Array<octave_idx_type>& perm) const
-{
-  octave_idx_type n = nfields ();
-  if (perm.length () != n)
-    perm.clear (1, n);
-
-  return equal_up_to_order (other, perm.fortran_vec ());
-}
-
-string_vector
-octave_fields::fieldnames (void) const
-{
-  octave_idx_type n = nfields ();
-  string_vector retval(n);
-
-  for (iterator p = begin (); p != end (); p++)
-    retval.xelem (p->second) = p->first;
-
-  return retval;
-}
-
-octave_value
-octave_scalar_map::getfield (const std::string& k) const
-{
-  octave_idx_type idx = xkeys.getfield (k);
-  return (idx >= 0) ? xvals[idx] : octave_value ();
-}
-
-void
-octave_scalar_map::setfield (const std::string& k, const octave_value& val)
-{
-  octave_idx_type idx = xkeys.getfield (k);
-  if (idx < static_cast<octave_idx_type> (xvals.size ()))
-    xvals[idx] = val;
-  else
-    xvals.push_back (val);
-}
-
-void
-octave_scalar_map::rmfield (const std::string& k)
-{
-  octave_idx_type idx = xkeys.rmfield (k);
-  if (idx >= 0)
-    xvals.erase (xvals.begin () + idx);
-}
-
-octave_scalar_map
-octave_scalar_map::orderfields (void) const
-{
-  Array<octave_idx_type> perm;
-  return orderfields (perm);
-}
-
-octave_scalar_map
-octave_scalar_map::orderfields (Array<octave_idx_type>& perm) const
-{
-  octave_scalar_map retval (xkeys);
-  retval.xkeys.orderfields (perm);
-
-  octave_idx_type nf = nfields ();
-  for (octave_idx_type i = 0; i < nf; i++)
-    retval.xvals[i] = xvals[perm.xelem (i)];
-
-  return retval;
-}
-
-octave_scalar_map
-octave_scalar_map::orderfields (const octave_scalar_map& other,
-                                Array<octave_idx_type>& perm) const
-{
-  if (xkeys.is_same (other.xkeys))
-    return *this;
-  else
-    {
-      octave_scalar_map retval (other.xkeys);
-      if (other.xkeys.equal_up_to_order (xkeys, perm))
-        {
-          octave_idx_type nf = nfields ();
-          for (octave_idx_type i = 0; i < nf; i++)
-            retval.xvals[i] = xvals[perm.xelem (i)];
-        }
-      else
-        error ("orderfields: structs must have same fields up to order");
-
-      return retval;
-    }
-}
-
-octave_value
-octave_scalar_map::contents (const std::string& k) const
-{
-  return getfield (k);
-}
-
-octave_value&
-octave_scalar_map::contents (const std::string& k)
-{
-  octave_idx_type idx = xkeys.getfield (k);
-  if (idx >= static_cast<octave_idx_type> (xvals.size ()))
-    xvals.resize (idx+1);
-  return xvals[idx];
-}
-
-octave_map::octave_map (const octave_scalar_map& m)
-  : xkeys (m.xkeys), xvals (), dimensions (1, 1)
-{
-  octave_idx_type nf = m.nfields ();
-  xvals.reserve (nf);
-  for (octave_idx_type i = 0; i < nf; i++)
-    {
-      xvals.push_back (Cell (dimensions));
-      xvals[i].xelem (0) = m.xvals[i];
-    }
-}
-
-octave_map::octave_map (const Octave_map& m)
-  : xkeys (m.keys ()), xvals (m.nfields ()), dimensions (m.dims ())
-{
-  for (iterator p = begin (); p != end (); p++)
-    contents(p) = m.contents (key (p));
-
-  optimize_dimensions ();
-}
-
-Cell
-octave_map::getfield (const std::string& k) const
-{
-  octave_idx_type idx = xkeys.getfield (k);
-  return (idx >= 0) ? xvals[idx] : Cell ();
-}
-
-void
-octave_map::setfield (const std::string& k, const Cell& val)
-{
-  if (nfields () == 0)
-    dimensions = val.dims ();
-
-  if (val.dims () == dimensions)
-    {
-      octave_idx_type idx = xkeys.getfield (k);
-      if (idx < static_cast<octave_idx_type> (xvals.size ()))
-        xvals[idx] = val;
-      else
-        xvals.push_back (val);
-    }
-  else
-    error ("octave_map::setfield: internal error");
-}
-
-void
-octave_map::rmfield (const std::string& k)
-{
-  octave_idx_type idx = xkeys.rmfield (k);
-  if (idx >= 0)
-    xvals.erase (xvals.begin () + idx);
-}
-
-octave_map
-octave_map::orderfields (void) const
-{
-  Array<octave_idx_type> perm;
-  return orderfields (perm);
-}
-
-octave_map
-octave_map::orderfields (Array<octave_idx_type>& perm) const
-{
-  octave_map retval (xkeys);
-  retval.xkeys.orderfields (perm);
-
-  octave_idx_type nf = nfields ();
-  for (octave_idx_type i = 0; i < nf; i++)
-    retval.xvals[i] = xvals[perm.xelem (i)];
-
-  return retval;
-}
-
-octave_map
-octave_map::orderfields (const octave_map& other,
-                         Array<octave_idx_type>& perm) const
-{
-  if (xkeys.is_same (other.xkeys))
-    return *this;
-  else
-    {
-      octave_map retval (other.xkeys);
-      if (other.xkeys.equal_up_to_order (xkeys, perm))
-        {
-          octave_idx_type nf = nfields ();
-          for (octave_idx_type i = 0; i < nf; i++)
-            retval.xvals[i] = xvals[perm.xelem (i)];
-        }
-      else
-        error ("orderfields: structs must have same fields up to order");
-
-      return retval;
-    }
-}
-
-Cell
-octave_map::contents (const std::string& k) const
-{
-  return getfield (k);
-}
-
-Cell&
-octave_map::contents (const std::string& k)
-{
-  octave_idx_type idx = xkeys.getfield (k);
-  if (idx >= static_cast<octave_idx_type> (xvals.size ()))
-    xvals.push_back (Cell (dimensions)); // auto-set correct dims.
-  return xvals[idx];
-}
-
-void
-octave_map::extract_scalar (octave_scalar_map& dest,
-                            octave_idx_type idx) const
-{
-  octave_idx_type nf = nfields ();
-  for (octave_idx_type i = 0; i < nf; i++)
-    dest.xvals[i] = xvals[i](idx);
-}
-
-octave_scalar_map
-octave_map::checkelem (octave_idx_type n) const
-{
-  octave_scalar_map retval (xkeys);
-
-  // Optimize this so that there is just one check.
-  extract_scalar (retval, compute_index (n, dimensions));
-
-  return retval;
-}
-
-octave_scalar_map
-octave_map::checkelem (octave_idx_type i, octave_idx_type j) const
-{
-  octave_scalar_map retval (xkeys);
-
-  // Optimize this so that there is just one check.
-  extract_scalar (retval, compute_index (i, j, dimensions));
-
-  return retval;
-}
-
-octave_scalar_map
-octave_map::checkelem (const Array<octave_idx_type>& ra_idx) const
-{
-  octave_scalar_map retval (xkeys);
-
-  // Optimize this so that there is just one check.
-  extract_scalar (retval, compute_index (ra_idx, dimensions));
-
-  return retval;
-}
-
-octave_scalar_map
-octave_map::fast_elem_extract (octave_idx_type n) const
-{
-  octave_scalar_map retval (xkeys);
-
-  extract_scalar (retval, n);
-
-  return retval;
-}
-
-bool
-octave_map::fast_elem_insert (octave_idx_type n,
-                              const octave_scalar_map& rhs)
-{
-  bool retval = false;
-
-  octave_idx_type nf = nfields ();
-  if (rhs.xkeys.is_same (xkeys))
-    {
-      for (octave_idx_type i = 0; i < nf; i++)
-        xvals[i](n) = rhs.xvals[i];
-
-      retval = true;
-    }
-  else
-    {
-      OCTAVE_LOCAL_BUFFER (octave_idx_type, perm, nf);
-      if (xkeys.equal_up_to_order (rhs.xkeys, perm))
-        {
-          for (octave_idx_type i = 0; i < nf; i++)
-            xvals[i](n) = rhs.xvals[perm[i]];
-
-          retval = true;
-        }
-    }
-
-  return retval;
-}
-
-octave_map
-octave_map::squeeze (void) const
-{
-  octave_map retval (*this);
-  octave_idx_type nf = nfields ();
-
-  retval.dimensions = dimensions.squeeze ();
-
-  for (octave_idx_type i = 0; i < nf; i++)
-    retval.xvals[i] = xvals[i].squeeze ();
-
-  retval.optimize_dimensions ();
-
-  return retval;
-}
-
-/*
-## test preservation of xkeys by squeeze
-%!test
-%! x(1,1,1,1).d = 10;  x(3,5,1,7).a = "b";  x(2,4,1,7).f = 27;
-%! assert (fieldnames (squeeze (x)), {"d"; "a"; "f"});
-*/
-
-octave_map
-octave_map::permute (const Array<int>& vec, bool inv) const
-{
-  octave_map retval (xkeys);
-  octave_idx_type nf = nfields ();
-
-  for (octave_idx_type i = 0; i < nf; i++)
-    retval.xvals[i] = xvals[i].permute (vec, inv);
-
-  // FIXME:
-  // There is no dim_vector::permute for technical reasons.
-  // We pick the dim vector from results if possible, otherwise use a dummy
-  // array to get it. Need (?) a better solution to this problem.
-  if (nf > 0)
-    retval.dimensions = retval.xvals[0].dims ();
-  else
-    {
-      Array<char> dummy (dimensions);
-      dummy = dummy.permute (vec, inv);
-      retval.dimensions = dummy.dims ();
-    }
-
-  retval.optimize_dimensions ();
-
-  return retval;
-}
-
-/*
-## test preservation of key order by permute
-%!test
-%! x(1,1,1,1).d = 10;  x(3,5,1,7).a = "b";  x(2,4,1,7).f = 27;
-%! assert (fieldnames (permute (x, [3, 4, 1, 2])), {"d"; "a"; "f"});
-*/
-
-octave_map
-octave_map::transpose (void) const
-{
-  assert (ndims () == 2);
-
-  octave_map retval (xkeys);
-
-  retval.dimensions = dim_vector (dimensions (1), dimensions (0));
-
-  octave_idx_type nf = nfields ();
-  for (octave_idx_type i = 0; i < nf; i++)
-    retval.xvals[i] = xvals[i].transpose ();
-
-  retval.optimize_dimensions ();
-
-  return retval;
-}
-
-/*
-## test preservation of key order by transpose
-%!test
-%! x(1,1).d = 10;  x(3,5).a = "b";  x(2,4).f = 27;
-%! assert (fieldnames (transpose (x)), {"d"; "a"; "f"});
-%! assert (fieldnames (x'), {"d"; "a"; "f"});
-%! assert (fieldnames (x.'), {"d"; "a"; "f"});
-*/
-
-octave_map
-octave_map::reshape (const dim_vector& dv) const
-{
-  octave_map retval (xkeys);
-  retval.dimensions = dv;
-
-  octave_idx_type nf = nfields ();
-  if (nf > 0)
-    {
-      retval.xvals.reserve (nf);
-      for (octave_idx_type i = 0; i < nf; i++)
-        retval.xvals[i] = xvals[i].reshape (dv);
-    }
-  else
-    {
-      // FIXME: Do it with a dummy array, to reuse error message.
-      // Need (?) a better solution.
-      Array<char> dummy (dimensions);
-      dummy.reshape (dv);
-    }
-
-  retval.optimize_dimensions ();
-
-  return retval;
-}
-
-/*
-## test preservation of key order by reshape
-%!test
-%! x(1,1).d = 10;  x(4,6).a = "b";  x(2,4).f = 27;
-%! assert (fieldnames (reshape (x, 3, 8)), {"d"; "a"; "f"});
-*/
-
-void
-octave_map::resize (const dim_vector& dv, bool fill)
-{
-  octave_idx_type nf = nfields ();
-  if (nf > 0)
-    {
-      for (octave_idx_type i = 0; i < nf; i++)
-        {
-          if (fill)
-            xvals[i].resize (dv, Matrix ());
-          else
-            xvals[i].resize (dv);
-        }
-    }
-  else
-    {
-      // FIXME: Do it with a dummy array, to reuse error message.
-      // Need (?) a better solution.
-      Array<char> dummy (dimensions);
-      dummy.resize (dv);
-    }
-
-  dimensions = dv;
-  optimize_dimensions ();
-}
-
-void
-octave_map::do_cat (int dim, octave_idx_type n, const octave_scalar_map *map_list,
-                    octave_map& retval)
-{
-  octave_idx_type nf = retval.nfields ();
-  retval.xvals.reserve (nf);
-
-  dim_vector& rd = retval.dimensions;
-  rd.resize (dim+1, 1);
-  rd(0) = rd(1) = 1;
-  rd(dim) = n;
-
-  for (octave_idx_type j = 0; j < nf; j++)
-    {
-      retval.xvals.push_back (Cell (rd));
-      assert (retval.xvals[j].numel () == n);
-      for (octave_idx_type i = 0; i < n; i++)
-        retval.xvals[j].xelem (i) = map_list[i].xvals[j];
-    }
-}
-
-void
-octave_map::do_cat (int dim, octave_idx_type n, const octave_map *map_list,
-                    octave_map& retval)
-{
-  octave_idx_type nf = retval.nfields ();
-  retval.xvals.reserve (nf);
-
-  OCTAVE_LOCAL_BUFFER (Array<octave_value>, field_list, n);
-
-  for (octave_idx_type j = 0; j < nf; j++)
-    {
-      for (octave_idx_type i = 0; i < n; i++)
-        field_list[i] = map_list[i].xvals[j];
-
-      retval.xvals.push_back (Array<octave_value>::cat (dim, n, field_list));
-      if (j == 0)
-        retval.dimensions = retval.xvals[j].dims ();
-    }
-}
-
-// This is just a wrapper.
-void permute_to_correct_order1 (const octave_scalar_map& ref, const octave_scalar_map& src,
-                                octave_scalar_map& dest, Array<octave_idx_type>& perm)
-{
-  dest = src.orderfields (ref, perm);
-}
-
-// In non-scalar case, we also promote empty structs without fields.
-void permute_to_correct_order1 (const octave_map& ref, const octave_map& src,
-                                octave_map& dest, Array<octave_idx_type>& perm)
-{
-  if (src.nfields () == 0 && src.is_empty ())
-     dest = octave_map (src.dims (), ref.keys ());
-  else
-     dest = src.orderfields (ref, perm);
-}
-
-template <class map>
-static void
-permute_to_correct_order (octave_idx_type n, octave_idx_type nf,
-                          octave_idx_type idx, const map *map_list,
-                          map *new_map_list)
-{
-  new_map_list[idx] = map_list[idx];
-
-  Array<octave_idx_type> perm (dim_vector (1, nf));
-
-  for (octave_idx_type i = 0; i < n; i++)
-    {
-      if (i == idx)
-         continue;
-
-      permute_to_correct_order1 (map_list[idx], map_list[i], new_map_list[i], perm);
-
-      if (error_state)
-        {
-          // Use liboctave exception to be consistent.
-          (*current_liboctave_error_handler)
-            ("cat: field names mismatch in concatenating structs");
-          break;
-        }
-    }
-}
-
-
-octave_map
-octave_map::cat (int dim, octave_idx_type n, const octave_scalar_map *map_list)
-{
-  octave_map retval;
-
-  // Allow dim = -1, -2 for compatibility, though it makes no difference here.
-  if (dim == -1 || dim == -2)
-    dim = -dim - 1;
-  else if (dim < 0)
-    (*current_liboctave_error_handler)
-      ("cat: invalid dimension");
-
-  if (n == 1)
-    retval = map_list[0];
-  else if (n > 1)
-    {
-      octave_idx_type idx, nf = 0;
-      for (idx = 0; idx < n; idx++)
-        {
-          nf = map_list[idx].nfields ();
-          if (nf > 0)
-            {
-              retval.xkeys = map_list[idx].xkeys;
-              break;
-            }
-        }
-
-      if (nf > 0)
-        {
-          // Try the fast case.
-          bool all_same = true;
-          for (octave_idx_type i = 0; i < n; i++)
-            {
-              all_same = map_list[idx].xkeys.is_same (map_list[i].xkeys);
-              if (! all_same)
-                break;
-            }
-
-          if (all_same)
-            do_cat (dim, n, map_list, retval);
-          else
-            {
-              // permute all structures to common order.
-              OCTAVE_LOCAL_BUFFER (octave_scalar_map, new_map_list, n);
-
-              permute_to_correct_order (n, nf, idx, map_list, new_map_list);
-
-              do_cat (dim, n, new_map_list, retval);
-            }
-
-        }
-      else
-        {
-          dim_vector& rd = retval.dimensions;
-          rd.resize (dim+1, 1);
-          rd(0) = rd(1) = 1;
-          rd(dim) = n;
-        }
-
-      retval.optimize_dimensions ();
-    }
-
-  return retval;
-}
-
-octave_map
-octave_map::cat (int dim, octave_idx_type n, const octave_map *map_list)
-{
-  octave_map retval;
-
-  // Allow dim = -1, -2 for compatibility, though it makes no difference here.
-  if (dim == -1 || dim == -2)
-    dim = -dim - 1;
-  else if (dim < 0)
-    (*current_liboctave_error_handler)
-      ("cat: invalid dimension");
-
-  if (n == 1)
-    retval = map_list[0];
-  else if (n > 1)
-    {
-      octave_idx_type idx, nf = 0;
-
-      for (idx = 0; idx < n; idx++)
-        {
-          nf = map_list[idx].nfields ();
-          if (nf > 0)
-            {
-              retval.xkeys = map_list[idx].xkeys;
-              break;
-            }
-        }
-
-      // Try the fast case.
-      bool all_same = true;
-
-      if (nf > 0)
-        {
-          for (octave_idx_type i = 0; i < n; i++)
-            {
-              all_same = map_list[idx].xkeys.is_same (map_list[i].xkeys);
-
-              if (! all_same)
-                break;
-            }
-        }
-
-      if (all_same && nf > 0)
-        do_cat (dim, n, map_list, retval);
-      else
-        {
-          if (nf > 0)
-            {
-              // permute all structures to correct order.
-              OCTAVE_LOCAL_BUFFER (octave_map, new_map_list, n);
-
-              permute_to_correct_order (n, nf, idx, map_list, new_map_list);
-
-              do_cat (dim, n, new_map_list, retval);
-            }
-          else
-            {
-              dim_vector dv = map_list[0].dimensions;
-
-              for (octave_idx_type i = 1; i < n; i++)
-                {
-                  if (! dv.concat (map_list[i].dimensions, dim))
-                    {
-                      error ("dimension mismatch in struct concatenation");
-                      return retval;
-                    }
-                }
-
-              retval.dimensions = dv;
-            }
-        }
-
-      retval.optimize_dimensions ();
-    }
-
-  return retval;
-}
-
-/*
-## test preservation of key order by concatenation
-%!test
-%! x(1, 1).d = 10;  x(4, 6).a = "b";  x(2, 4).f = 27;
-%! y(1, 6).f = 11;  y(1, 6).a = "c";  y(1, 6).d = 33;
-%! assert (fieldnames ([x; y]), {"d"; "a"; "f"});
-
-%!test
-%! s = struct ();
-%! sr = [s,s];
-%! sc = [s;s];
-%! sm = [s,s;s,s];
-%! assert (nfields (sr), 0);
-%! assert (nfields (sc), 0);
-%! assert (nfields (sm), 0);
-%! assert (size (sr), [1, 2]);
-%! assert (size (sc), [2, 1]);
-%! assert (size (sm), [2, 2]);
-*/
-
-octave_map
-octave_map::index (const idx_vector& i, bool resize_ok) const
-{
-  octave_map retval (xkeys);
-  octave_idx_type nf = nfields ();
-
-  for (octave_idx_type k = 0; k < nf; k++)
-    retval.xvals[k] = xvals[k].index (i, resize_ok);
-
-  if (nf > 0)
-    retval.dimensions = retval.xvals[0].dims ();
-  else
-    {
-      // Use dummy array. FIXME: Need(?) a better solution.
-      Array<char> dummy (dimensions);
-      dummy = dummy.index (i, resize_ok);
-      retval.dimensions = dummy.dims ();
-    }
-
-  retval.optimize_dimensions ();
-
-  return retval;
-}
-
-octave_map
-octave_map::index (const idx_vector& i, const idx_vector& j,
-                   bool resize_ok) const
-{
-  octave_map retval (xkeys);
-  octave_idx_type nf = nfields ();
-
-  for (octave_idx_type k = 0; k < nf; k++)
-    retval.xvals[k] = xvals[k].index (i, j, resize_ok);
-
-  if (nf > 0)
-    retval.dimensions = retval.xvals[0].dims ();
-  else
-    {
-      // Use dummy array. FIXME: Need(?) a better solution.
-      Array<char> dummy (dimensions);
-      dummy = dummy.index (i, j, resize_ok);
-      retval.dimensions = dummy.dims ();
-    }
-
-  retval.optimize_dimensions ();
-
-  return retval;
-}
-
-octave_map
-octave_map::index (const Array<idx_vector>& ia, bool resize_ok) const
-{
-  octave_map retval (xkeys);
-  octave_idx_type nf = nfields ();
-
-  for (octave_idx_type k = 0; k < nf; k++)
-    retval.xvals[k] = xvals[k].index (ia, resize_ok);
-
-  if (nf > 0)
-    retval.dimensions = retval.xvals[0].dims ();
-  else
-    {
-      // Use dummy array. FIXME: Need(?) a better solution.
-      Array<char> dummy (dimensions);
-      dummy = dummy.index (ia, resize_ok);
-      retval.dimensions = dummy.dims ();
-    }
-
-  retval.optimize_dimensions ();
-
-  return retval;
-}
-
-octave_map
-octave_map::index (const octave_value_list& idx, bool resize_ok) const
-{
-  octave_idx_type n_idx = idx.length ();
-  octave_map retval;
-
-  switch (n_idx)
-    {
-    case 1:
-      {
-        idx_vector i = idx(0).index_vector ();
-
-        if (! error_state)
-          retval = index (i, resize_ok);
-      }
-      break;
-
-    case 2:
-      {
-        idx_vector i = idx(0).index_vector ();
-
-        if (! error_state)
-          {
-            idx_vector j = idx(1).index_vector ();
-
-            retval = index (i, j, resize_ok);
-          }
-      }
-      break;
-
-    default:
-      {
-        Array<idx_vector> ia (dim_vector (n_idx, 1));
-
-        for (octave_idx_type i = 0; i < n_idx; i++)
-          {
-            ia(i) = idx(i).index_vector ();
-
-            if (error_state)
-              break;
-          }
-
-        if (! error_state)
-          retval = index (ia, resize_ok);
-      }
-      break;
-    }
-
-  return retval;
-}
-
-// Perhaps one day these will be optimized. Right now, they just call index.
-octave_map
-octave_map::column (octave_idx_type k) const
-{
-  return index (idx_vector::colon, k);
-}
-
-octave_map
-octave_map::page (octave_idx_type k) const
-{
-  static Array<idx_vector> ia (dim_vector (3, 1), idx_vector::colon);
-
-  ia(2) = k;
-  return index (ia);
-}
-
-void
-octave_map::assign (const idx_vector& i, const octave_map& rhs)
-{
-  if (rhs.xkeys.is_same (xkeys))
-    {
-      octave_idx_type nf = nfields ();
-
-      for (octave_idx_type k = 0; k < nf; k++)
-        xvals[k].assign (i, rhs.xvals[k], Matrix ());
-
-      if (nf > 0)
-        dimensions = xvals[0].dims ();
-      else
-        {
-          // Use dummy array. FIXME: Need(?) a better solution.
-          Array<char> dummy (dimensions), rhs_dummy (rhs.dimensions);
-          dummy.assign (i, rhs_dummy);;
-          dimensions = dummy.dims ();
-        }
-
-      optimize_dimensions ();
-    }
-  else if (nfields () == 0)
-    {
-      octave_map tmp (dimensions, rhs.xkeys);
-      tmp.assign (i, rhs);
-      *this = tmp;
-    }
-  else
-    {
-      Array<octave_idx_type> perm;
-      octave_map rhs1 = rhs.orderfields (*this, perm);
-      if (! error_state)
-        {
-          assert (rhs1.xkeys.is_same (xkeys));
-          assign (i, rhs1);
-        }
-      else
-        error ("incompatible fields in struct assignment");
-    }
-}
-
-void
-octave_map::assign (const idx_vector& i, const idx_vector& j,
-                    const octave_map& rhs)
-{
-  if (rhs.xkeys.is_same (xkeys))
-    {
-      octave_idx_type nf = nfields ();
-
-      for (octave_idx_type k = 0; k < nf; k++)
-        xvals[k].assign (i, j, rhs.xvals[k], Matrix ());
-
-      if (nf > 0)
-        dimensions = xvals[0].dims ();
-      else
-        {
-          // Use dummy array. FIXME: Need(?) a better solution.
-          Array<char> dummy (dimensions), rhs_dummy (rhs.dimensions);
-          dummy.assign (i, j, rhs_dummy);;
-          dimensions = dummy.dims ();
-        }
-
-      optimize_dimensions ();
-    }
-  else if (nfields () == 0)
-    {
-      octave_map tmp (dimensions, rhs.xkeys);
-      tmp.assign (i, j, rhs);
-      *this = tmp;
-    }
-  else
-    {
-      Array<octave_idx_type> perm;
-      octave_map rhs1 = rhs.orderfields (*this, perm);
-      if (! error_state)
-        {
-          assert (rhs1.xkeys.is_same (xkeys));
-          assign (i, j, rhs1);
-        }
-      else
-        error ("incompatible fields in struct assignment");
-    }
-}
-
-void
-octave_map::assign (const Array<idx_vector>& ia,
-                    const octave_map& rhs)
-{
-  if (rhs.xkeys.is_same (xkeys))
-    {
-      octave_idx_type nf = nfields ();
-
-      for (octave_idx_type k = 0; k < nf; k++)
-        xvals[k].assign (ia, rhs.xvals[k], Matrix ());
-
-      if (nf > 0)
-        dimensions = xvals[0].dims ();
-      else
-        {
-          // Use dummy array. FIXME: Need(?) a better solution.
-          Array<char> dummy (dimensions), rhs_dummy (rhs.dimensions);
-          dummy.assign (ia, rhs_dummy);;
-          dimensions = dummy.dims ();
-        }
-
-      optimize_dimensions ();
-    }
-  else if (nfields () == 0)
-    {
-      octave_map tmp (dimensions, rhs.xkeys);
-      tmp.assign (ia, rhs);
-      *this = tmp;
-    }
-  else
-    {
-      Array<octave_idx_type> perm;
-      octave_map rhs1 = rhs.orderfields (*this, perm);
-      if (! error_state)
-        {
-          assert (rhs1.xkeys.is_same (xkeys));
-          assign (ia, rhs1);
-        }
-      else
-        error ("incompatible fields in struct assignment");
-    }
-}
-
-void
-octave_map::assign (const octave_value_list& idx, const octave_map& rhs)
-{
-  octave_idx_type n_idx = idx.length ();
-
-  switch (n_idx)
-    {
-    case 1:
-      {
-        idx_vector i = idx(0).index_vector ();
-
-        if (! error_state)
-          assign (i, rhs);
-      }
-      break;
-
-    case 2:
-      {
-        idx_vector i = idx(0).index_vector ();
-
-        if (! error_state)
-          {
-            idx_vector j = idx(1).index_vector ();
-
-            assign (i, j, rhs);
-          }
-      }
-      break;
-
-    default:
-      {
-        Array<idx_vector> ia (dim_vector (n_idx, 1));
-
-        for (octave_idx_type i = 0; i < n_idx; i++)
-          {
-            ia(i) = idx(i).index_vector ();
-
-            if (error_state)
-              break;
-          }
-
-        if (! error_state)
-          assign (ia, rhs);
-      }
-      break;
-    }
-}
-
-void
-octave_map::assign (const octave_value_list& idx, const std::string& k,
-                    const Cell& rhs)
-{
-  Cell tmp;
-  iterator p = seek (k);
-  Cell& ref = p != end () ? contents (p) : tmp;
-
-  if (&ref == &tmp)
-    ref = Cell (dimensions);
-
-  ref.assign (idx, rhs);
-
-  if (! error_state && ref.dims () != dimensions)
-    {
-      dimensions = ref.dims ();
-
-      octave_idx_type nf = nfields ();
-      for (octave_idx_type i = 0; i < nf; i++)
-        {
-          if (&xvals[i] != &ref)
-            xvals[i].resize (dimensions, Matrix ());
-        }
-
-      optimize_dimensions ();
-    }
-
-  if (! error_state && &ref == &tmp)
-    setfield (k, tmp);
-}
-
-/*
-%!test
-%! rhs.b = 1;
-%! a(3) = rhs;
-%! assert ({a.b}, {[], [], 1})
-*/
-
-void
-octave_map::delete_elements (const idx_vector& i)
-{
-  octave_idx_type nf = nfields ();
-  for (octave_idx_type k = 0; k < nf; k++)
-    xvals[k].delete_elements (i);
-
-  if (nf > 0)
-    dimensions = xvals[0].dims ();
-  else
-    {
-      // Use dummy array. FIXME: Need(?) a better solution.
-      Array<char> dummy (dimensions);
-      dummy.delete_elements (i);
-      dimensions = dummy.dims ();
-    }
-
-  optimize_dimensions ();
-}
-
-void
-octave_map::delete_elements (int dim, const idx_vector& i)
-{
-  octave_idx_type nf = nfields ();
-  for (octave_idx_type k = 0; k < nf; k++)
-    xvals[k].delete_elements (dim, i);
-
-  if (nf > 0)
-    dimensions = xvals[0].dims ();
-  else
-    {
-      // Use dummy array. FIXME: Need(?) a better solution.
-      Array<char> dummy (dimensions);
-      dummy.delete_elements (dim, i);
-      dimensions = dummy.dims ();
-    }
-
-  optimize_dimensions ();
-}
-
-void
-octave_map::delete_elements (const Array<idx_vector>& ia)
-{
-  octave_idx_type nf = nfields ();
-  for (octave_idx_type k = 0; k < nf; k++)
-    xvals[k].delete_elements (ia);
-
-  if (nf > 0)
-    dimensions = xvals[0].dims ();
-  else
-    {
-      // Use dummy array. FIXME: Need(?) a better solution.
-      Array<char> dummy (dimensions);
-      dummy.delete_elements (ia);
-      dimensions = dummy.dims ();
-    }
-
-  optimize_dimensions ();
-}
-
-void
-octave_map::delete_elements (const octave_value_list& idx)
-{
-  octave_idx_type n_idx = idx.length ();
-
-  Array<idx_vector> ia (dim_vector (n_idx, 1));
-
-  for (octave_idx_type i = 0; i < n_idx; i++)
-    {
-      ia(i) = idx(i).index_vector ();
-
-      if (error_state)
-        break;
-    }
-
-  if (! error_state)
-    delete_elements (ia);
-}
-
-/*
-## test preservation of key order by indexing
-%!test
-%! x(1, 1).d = 10;  x(4, 6).a = "b";  x(2, 4).f = 27;
-%! assert (fieldnames (x([1, 2], [2:5])), {"d"; "a"; "f"});
-*/
-
-octave_map
-octave_map::concat (const octave_map& rb, const Array<octave_idx_type>& ra_idx)
-{
-  if (nfields () == rb.nfields ())
-    {
-      for (const_iterator pa = begin (); pa != end (); pa++)
-        {
-          const_iterator pb = rb.seek (key(pa));
-
-          if (pb == rb.end ())
-            {
-              error ("field name mismatch in structure concatenation");
-              break;
-            }
-
-          contents(pa).insert (rb.contents (pb), ra_idx);
-        }
-    }
-  else
-    {
-      dim_vector dv = dims ();
-
-      if (dv.all_zero ())
-        *this = rb;
-      else if (! rb.dims ().all_zero ())
-        error ("invalid structure concatenation");
-    }
-
-  return *this;
-}
-
-void
-octave_map::optimize_dimensions (void)
-{
-  octave_idx_type nf = nfields ();
-
-  for (octave_idx_type i = 0; i < nf; i++)
-    {
-      if (! xvals[i].optimize_dimensions (dimensions))
-        {
-          error ("internal error: dimension mismatch across fields in struct");
-          break;
-        }
-    }
-
-}
-
-Octave_map::Octave_map (const dim_vector& dv, const Cell& key_vals)
-  : map (), key_list (), dimensions (dv)
-{
-  Cell c (dv);
-
-  if (key_vals.is_cellstr ())
-    {
-      for (octave_idx_type i = 0; i < key_vals.numel (); i++)
-        {
-          std::string k = key_vals(i).string_value ();
-          map[k] = c;
-          key_list.push_back (k);
-        }
-    }
-  else
-    error ("Octave_map: expecting keys to be cellstr");
-}
-
-Octave_map::Octave_map (const octave_map& m)
-  : map (), key_list (), dimensions (m.dims ())
-{
-  for (octave_map::const_iterator p = m.begin (); p != m.end (); p++)
-    map[m.key (p)] = m.contents (p);
-  const string_vector mkeys = m.fieldnames ();
-  for (octave_idx_type i = 0; i < mkeys.numel (); i++)
-    key_list.push_back (mkeys(i));
-}
-
-Octave_map
-Octave_map::squeeze (void) const
-{
-  Octave_map retval (dims ().squeeze ());
-
-  for (const_iterator pa = begin (); pa != end (); pa++)
-    {
-      Cell tmp = contents (pa).squeeze ();
-
-      if (error_state)
-        break;
-
-      retval.assign (key (pa), tmp);
-    }
-
-  // Preserve order of keys.
-  retval.key_list = key_list;
-
-  return retval;
-}
-
-Octave_map
-Octave_map::permute (const Array<int>& vec, bool inv) const
-{
-  Octave_map retval (dims ());
-
-  for (const_iterator pa = begin (); pa != end (); pa++)
-    {
-      Cell tmp = contents (pa).permute (vec, inv);
-
-      if (error_state)
-        break;
-
-      retval.assign (key (pa), tmp);
-    }
-
-  // Preserve order of keys.
-  retval.key_list = key_list;
-
-  return retval;
-}
-
-Cell&
-Octave_map::contents (const std::string& k)
-{
-  maybe_add_to_key_list (k);
-
-  return map[k];
-}
-
-Cell
-Octave_map::contents (const std::string& k) const
-{
-  const_iterator p = seek (k);
-
-  return p != end () ? p->second : Cell ();
-}
-
-int
-Octave_map::intfield (const std::string& k, int def_val) const
-{
-  int retval = def_val;
-
-  Cell c = contents (k);
-
-  if (! c.is_empty ())
-    retval = c(0).int_value ();
-
-  return retval;
-}
-
-std::string
-Octave_map::stringfield (const std::string& k,
-                         const std::string& def_val) const
-{
-  std::string retval = def_val;
-
-  Cell c = contents (k);
-
-  if (! c.is_empty ())
-    retval = c(0).string_value ();
-
-  return retval;
-}
-
-string_vector
-Octave_map::keys (void) const
-{
-  assert (static_cast<size_t>(nfields ()) == key_list.size ());
-
-  return string_vector (key_list);
-}
-
-Octave_map
-Octave_map::transpose (void) const
-{
-  assert (ndims () == 2);
-
-  dim_vector dv = dims ();
-
-  octave_idx_type nr = dv(0);
-  octave_idx_type nc = dv(1);
-
-  dim_vector new_dims (nc, nr);
-
-  Octave_map retval (new_dims);
-
-  for (const_iterator p = begin (); p != end (); p++)
-    retval.assign (key(p), Cell (contents(p).transpose ()));
-
-  // Preserve order of keys.
-  retval.key_list = key_list;
-
-  return retval;
-}
-
-Octave_map
-Octave_map::reshape (const dim_vector& new_dims) const
-{
-  Octave_map retval;
-
-  if (new_dims != dims ())
-    {
-      for (const_iterator p = begin (); p != end (); p++)
-        retval.assign (key(p), contents(p).reshape (new_dims));
-
-      retval.dimensions = new_dims;
-
-      // Preserve order of keys.
-      retval.key_list = key_list;
-    }
-  else
-    retval = *this;
-
-  return retval;
-}
-
-void
-Octave_map::resize (const dim_vector& dv, bool fill)
-{
-  if (dv != dims ())
-    {
-      if (nfields () == 0)
-        dimensions = dv;
-      else
-        {
-          for (const_iterator p = begin (); p != end (); p++)
-            {
-              Cell tmp = contents(p);
-
-              if (fill)
-                tmp.resize (dv, Matrix ());
-              else
-                tmp.resize (dv);
-
-              dimensions = dv;
-
-              assign (key(p), tmp);
-            }
-        }
-    }
-}
-
-Octave_map
-Octave_map::concat (const Octave_map& rb, const Array<octave_idx_type>& ra_idx)
-{
-  Octave_map retval;
-
-  if (nfields () == rb.nfields ())
-    {
-      for (const_iterator pa = begin (); pa != end (); pa++)
-        {
-          const_iterator pb = rb.seek (key(pa));
-
-          if (pb == rb.end ())
-            {
-              error ("field name mismatch in structure concatenation");
-              break;
-            }
-
-          retval.assign (key(pa),
-                         contents(pa).insert (rb.contents(pb), ra_idx));
-        }
-
-      // Preserve order of keys.
-      retval.key_list = key_list;
-    }
-  else
-    {
-      dim_vector dv = dims ();
-
-      if (dv.all_zero ())
-        retval = rb;
-      else
-        {
-          dv = rb.dims ();
-
-          if (dv.all_zero ())
-            retval = *this;
-          else
-            error ("invalid structure concatenation");
-        }
-    }
-
-  return retval;
-}
-
-static bool
-keys_ok (const Octave_map& a, const Octave_map& b, string_vector& keys)
-{
-  bool retval = false;
-
-  keys = string_vector ();
-
-  if (a.nfields () == 0)
-    {
-      keys = b.keys ();
-      retval = true;
-    }
-  else
-    {
-      string_vector a_keys = a.keys ().sort ();
-      string_vector b_keys = b.keys ().sort ();
-
-      octave_idx_type a_len = a_keys.length ();
-      octave_idx_type b_len = b_keys.length ();
-
-      if (a_len == b_len)
-        {
-          for (octave_idx_type i = 0; i < a_len; i++)
-            {
-              if (a_keys[i] != b_keys[i])
-                goto done;
-            }
-
-          keys = a_keys;
-          retval = true;
-        }
-    }
-
- done:
-  return retval;
-}
-
-Octave_map&
-Octave_map::maybe_delete_elements (const octave_value_list& idx)
-{
-  string_vector t_keys = keys ();
-  octave_idx_type len = t_keys.length ();
-
-  if (len > 0)
-    {
-      for (octave_idx_type i = 0; i < len; i++)
-        {
-          std::string k = t_keys[i];
-
-          contents(k).delete_elements (idx);
-
-          if (error_state)
-            break;
-        }
-
-      if (!error_state)
-        dimensions = contents(t_keys[0]).dims ();
-    }
-
-  return *this;
-}
-
-Octave_map&
-Octave_map::assign (const octave_value_list& idx, const Octave_map& rhs)
-{
-  string_vector t_keys;
-
-  if (keys_ok (*this, rhs, t_keys))
-    {
-      octave_idx_type len = t_keys.length ();
-
-      if (len == 0)
-        {
-          Cell tmp_lhs (dims ());
-          Cell tmp_rhs (rhs.dims ());
-
-          tmp_lhs.assign (idx, tmp_rhs, Matrix ());
-
-          if (! error_state)
-            resize (tmp_lhs.dims ());
-          else
-            error ("size mismatch in structure assignment");
-        }
-      else
-        {
-          for (octave_idx_type i = 0; i < len; i++)
-            {
-              std::string k = t_keys[i];
-
-              Cell t_rhs = rhs.contents (k);
-
-              assign (idx, k, t_rhs);
-
-              if (error_state)
-                break;
-            }
-        }
-    }
-  else
-    error ("field name mismatch in structure assignment");
-
-  return *this;
-}
-
-Octave_map&
-Octave_map::assign (const octave_value_list& idx, const std::string& k,
-                    const Cell& rhs)
-{
-  Cell tmp;
-
-  if (contains (k))
-    tmp = map[k];
-  else
-    tmp = Cell (dimensions);
-
-  tmp.assign (idx, rhs);
-
-  if (! error_state)
-    {
-      dim_vector tmp_dims = tmp.dims ();
-
-      if (tmp_dims != dimensions)
-        {
-          for (iterator p = begin (); p != end (); p++)
-            contents(p).resize (tmp_dims, Matrix ());
-
-          dimensions = tmp_dims;
-        }
-
-      maybe_add_to_key_list (k);
-
-      map[k] = tmp;
-    }
-
-  return *this;
-}
-
-Octave_map&
-Octave_map::assign (const std::string& k, const octave_value& rhs)
-{
-  if (nfields () == 0)
-    {
-      maybe_add_to_key_list (k);
-
-      map[k] = Cell (rhs);
-
-      dimensions = dim_vector (1, 1);
-    }
-  else
-    {
-      dim_vector dv = dims ();
-
-      if (dv.all_ones ())
-        {
-          maybe_add_to_key_list (k);
-
-          map[k] = Cell (rhs);
-        }
-      else
-        error ("invalid structure assignment");
-    }
-
-  return *this;
-}
-
-Octave_map&
-Octave_map::assign (const std::string& k, const Cell& rhs)
-{
-  if (nfields () == 0)
-    {
-      maybe_add_to_key_list (k);
-
-      map[k] = rhs;
-
-      dimensions = rhs.dims ();
-    }
-  else
-    {
-      if (dims () == rhs.dims ())
-        {
-          maybe_add_to_key_list (k);
-
-          map[k] = rhs;
-        }
-      else
-        error ("invalid structure assignment");
-    }
-
-  return *this;
-}
-
-Octave_map
-Octave_map::index (const octave_value_list& idx, bool resize_ok) const
-{
-  Octave_map retval;
-
-  octave_idx_type n_idx = idx.length ();
-
-  if (n_idx > 0)
-    {
-      Array<idx_vector> ra_idx (dim_vector (n_idx, 1));
-
-      for (octave_idx_type i = 0; i < n_idx; i++)
-        {
-          ra_idx(i) = idx(i).index_vector ();
-          if (error_state)
-            break;
-        }
-
-      if (! error_state)
-        {
-          for (const_iterator p = begin (); p != end (); p++)
-            {
-              Cell tmp = contents (p);
-
-              tmp = tmp.Array<octave_value>::index (ra_idx, resize_ok);
-
-              if (error_state)
-                break;
-
-              retval.assign (key(p), tmp);
-            }
-
-          // Preserve order of keys.
-          retval.key_list = key_list;
-        }
-    }
-  else
-    retval = *this;
-
-  return retval;
-}
--- a/src/oct-map.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,659 +0,0 @@
-/*
-
-Copyright (C) 1994-2012 John W. Eaton
-Copyright (C) 2010 VZLU Prague
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#if !defined (octave_oct_map_h)
-#define octave_oct_map_h 1
-
-#include <algorithm>
-#include <map>
-
-#include "Cell.h"
-#include "oct-obj.h"
-
-class string_vector;
-
-// A class holding a map field->index. Supports reference-counting.
-class OCTINTERP_API
-octave_fields
-{
-  class fields_rep : public std::map<std::string, octave_idx_type>
-  {
-  public:
-    fields_rep (void) : std::map<std::string, octave_idx_type> (), count (1) { }
-    fields_rep (const fields_rep& other)
-      : std::map<std::string, octave_idx_type> (other), count (1) { }
-
-    octave_refcount<int> count;
-
-  private:
-    fields_rep& operator = (const fields_rep&); // no assignment!
-  };
-
-  fields_rep *rep;
-
-  static fields_rep *nil_rep (void)
-    {
-      static fields_rep nr;
-      return &nr;
-    }
-
-public:
-
-  octave_fields (void) : rep (nil_rep ()) { rep->count++; }
-  octave_fields (const string_vector&);
-  octave_fields (const char * const *);
-
-  ~octave_fields (void)
-    {
-      if (--rep->count == 0)
-        delete rep;
-    }
-
-  void make_unique (void)
-    {
-      if (rep->count > 1)
-        {
-          fields_rep *r = new fields_rep (*rep);
-
-          if (--rep->count == 0)
-            delete rep;
-
-          rep = r;
-        }
-    }
-
-  octave_fields (const octave_fields& o) : rep (o.rep) { rep->count++; }
-
-  octave_fields&
-  operator = (const octave_fields& o)
-    {
-      o.rep->count++;
-      if (--rep->count == 0)
-        delete rep;
-      rep = o.rep;
-
-      return *this;
-    }
-
-  // constant iteration support. non-const iteration intentionally unsupported.
-
-  typedef std::map<std::string, octave_idx_type>::const_iterator const_iterator;
-  typedef const_iterator iterator;
-
-  const_iterator begin (void) const { return rep->begin (); }
-  const_iterator end (void) const { return rep->end (); }
-
-  std::string key (const_iterator p) const { return p->first; }
-  octave_idx_type index (const_iterator p) const { return p->second; }
-
-  const_iterator seek (const std::string& k) const
-    { return rep->find (k); }
-
-  // high-level methods.
-
-  // number of fields.
-  octave_idx_type nfields (void) const { return rep->size (); }
-
-  // check whether a field exists.
-  bool isfield (const std::string& name) const;
-
-  // get index of field. return -1 if not exist
-  octave_idx_type getfield (const std::string& name) const;
-  // get index of field. add if not exist
-  octave_idx_type getfield (const std::string& name);
-  // remove field and return the index. -1 if didn't exist.
-  octave_idx_type rmfield (const std::string& name);
-
-  // order the fields of this map. creates a permutation
-  // used to order the fields.
-  void orderfields (Array<octave_idx_type>& perm);
-
-  // compares two instances for equality up to order of fields.
-  // returns a permutation needed to bring the fields of *other*
-  // into the order of *this*.
-  bool equal_up_to_order (const octave_fields& other,
-                          octave_idx_type* perm) const;
-
-  bool equal_up_to_order (const octave_fields& other,
-                          Array<octave_idx_type>& perm) const;
-
-  bool is_same (const octave_fields& other) const
-    { return rep == other.rep; }
-
-  // Returns the fields as a vector of strings.
-  string_vector fieldnames (void) const;
-
-  void clear (void)
-    {
-      *this = octave_fields ();
-    }
-};
-
-
-class OCTINTERP_API
-octave_scalar_map
-{
-public:
-
-  octave_scalar_map (const octave_fields& k)
-    : xkeys (k), xvals (k.nfields ()) { }
-
-  octave_scalar_map (void) : xkeys (), xvals () { }
-
-  octave_scalar_map (const string_vector& k)
-    : xkeys (k), xvals (k.length ()) { }
-
-  octave_scalar_map (const octave_scalar_map& m)
-    : xkeys (m.xkeys), xvals(m.xvals) { }
-
-  octave_scalar_map& operator = (const octave_scalar_map& m)
-    {
-      xkeys = m.xkeys;
-      xvals = m.xvals;
-
-      return *this;
-    }
-
-  // iteration support. note that both const and non-const iterators are the
-  // same. The const/non-const distinction is made by the key & contents method.
-  typedef octave_fields::const_iterator const_iterator;
-  typedef const_iterator iterator;
-
-  const_iterator begin (void) const { return xkeys.begin (); }
-  const_iterator end (void) const { return xkeys.end (); }
-
-  const_iterator seek (const std::string& k) const { return xkeys.seek (k); }
-
-  std::string key (const_iterator p) const
-    { return xkeys.key (p); }
-  octave_idx_type index (const_iterator p) const
-    { return xkeys.index (p); }
-
-  const octave_value& contents (const_iterator p) const
-    { return xvals[xkeys.index (p)]; }
-
-  octave_value& contents (iterator p)
-    { return xvals[xkeys.index (p)]; }
-
-  const octave_value& contents (octave_idx_type i) const
-    { return xvals[i]; }
-
-  octave_value& contents (octave_idx_type i)
-    { return xvals[i]; }
-
-  // number of fields.
-  octave_idx_type nfields (void) const { return xkeys.nfields (); }
-
-  // check whether a field exists.
-  bool isfield (const std::string& name) const
-    { return xkeys.isfield (name); }
-
-  bool contains (const std::string& name) const
-    { return isfield (name); }
-
-  string_vector fieldnames (void) const
-    { return xkeys.fieldnames (); }
-
-  string_vector keys (void) const
-    { return fieldnames (); }
-
-  // get contents of a given field. empty value if not exist.
-  octave_value getfield (const std::string& key) const;
-
-  // set contents of a given field. add if not exist.
-  void setfield (const std::string& key, const octave_value& val);
-  void assign (const std::string& k, const octave_value& val)
-    { setfield (k, val); }
-
-  // remove a given field. do nothing if not exist.
-  void rmfield (const std::string& key);
-  void del (const std::string& k) { rmfield (k); }
-
-  // return a copy with fields ordered, optionally along with permutation.
-  octave_scalar_map orderfields (void) const;
-  octave_scalar_map orderfields (Array<octave_idx_type>& perm) const;
-  octave_scalar_map orderfields (const octave_scalar_map& other,
-                                 Array<octave_idx_type>& perm) const;
-
-  // aka getfield/setfield, but the latter returns a reference.
-  octave_value contents (const std::string& k) const;
-  octave_value& contents (const std::string& k);
-
-  void clear (void)
-    {
-      xkeys.clear ();
-      xvals.clear ();
-    }
-
-  friend class octave_map;
-
-private:
-
-  octave_fields xkeys;
-  std::vector<octave_value> xvals;
-
-};
-
-template<>
-inline octave_scalar_map octave_value_extract<octave_scalar_map> (const octave_value& v)
-  { return v.scalar_map_value (); }
-
-class OCTINTERP_API
-octave_map
-{
-public:
-
-  octave_map (const octave_fields& k)
-    : xkeys (k), xvals (k.nfields ()), dimensions () { }
-
-  octave_map (const dim_vector& dv, const octave_fields& k)
-    : xkeys (k), xvals (k.nfields (), Cell (dv)), dimensions (dv) { }
-
-  typedef octave_scalar_map element_type;
-
-  octave_map (void) : xkeys (), xvals (), dimensions () { }
-
-  octave_map (const dim_vector& dv) : xkeys (), xvals (), dimensions (dv) { }
-
-  octave_map (const string_vector& k)
-    : xkeys (k), xvals (k.length (), Cell (1, 1)), dimensions (1, 1) { }
-
-  octave_map (const dim_vector& dv, const string_vector& k)
-    : xkeys (k), xvals (k.length (), Cell (dv)), dimensions (dv) { }
-
-  octave_map (const octave_map& m)
-    : xkeys (m.xkeys), xvals (m.xvals), dimensions (m.dimensions) { }
-
-  octave_map (const octave_scalar_map& m);
-
-  octave_map (const Octave_map& m);
-
-  octave_map& operator = (const octave_map& m)
-    {
-      xkeys = m.xkeys;
-      xvals = m.xvals;
-      dimensions = m.dimensions;
-
-      return *this;
-    }
-
-  // iteration support. note that both const and non-const iterators are the
-  // same. The const/non-const distinction is made by the key & contents method.
-  typedef octave_fields::const_iterator const_iterator;
-  typedef const_iterator iterator;
-
-  const_iterator begin (void) const { return xkeys.begin (); }
-  const_iterator end (void) const { return xkeys.end (); }
-
-  const_iterator seek (const std::string& k) const { return xkeys.seek (k); }
-
-  std::string key (const_iterator p) const
-    { return xkeys.key (p); }
-  octave_idx_type index (const_iterator p) const
-    { return xkeys.index (p); }
-
-  const Cell& contents (const_iterator p) const
-    { return xvals[xkeys.index (p)]; }
-
-  Cell& contents (iterator p)
-    { return xvals[xkeys.index (p)]; }
-
-  const Cell& contents (octave_idx_type i) const
-    { return xvals[i]; }
-
-  Cell& contents (octave_idx_type i)
-    { return xvals[i]; }
-
-  // number of fields.
-  octave_idx_type nfields (void) const { return xkeys.nfields (); }
-
-  // check whether a field exists.
-  bool isfield (const std::string& name) const
-    { return xkeys.isfield (name); }
-
-  bool contains (const std::string& name) const
-    { return isfield (name); }
-
-  string_vector fieldnames (void) const
-    { return xkeys.fieldnames (); }
-
-  string_vector keys (void) const
-    { return fieldnames (); }
-
-  // get contents of a given field. empty value if not exist.
-  Cell getfield (const std::string& key) const;
-
-  // set contents of a given field. add if not exist. checks for
-  // correct dimensions.
-  void setfield (const std::string& key, const Cell& val);
-  void assign (const std::string& k, const Cell& val)
-    { setfield (k, val); }
-
-  // remove a given field. do nothing if not exist.
-  void rmfield (const std::string& key);
-  void del (const std::string& k) { rmfield (k); }
-
-  // return a copy with fields ordered, optionally along with permutation.
-  octave_map orderfields (void) const;
-  octave_map orderfields (Array<octave_idx_type>& perm) const;
-  octave_map orderfields (const octave_map& other,
-                          Array<octave_idx_type>& perm) const;
-
-  // aka getfield/setfield, but the latter returns a reference.
-  Cell contents (const std::string& k) const;
-  Cell& contents (const std::string& k);
-
-  void clear (void)
-    {
-      xkeys.clear ();
-      xvals.clear ();
-    }
-
-  // The Array-like methods.
-  octave_idx_type numel (void) const { return dimensions.numel (); }
-  octave_idx_type length (void) const { return numel (); }
-  bool is_empty (void) const { return dimensions.any_zero (); }
-
-  octave_idx_type rows (void) const { return dimensions(0); }
-  octave_idx_type cols (void) const { return dimensions(1); }
-  octave_idx_type columns (void) const { return dimensions(1); }
-
-  // Extract a scalar substructure.
-  octave_scalar_map checkelem (octave_idx_type n) const;
-  octave_scalar_map checkelem (octave_idx_type i, octave_idx_type j) const;
-
-  octave_scalar_map
-  checkelem (const Array<octave_idx_type>& ra_idx) const;
-
-  octave_scalar_map operator () (octave_idx_type n) const
-    { return checkelem (n); }
-  octave_scalar_map operator () (octave_idx_type i, octave_idx_type j) const
-    { return checkelem (i, j); }
-
-  octave_scalar_map
-  operator () (const Array<octave_idx_type>& ra_idx) const
-    { return checkelem (ra_idx); }
-
-  octave_map squeeze (void) const;
-
-  octave_map permute (const Array<int>& vec, bool inv = false) const;
-
-  dim_vector dims (void) const { return dimensions; }
-
-  int ndims (void) const { return dimensions.length (); }
-
-  octave_map transpose (void) const;
-
-  octave_map reshape (const dim_vector& dv) const;
-
-  void resize (const dim_vector& dv, bool fill = false);
-
-  static octave_map
-  cat (int dim, octave_idx_type n, const octave_scalar_map *map_list);
-
-  static octave_map
-  cat (int dim, octave_idx_type n, const octave_map *map_list);
-
-  octave_map index (const idx_vector& i, bool resize_ok = false) const;
-
-  octave_map index (const idx_vector& i, const idx_vector& j,
-                    bool resize_ok = false) const;
-
-  octave_map index (const Array<idx_vector>& ia,
-                    bool resize_ok = false) const;
-
-  octave_map index (const octave_value_list&, bool resize_ok = false) const;
-
-  octave_map column (octave_idx_type k) const;
-  octave_map page (octave_idx_type k) const;
-
-  void assign (const idx_vector& i, const octave_map& rhs);
-
-  void assign (const idx_vector& i, const idx_vector& j, const octave_map& rhs);
-
-  void assign (const Array<idx_vector>& ia, const octave_map& rhs);
-
-  void assign (const octave_value_list&, const octave_map& rhs);
-
-  void assign (const octave_value_list& idx, const std::string& k,
-               const Cell& rhs);
-
-  void delete_elements (const idx_vector& i);
-
-  void delete_elements (int dim, const idx_vector& i);
-
-  void delete_elements (const Array<idx_vector>& ia);
-
-  void delete_elements (const octave_value_list&);
-
-  octave_map concat (const octave_map& rb, const Array<octave_idx_type>& ra_idx);
-
-  // like checkelem, but no check.
-  octave_scalar_map fast_elem_extract (octave_idx_type n) const;
-
-  // element assignment, no bounds check
-  bool fast_elem_insert (octave_idx_type n, const octave_scalar_map& rhs);
-
-private:
-
-  octave_fields xkeys;
-  std::vector<Cell> xvals;
-  dim_vector dimensions;
-
-  void optimize_dimensions (void);
-  void extract_scalar (octave_scalar_map& dest,
-                       octave_idx_type index) const;
-  static void do_cat (int dim, octave_idx_type n,
-                      const octave_scalar_map *map_list, octave_map& retval);
-  static void do_cat (int dim, octave_idx_type n,
-                      const octave_map *map_list, octave_map& retval);
-};
-
-template<>
-inline octave_map octave_value_extract<octave_map> (const octave_value& v)
-  { return v.map_value (); }
-
-// The original Octave_map object. Octave_map and octave_map are convertible to
-// each other.
-
-class
-OCTINTERP_API
-Octave_map
-{
- public:
-
-  typedef std::map<std::string, Cell>::iterator iterator;
-  typedef std::map<std::string, Cell>::const_iterator const_iterator;
-
-  typedef std::list<std::string>::iterator key_list_iterator;
-  typedef std::list<std::string>::const_iterator const_key_list_iterator;
-
-  // Warning!  You should always use at least two dimensions.
-
-  Octave_map (const dim_vector& dv = dim_vector (0, 0),
-              const Cell& key_vals = Cell ());
-
-  Octave_map (const std::string& k, const octave_value& value)
-    : map (), key_list (), dimensions (1, 1)
-  {
-    map[k] = value;
-    key_list.push_back (k);
-  }
-
-  Octave_map (const string_vector& sv,
-              const dim_vector& dv = dim_vector (0, 0))
-    : map (), key_list (), dimensions (dv)
-  {
-    for (octave_idx_type i = 0; i < sv.length (); i++)
-      {
-        std::string k = sv[i];
-        map[k] = Cell (dv);
-        key_list.push_back (k);
-      }
-  }
-
-  Octave_map (const std::string& k, const Cell& vals)
-    : map (), key_list (), dimensions (vals.dims ())
-  {
-    map[k] = vals;
-    key_list.push_back (k);
-  }
-
-  Octave_map (const std::string& k, const octave_value_list& val_list)
-    : map (), key_list (), dimensions (1, val_list.length ())
-  {
-    map[k] = val_list;
-    key_list.push_back (k);
-  }
-
-  Octave_map (const Octave_map& m)
-    : map (m.map), key_list (m.key_list), dimensions (m.dimensions) { }
-
-  Octave_map (const octave_map& m);
-
-  Octave_map& operator = (const Octave_map& m)
-    {
-      if (this != &m)
-        {
-          map = m.map;
-          key_list = m.key_list;
-          dimensions = m.dimensions;
-        }
-
-      return *this;
-    }
-
-  ~Octave_map (void) { }
-
-  Octave_map squeeze (void) const;
-
-  Octave_map permute (const Array<int>& vec, bool inv = false) const;
-
-  // This is the number of keys.
-  octave_idx_type nfields (void) const { return map.size (); }
-
-  void del (const std::string& k)
-    {
-      iterator p = map.find (k);
-
-      if (p != map.end ())
-        {
-          map.erase (p);
-
-          key_list_iterator q
-            = std::find (key_list.begin (), key_list.end (), k);
-
-          assert (q != key_list.end ());
-
-          key_list.erase (q);
-        }
-    }
-
-  iterator begin (void) { return iterator (map.begin ()); }
-  const_iterator begin (void) const { return const_iterator (map.begin ()); }
-
-  iterator end (void) { return iterator (map.end ()); }
-  const_iterator end (void) const { return const_iterator (map.end ()); }
-
-  std::string key (const_iterator p) const { return p->first; }
-
-  Cell& contents (const std::string& k);
-  Cell contents (const std::string& k) const;
-
-  Cell& contents (iterator p)
-    { return p->second; }
-
-  Cell contents (const_iterator p) const
-    { return p->second; }
-
-  int intfield (const std::string& k, int def_val = 0) const;
-
-  std::string stringfield (const std::string& k,
-                           const std::string& def_val = std::string ()) const;
-
-  iterator seek (const std::string& k) { return map.find (k); }
-  const_iterator seek (const std::string& k) const { return map.find (k); }
-
-  bool contains (const std::string& k) const
-    { return (seek (k) != map.end ()); }
-
-  void clear (void)
-    {
-      map.clear ();
-      key_list.clear ();
-    }
-
-  string_vector keys (void) const;
-
-  octave_idx_type rows (void) const { return dimensions(0); }
-
-  octave_idx_type columns (void) const { return dimensions(1); }
-
-  dim_vector dims (void) const { return dimensions; }
-
-  int ndims (void) const { return dimensions.length (); }
-
-  Octave_map transpose (void) const;
-
-  Octave_map reshape (const dim_vector& new_dims) const;
-
-  void resize (const dim_vector& dv, bool fill = false);
-
-  octave_idx_type numel (void) const { return dimensions.numel (); }
-
-  Octave_map concat (const Octave_map& rb, const Array<octave_idx_type>& ra_idx);
-
-  Octave_map& maybe_delete_elements (const octave_value_list& idx);
-
-  Octave_map& assign (const octave_value_list& idx, const Octave_map& rhs);
-
-  Octave_map& assign (const octave_value_list& idx, const std::string& k,
-                      const Cell& rhs);
-
-  Octave_map& assign (const std::string& k, const octave_value& rhs);
-
-  Octave_map& assign (const std::string& k, const Cell& rhs);
-
-  Octave_map index (const octave_value_list& idx,
-                    bool resize_ok = false) const;
-
-private:
-
-  // The map of names to values.
-  std::map<std::string, Cell> map;
-
-  // An extra list of keys, so we can keep track of the order the keys
-  // are added for compatibility with you know what.
-  std::list<std::string> key_list;
-
-  // The current size.
-  mutable dim_vector dimensions;
-
-  void maybe_add_to_key_list (const std::string& k)
-    {
-      if (! contains (k))
-        key_list.push_back (k);
-    }
-};
-
-#endif
--- a/src/oct-obj.cc	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,284 +0,0 @@
-/*
-
-Copyright (C) 1994-2012 John W. Eaton
-Copyright (C) 2009 VZLU Prague
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "error.h"
-#include "oct-obj.h"
-#include "Cell.h"
-
-// We are likely to have a lot of octave_value_list objects to allocate,
-// so make the grow_size large.
-DEFINE_OCTAVE_ALLOCATOR2(octave_value_list, 1024);
-
-octave_value_list::octave_value_list (const std::list<octave_value_list>& lst)
-{
-  octave_idx_type n = 0, nel = 0;
-
-  // Determine number.
-  for (std::list<octave_value_list>::const_iterator p = lst.begin ();
-       p != lst.end (); p++)
-    {
-      n++;
-      nel += p->length ();
-    }
-
-  // Optimize single-element case
-  if (n == 1)
-    data = lst.front ().data;
-  else if (nel > 0)
-    {
-      data.resize (dim_vector (1, nel));
-      octave_idx_type k = 0;
-      for (std::list<octave_value_list>::const_iterator p = lst.begin ();
-           p != lst.end (); p++)
-        {
-          data.assign (idx_vector (k, k + p->length ()), p->data);
-          k += p->length ();
-        }
-      assert (k == nel);
-    }
-
-}
-
-octave_value_list&
-octave_value_list::prepend (const octave_value& val)
-{
-  octave_idx_type n = length ();
-
-  resize (n + 1);
-
-  while (n > 0)
-    {
-      elem (n) = elem (n - 1);
-      n--;
-    }
-
-  elem (0) = val;
-
-  return *this;
-}
-
-octave_value_list&
-octave_value_list::append (const octave_value& val)
-{
-  octave_idx_type n = length ();
-
-  resize (n + 1);
-
-  elem (n) = val;
-
-  return *this;
-}
-
-octave_value_list&
-octave_value_list::append (const octave_value_list& lst)
-{
-  octave_idx_type len = length ();
-  octave_idx_type lst_len = lst.length ();
-
-  resize (len + lst_len);
-
-  for (octave_idx_type i = 0; i < lst_len; i++)
-    elem (len + i) = lst (i);
-
-  return *this;
-}
-
-octave_value_list&
-octave_value_list::reverse (void)
-{
-  octave_idx_type n = length ();
-
-  for (octave_idx_type i = 0; i < n / 2; i++)
-    {
-      octave_value tmp = elem (i);
-      elem (i) = elem (n - i - 1);
-      elem (n - i - 1) = tmp;
-    }
-
-  return *this;
-}
-
-octave_value_list
-octave_value_list::splice (octave_idx_type offset, octave_idx_type rep_length,
-                           const octave_value_list& lst) const
-{
-  octave_value_list retval;
-
-  octave_idx_type len = length ();
-
-  if (offset < 0 || offset >= len)
-    {
-      if (! (rep_length == 0 && offset == len))
-        {
-          error ("octave_value_list::splice: invalid OFFSET");
-          return retval;
-        }
-    }
-
-  if (rep_length < 0 || rep_length + offset > len)
-    {
-      error ("octave_value_list::splice: invalid LENGTH");
-      return retval;
-    }
-
-  octave_idx_type lst_len = lst.length ();
-
-  octave_idx_type new_len = len - rep_length + lst_len;
-
-  retval.resize (new_len);
-
-  octave_idx_type k = 0;
-
-  for (octave_idx_type i = 0; i < offset; i++)
-    retval(k++) = elem (i);
-
-  for (octave_idx_type i = 0; i < lst_len; i++)
-    retval(k++) = lst (i);
-
-  for (octave_idx_type i = offset + rep_length; i < len; i++)
-    retval(k++) = elem (i);
-
-  return retval;
-}
-
-bool
-octave_value_list::all_strings_p (void) const
-{
-  octave_idx_type n = length ();
-
-  for (octave_idx_type i = 0; i < n; i++)
-    if (! elem(i).is_string ())
-      return false;
-
-  return true;
-}
-
-bool
-octave_value_list::all_scalars (void) const
-{
-  octave_idx_type n = length ();
-
-  for (octave_idx_type i = 0; i < n; i++)
-    {
-      dim_vector dv = elem(i).dims ();
-      if (! dv.all_ones ())
-        return false;
-    }
-
-  return true;
-}
-
-bool
-octave_value_list::any_cell (void) const
-{
-  octave_idx_type n = length ();
-
-  for (octave_idx_type i = 0; i < n; i++)
-    if (elem (i).is_cell ())
-      return true;
-
-  return false;
-}
-
-bool
-octave_value_list::has_magic_colon (void) const
-{
-  octave_idx_type n = length ();
-
-  for (octave_idx_type i = 0; i < n; i++)
-    if (elem(i).is_magic_colon ())
-      return true;
-
-  return false;
-}
-
-string_vector
-octave_value_list::make_argv (const std::string& fcn_name) const
-{
-  string_vector argv;
-
-  if (all_strings_p ())
-    {
-      octave_idx_type len = length ();
-
-      octave_idx_type total_nr = 0;
-
-      for (octave_idx_type i = 0; i < len; i++)
-        {
-          // An empty std::string ("") has zero columns and zero rows (a
-          // change that was made for Matlab contemptibility.
-
-          octave_idx_type n = elem(i).rows ();
-
-          total_nr += n ? n : 1;
-        }
-
-      octave_idx_type k = 0;
-      if (! fcn_name.empty ())
-        {
-          argv.resize (total_nr+1);
-          argv[0] = fcn_name;
-          k = 1;
-        }
-      else
-        argv.resize (total_nr);
-
-      for (octave_idx_type i = 0; i < len; i++)
-        {
-          octave_idx_type nr = elem(i).rows ();
-
-          if (nr < 2)
-            argv[k++] = elem(i).string_value ();
-          else
-            {
-              string_vector tmp = elem(i).all_strings ();
-
-              for (octave_idx_type j = 0; j < nr; j++)
-                argv[k++] = tmp[j];
-            }
-        }
-    }
-  else
-    error ("%s: expecting all arguments to be strings", fcn_name.c_str ());
-
-  return argv;
-}
-
-void
-octave_value_list::make_storable_values (void)
-{
-  octave_idx_type len = length ();
-  const Array<octave_value>& cdata = data;
-
-  for (octave_idx_type i = 0; i < len; i++)
-    {
-      // This is optimized so that we don't force a copy unless necessary.
-      octave_value tmp = cdata(i).storable_value ();
-      if (! tmp.is_copy_of (cdata (i)))
-        data(i) = tmp;
-    }
-}
--- a/src/oct-obj.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,169 +0,0 @@
-/*
-
-Copyright (C) 1994-2012 John W. Eaton
-Copyright (C) 2009 VZLU Prague
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#if !defined (octave_oct_obj_h)
-#define octave_oct_obj_h 1
-
-#include <string>
-#include <vector>
-
-#include "oct-alloc.h"
-#include "str-vec.h"
-#include "Array.h"
-
-#include "ov.h"
-#include "Cell.h"
-
-class
-OCTINTERP_API
-octave_value_list
-{
-public:
-
-  octave_value_list (void)
-    : data (), names () { }
-
-  explicit octave_value_list (octave_idx_type n)
-    : data (dim_vector (1, n)), names () { }
-
-  octave_value_list (octave_idx_type n, const octave_value& val)
-    : data (dim_vector (1, n), val), names () { }
-
-  octave_value_list (const octave_value& tc)
-    : data (dim_vector (1, 1), tc), names () { }
-
-  octave_value_list (const Array<octave_value>& d)
-    : data (d.as_row ()), names () { }
-
-  octave_value_list (const Cell& tc)
-    : data (tc.as_row ()), names () { }
-
-  octave_value_list (const octave_value_list& obj)
-    : data (obj.data), names (obj.names) { }
-
-  // Concatenation constructor.
-  octave_value_list (const std::list<octave_value_list>&);
-
-  ~octave_value_list (void) { }
-
-  octave_value_list& operator = (const octave_value_list& obj)
-    {
-      if (this != &obj)
-        {
-          data = obj.data;
-          names = obj.names;
-        }
-
-      return *this;
-    }
-
-  Array<octave_value> array_value (void) const { return data; }
-
-  Cell cell_value (void) const { return array_value (); }
-
-  // Assignment will resize on range errors.
-
-  octave_value& operator () (octave_idx_type n) { return elem (n); }
-
-  const octave_value& operator () (octave_idx_type n) const { return elem (n); }
-
-  octave_idx_type length (void) const { return data.length (); }
-
-  bool empty (void) const { return length () == 0; }
-
-  void resize (octave_idx_type n, const octave_value& rfv = octave_value ())
-  {
-    data.resize (dim_vector (1, n), rfv);
-  }
-
-  octave_value_list& prepend (const octave_value& val);
-
-  octave_value_list& append (const octave_value& val);
-
-  octave_value_list& append (const octave_value_list& lst);
-
-  octave_value_list& reverse (void);
-
-  octave_value_list
-  slice (octave_idx_type offset, octave_idx_type len, bool tags = false) const
-    {
-      octave_value_list retval (data.linear_slice (offset, offset + len));
-      if (tags && len > 0 && names.length () > 0)
-        retval.names = names.linear_slice (offset, std::min (len, names.length ()));
-
-      return retval;
-    }
-
-  octave_value_list
-  splice (octave_idx_type offset, octave_idx_type len,
-          const octave_value_list& lst = octave_value_list ()) const;
-
-  bool all_strings_p (void) const;
-
-  bool all_scalars (void) const;
-
-  bool any_cell (void) const;
-
-  bool has_magic_colon (void) const;
-
-  string_vector make_argv (const std::string& = std::string ()) const;
-
-  void stash_name_tags (const string_vector& nm) { names = nm; }
-
-  string_vector name_tags (void) const { return names; }
-
-  void make_storable_values (void);
-
-  octave_value& xelem (octave_idx_type i)
-    {
-      return data.xelem (i);
-    }
-
-  void clear (void)
-    {
-      data.clear ();
-    }
-
-private:
-
-  Array<octave_value> data;
-
-  // This list of strings can be used to tag each element of data with
-  // a name.  By default, it is empty.
-  string_vector names;
-
-  octave_value& elem (octave_idx_type n)
-    {
-      if (n >= length ())
-        resize (n + 1);
-
-      return data(n);
-    }
-
-  const octave_value& elem (octave_idx_type n) const
-    { return data(n); }
-
-  DECLARE_OCTAVE_ALLOCATOR
-};
-
-#endif
--- a/src/oct-prcstrm.cc	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-/*
-
-Copyright (C) 1996-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <cstdio>
-
-#include "oct-prcstrm.h"
-#include "sysdep.h"
-
-octave_stream
-octave_iprocstream::create (const std::string& n, std::ios::openmode arg_md,
-                            oct_mach_info::float_format ff)
-{
-  return octave_stream (new octave_iprocstream (n, arg_md, ff));
-}
-
-octave_iprocstream::octave_iprocstream (const std::string& n,
-                                        std::ios::openmode arg_md,
-                                        oct_mach_info::float_format ff)
-  : octave_stdiostream (n, octave_popen (n.c_str (), "r"),
-                        arg_md, ff, octave_pclose)
-{
-}
-
-octave_iprocstream::~octave_iprocstream (void)
-{
-  do_close ();
-}
-
-octave_stream
-octave_oprocstream::create (const std::string& n, std::ios::openmode arg_md,
-                            oct_mach_info::float_format ff)
-{
-  return octave_stream (new octave_oprocstream (n, arg_md, ff));
-}
-
-octave_oprocstream::octave_oprocstream (const std::string& n,
-                                        std::ios::openmode arg_md,
-                                        oct_mach_info::float_format ff)
-  : octave_stdiostream (n, octave_popen (n.c_str (), "w"),
-                        arg_md, ff, octave_pclose)
-{
-}
-
-octave_oprocstream::~octave_oprocstream (void)
-{
-  do_close ();
-}
--- a/src/oct-prcstrm.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-/*
-
-Copyright (C) 1996-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#if !defined (octave_octave_procstream_h)
-#define octave_octave_procstream_h 1
-
-#include "oct-stdstrm.h"
-
-// FIXME -- why don't these classes use iprocstream and
-// oprocstream, which in turn use the octave_procbuf class?
-
-class
-octave_iprocstream : public octave_stdiostream
-{
-public:
-
-  octave_iprocstream (const std::string& n,
-                      std::ios::openmode arg_md = std::ios::in,
-                      oct_mach_info::float_format flt_fmt
-                        = oct_mach_info::native_float_format ());
-
-  static octave_stream
-  create (const std::string& n, std::ios::openmode arg_md = std::ios::in,
-          oct_mach_info::float_format flt_fmt
-            = oct_mach_info::native_float_format ());
-
-protected:
-
-  ~octave_iprocstream (void);
-
-private:
-
-  // No copying!
-
-  octave_iprocstream (const octave_iprocstream&);
-
-  octave_iprocstream& operator = (const octave_iprocstream&);
-};
-
-class
-octave_oprocstream : public octave_stdiostream
-{
-public:
-
-  octave_oprocstream (const std::string& n,
-                      std::ios::openmode arg_md = std::ios::out,
-                      oct_mach_info::float_format flt_fmt
-                        = oct_mach_info::native_float_format ());
-
-  static octave_stream
-  create (const std::string& n, std::ios::openmode arg_md = std::ios::out,
-          oct_mach_info::float_format flt_fmt
-            = oct_mach_info::native_float_format ());
-
-protected:
-
-  ~octave_oprocstream (void);
-
-private:
-
-  // No copying!
-
-  octave_oprocstream (const octave_oprocstream&);
-
-  octave_oprocstream& operator = (const octave_oprocstream&);
-};
-
-#endif
--- a/src/oct-procbuf.cc	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,218 +0,0 @@
-/*
-
-Copyright (C) 1996-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <cerrno>
-
-#include <iostream>
-
-#include <sys/types.h>
-#include <unistd.h>
-
-#include "lo-mappers.h"
-#include "lo-utils.h"
-#include "oct-procbuf.h"
-#include "oct-syscalls.h"
-#include "sysdep.h"
-#include "variables.h"
-
-#include "defun.h"
-#include "gripes.h"
-#include "utils.h"
-
-// This class is based on the procbuf class from libg++, written by
-// Per Bothner, Copyright (C) 1993 Free Software Foundation.
-
-static octave_procbuf *octave_procbuf_list = 0;
-
-#ifndef BUFSIZ
-#define BUFSIZ 1024
-#endif
-
-octave_procbuf *
-octave_procbuf::open (const char *command, int mode)
-{
-#if defined (__CYGWIN__) || defined (__MINGW32__) || defined (_MSC_VER)
-
-  if (is_open ())
-    return 0;
-
-  f = octave_popen (command, (mode & std::ios::in) ? "r" : "w");
-
-  if (! f)
-    return 0;
-
-  // Oops... popen doesn't return the associated pid, so fake it for now
-
-  proc_pid = 1;
-
-  open_p = true;
-
-  if (mode & std::ios::out)
-    ::setvbuf (f, 0, _IOLBF, BUFSIZ);
-
-  return this;
-
-#elif defined (HAVE_SYS_WAIT_H)
-
-  int pipe_fds[2];
-
-  volatile int child_std_end = (mode & std::ios::in) ? 1 : 0;
-
-  volatile int parent_end, child_end;
-
-  if (is_open ())
-    return 0;
-
-  if (pipe (pipe_fds) < 0)
-    return 0;
-
-  if (mode & std::ios::in)
-    {
-      parent_end = pipe_fds[0];
-      child_end = pipe_fds[1];
-    }
-  else
-    {
-      parent_end = pipe_fds[1];
-      child_end = pipe_fds[0];
-    }
-
-  proc_pid = ::fork ();
-
-  if (proc_pid == 0)
-    {
-      gnulib::close (parent_end);
-
-      if (child_end != child_std_end)
-        {
-          gnulib::dup2 (child_end, child_std_end);
-          gnulib::close (child_end);
-        }
-
-      while (octave_procbuf_list)
-        {
-          FILE *fp = octave_procbuf_list->f;
-
-          if (fp)
-            {
-              gnulib::fclose (fp);
-              fp = 0;
-            }
-
-          octave_procbuf_list = octave_procbuf_list->next;
-        }
-
-      execl ("/bin/sh", "sh", "-c", command, static_cast<void *> (0));
-
-      exit (127);
-    }
-
-  gnulib::close (child_end);
-
-  if (proc_pid < 0)
-    {
-      gnulib::close (parent_end);
-      return 0;
-    }
-
-  f = ::fdopen (parent_end, (mode & std::ios::in) ? "r" : "w");
-
-  if (mode & std::ios::out)
-    ::setvbuf (f, 0, _IOLBF, BUFSIZ);
-
-  open_p = true;
-
-  next = octave_procbuf_list;
-  octave_procbuf_list = this;
-
-  return this;
-
-#else
-
-  return 0;
-
-#endif
-}
-
-octave_procbuf *
-octave_procbuf::close (void)
-{
-#if defined (__CYGWIN__) || defined (__MINGW32__) || defined (_MSC_VER)
-
-  if (f)
-    {
-      wstatus = octave_pclose (f);
-      f = 0;
-    }
-
-  open_p = false;
-
-  return this;
-
-#elif defined (HAVE_SYS_WAIT_H)
-
-  if (f)
-    {
-      pid_t wait_pid;
-
-      int status = -1;
-
-      for (octave_procbuf **ptr = &octave_procbuf_list;
-           *ptr != 0;
-           ptr = &(*ptr)->next)
-        {
-          if (*ptr == this)
-            {
-              *ptr = (*ptr)->next;
-              status = 0;
-              break;
-            }
-        }
-
-      if (status == 0 && gnulib::fclose (f) == 0)
-        {
-          using namespace std;
-
-          do
-            {
-              wait_pid = octave_syscalls::waitpid (proc_pid, &wstatus, 0);
-            }
-          while (wait_pid == -1 && errno == EINTR);
-        }
-
-      f = 0;
-    }
-
-  open_p = false;
-
-  return this;
-
-#else
-
-  return 0;
-
-#endif
-}
--- a/src/oct-procbuf.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-/*
-
-Copyright (C) 1996-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-// This class is based on the procbuf class from libg++, written by
-// Per Bothner, Copyright (C) 1993 Free Software Foundation.
-
-#if !defined (octave_octave_procbuf_h)
-#define octave_octave_procbuf_h 1
-
-#include <sys/types.h>
-
-#include "c-file-ptr-stream.h"
-
-class
-octave_procbuf : public c_file_ptr_buf
-{
-public:
-
-  octave_procbuf (void)
-    : c_file_ptr_buf (0), wstatus (-1), open_p (false), proc_pid (-1),
-      next (0) { }
-
-  octave_procbuf (const char *command, int mode)
-    : c_file_ptr_buf (0), wstatus (-1), open_p (false), proc_pid (-1),
-      next (0) { open (command, mode); }
-
-  ~octave_procbuf (void) { close (); }
-
-  octave_procbuf *open (const char *command, int mode);
-
-  octave_procbuf *close (void);
-
-  int wait_status (void) const { return wstatus; }
-
-  bool is_open (void) const { return open_p; }
-
-  pid_t pid (void) const { return proc_pid; }
-
-protected:
-
-  int wstatus;
-
-  bool open_p;
-
-  pid_t proc_pid;
-
-  octave_procbuf *next;
-
-private:
-
-  // No copying!
-
-  octave_procbuf (const octave_procbuf&);
-
-  octave_procbuf& operator = (const octave_procbuf&);
-};
-
-extern void symbols_of_oct_procbuf (void);
-
-#endif
--- a/src/oct-stdstrm.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,175 +0,0 @@
-/*
-
-Copyright (C) 1996-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#if !defined (octave_octave_stdiostream_h)
-#define octave_octave_stdiostream_h 1
-
-#include "oct-stream.h"
-#include "c-file-ptr-stream.h"
-
-template <typename BUF_T, typename STREAM_T, typename FILE_T>
-class
-octave_tstdiostream : public octave_base_stream
-{
-public:
-
-  octave_tstdiostream (const std::string& n, FILE_T f = 0, int fid = 0,
-                       std::ios::openmode m = std::ios::in|std::ios::out,
-                       oct_mach_info::float_format ff
-                         = oct_mach_info::native_float_format (),
-                       typename BUF_T::close_fcn cf = BUF_T::file_close)
-    : octave_base_stream (m, ff), nm (n), md (m),
-      s (f ? new STREAM_T (f, cf) : 0), fnum (fid)
-  { }
-
-  // Position a stream at OFFSET relative to ORIGIN.
-
-  int seek (long offset, int origin)
-    { return s ? s->seek (offset, origin) : -1; }
-
-  // Return current stream position.
-
-  long tell (void) { return s ? s->tell () : -1; }
-
-  // Return non-zero if EOF has been reached on this stream.
-
-  bool eof (void) const { return s ? s->eof () : true; }
-
-  // The name of the file.
-
-  std::string name (void) const { return nm; }
-
-  std::istream *input_stream (void) { return (md & std::ios::in) ? s : 0; }
-
-  std::ostream *output_stream (void) { return (md & std::ios::out) ? s : 0; }
-
-  // FIXME -- should not have to cast away const here.
-  BUF_T *rdbuf (void) const
-    { return s ? (const_cast<STREAM_T *> (s))->rdbuf () : 0; }
-
-  int file_number (void) const { return fnum; }
-
-  bool bad (void) const { return s ? s->bad () : true; }
-
-  void clear (void) { if (s) s->clear (); }
-
-  void do_close (void) { if (s) s->stream_close (); }
-
-protected:
-
-  std::string nm;
-
-  std::ios::openmode md;
-
-  STREAM_T *s;
-
-  // The file number associated with this file.
-  int fnum;
-
-  ~octave_tstdiostream (void) { delete s; }
-
-private:
-
-  // No copying!
-
-  octave_tstdiostream (const octave_tstdiostream&);
-
-  octave_tstdiostream& operator = (const octave_tstdiostream&);
-};
-
-class
-octave_stdiostream
-  : public octave_tstdiostream<c_file_ptr_buf, io_c_file_ptr_stream, FILE *>
-{
-public:
-
-  octave_stdiostream (const std::string& n, FILE *f = 0,
-                      std::ios::openmode m = std::ios::in|std::ios::out,
-                      oct_mach_info::float_format ff
-                        = oct_mach_info::native_float_format (),
-                      c_file_ptr_buf::close_fcn cf = c_file_ptr_buf::file_close)
-    : octave_tstdiostream<c_file_ptr_buf, io_c_file_ptr_stream, FILE *> (n, f, f ? fileno (f) : -1, m, ff, cf) { }
-
-  static octave_stream
-  create (const std::string& n, FILE *f = 0,
-          std::ios::openmode m = std::ios::in|std::ios::out,
-          oct_mach_info::float_format ff
-            = oct_mach_info::native_float_format (),
-          c_file_ptr_buf::close_fcn cf = c_file_ptr_buf::file_close)
-  {
-    return octave_stream (new octave_stdiostream (n, f, m, ff, cf));
-  }
-
-protected:
-
-  ~octave_stdiostream (void) { }
-
-private:
-
-  // No copying!
-
-  octave_stdiostream (const octave_stdiostream&);
-
-  octave_stdiostream& operator = (const octave_stdiostream&);
-};
-
-#ifdef HAVE_ZLIB
-
-class
-octave_zstdiostream
-  : public octave_tstdiostream<c_zfile_ptr_buf, io_c_zfile_ptr_stream, gzFile>
-{
-public:
-
-  octave_zstdiostream (const std::string& n, gzFile f = 0, int fid = 0,
-                       std::ios::openmode m = std::ios::in|std::ios::out,
-                       oct_mach_info::float_format ff
-                         = oct_mach_info::native_float_format (),
-                       c_zfile_ptr_buf::close_fcn cf = c_zfile_ptr_buf::file_close)
-    : octave_tstdiostream<c_zfile_ptr_buf, io_c_zfile_ptr_stream, gzFile> (n, f, fid, m, ff, cf) { }
-
-  static octave_stream
-  create (const std::string& n, gzFile f = 0, int fid = 0,
-          std::ios::openmode m = std::ios::in|std::ios::out,
-          oct_mach_info::float_format ff
-            = oct_mach_info::native_float_format (),
-          c_zfile_ptr_buf::close_fcn cf = c_zfile_ptr_buf::file_close)
-  {
-    return octave_stream (new octave_zstdiostream (n, f, fid, m, ff, cf));
-  }
-
-protected:
-
-  ~octave_zstdiostream (void) { }
-
-private:
-
-  // No copying!
-
-  octave_zstdiostream (const octave_zstdiostream&);
-
-  octave_zstdiostream& operator = (const octave_zstdiostream&);
-};
-
-#endif
-
-#endif
--- a/src/oct-stream.cc	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4308 +0,0 @@
-/*
-
-Copyright (C) 1996-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <cassert>
-#include <cctype>
-#include <cstring>
-
-#include <iomanip>
-#include <iostream>
-#include <fstream>
-#include <sstream>
-#include <string>
-
-#include <Array.h>
-
-#include "byte-swap.h"
-#include "lo-ieee.h"
-#include "lo-mappers.h"
-#include "lo-utils.h"
-#include "quit.h"
-#include "singleton-cleanup.h"
-#include "str-vec.h"
-
-#include "error.h"
-#include "gripes.h"
-#include "input.h"
-#include "oct-stdstrm.h"
-#include "oct-stream.h"
-#include "oct-obj.h"
-#include "utils.h"
-
-// Possible values for conv_err:
-//
-//   1 : not a real scalar
-//   2 : value is NaN
-//   3 : value is not an integer
-
-static int
-convert_to_valid_int (const octave_value& tc, int& conv_err)
-{
-  int retval = 0;
-
-  conv_err = 0;
-
-  double dval = tc.double_value ();
-
-  if (! error_state)
-    {
-      if (! lo_ieee_isnan (dval))
-        {
-          int ival = NINT (dval);
-
-          if (ival == dval)
-            retval = ival;
-          else
-            conv_err = 3;
-        }
-      else
-        conv_err = 2;
-    }
-  else
-    conv_err = 1;
-
-  return retval;
-}
-
-static int
-get_size (double d, const std::string& who)
-{
-  int retval = -1;
-
-  if (! lo_ieee_isnan (d))
-    {
-      if (! xisinf (d))
-        {
-          if (d >= 0.0)
-            retval = NINT (d);
-          else
-            ::error ("%s: negative value invalid as size specification",
-                     who.c_str ());
-        }
-      else
-        retval = -1;
-    }
-  else
-    ::error ("%s: NaN is invalid as size specification", who.c_str ());
-
-  return retval;
-}
-
-static void
-get_size (const Array<double>& size, octave_idx_type& nr, octave_idx_type& nc, bool& one_elt_size_spec,
-          const std::string& who)
-{
-  nr = -1;
-  nc = -1;
-
-  one_elt_size_spec = false;
-
-  double dnr = -1.0;
-  double dnc = -1.0;
-
-  octave_idx_type sz_len = size.length ();
-
-  if (sz_len == 1)
-    {
-      one_elt_size_spec = true;
-
-      dnr = size (0);
-
-      dnc = (dnr == 0.0) ? 0.0 : 1.0;
-    }
-  else if (sz_len == 2)
-    {
-      dnr = size (0);
-
-      if (! xisinf (dnr))
-        dnc = size (1);
-      else
-        ::error ("%s: invalid size specification", who.c_str ());
-    }
-  else
-    ::error ("%s: invalid size specification", who.c_str ());
-
-  if (! error_state)
-    {
-      nr = get_size (dnr, who);
-
-      if (! error_state && dnc >= 0.0)
-        nc = get_size (dnc, who);
-    }
-}
-
-scanf_format_list::scanf_format_list (const std::string& s)
-  : nconv (0), curr_idx (0), list (dim_vector (16, 1)), buf (0)
-{
-  octave_idx_type num_elts = 0;
-
-  size_t n = s.length ();
-
-  size_t i = 0;
-
-  int width = 0;
-  bool discard = false;
-  char modifier = '\0';
-  char type = '\0';
-
-  bool have_more = true;
-
-  while (i < n)
-    {
-      have_more = true;
-
-      if (! buf)
-        buf = new std::ostringstream ();
-
-      if (s[i] == '%')
-        {
-          // Process percent-escape conversion type.
-
-          process_conversion (s, i, n, width, discard, type, modifier,
-                              num_elts);
-
-          have_more = (buf != 0);
-        }
-      else if (isspace (s[i]))
-        {
-          type = scanf_format_elt::whitespace_conversion;
-
-          width = 0;
-          discard = false;
-          modifier = '\0';
-          *buf << " ";
-
-          while (++i < n && isspace (s[i]))
-            /* skip whitespace */;
-
-          add_elt_to_list (width, discard, type, modifier, num_elts);
-
-          have_more = false;
-        }
-      else
-        {
-          type = scanf_format_elt::literal_conversion;
-
-          width = 0;
-          discard = false;
-          modifier = '\0';
-
-          while (i < n && ! isspace (s[i]) && s[i] != '%')
-            *buf << s[i++];
-
-          add_elt_to_list (width, discard, type, modifier, num_elts);
-
-          have_more = false;
-        }
-
-      if (nconv < 0)
-        {
-          have_more = false;
-          break;
-        }
-    }
-
-  if (have_more)
-    add_elt_to_list (width, discard, type, modifier, num_elts);
-
-  list.resize (dim_vector (num_elts, 1));
-
-  delete buf;
-}
-
-scanf_format_list::~scanf_format_list (void)
-{
-  octave_idx_type n = list.length ();
-
-  for (octave_idx_type i = 0; i < n; i++)
-    {
-      scanf_format_elt *elt = list(i);
-      delete elt;
-    }
-}
-
-void
-scanf_format_list::add_elt_to_list (int width, bool discard, char type,
-                                    char modifier, octave_idx_type& num_elts,
-                                    const std::string& char_class)
-{
-  if (buf)
-    {
-      std::string text = buf->str ();
-
-      if (! text.empty ())
-        {
-          scanf_format_elt *elt
-            = new scanf_format_elt (text.c_str (), width, discard, type,
-                                    modifier, char_class);
-
-          if (num_elts == list.length ())
-            list.resize (dim_vector (2 * num_elts, 1));
-
-          list(num_elts++) = elt;
-        }
-
-      delete buf;
-      buf = 0;
-    }
-}
-
-static std::string
-expand_char_class (const std::string& s)
-{
-  std::string retval;
-
-  size_t len = s.length ();
-
-  size_t i = 0;
-
-  while (i < len)
-    {
-      unsigned char c = s[i++];
-
-      if (c == '-' && i > 1 && i < len
-          && static_cast<unsigned char> (s[i-2]) <= static_cast<unsigned char> (s[i]))
-        {
-          // Add all characters from the range except the first (we
-          // already added it below).
-
-          for (c = s[i-2]+1; c < s[i]; c++)
-            retval += c;
-        }
-      else
-        {
-          // Add the character to the class.  Only add '-' if it is
-          // the last character in the class.
-
-          if (c != '-' || i == len)
-            retval += c;
-        }
-    }
-
-  return retval;
-}
-
-void
-scanf_format_list::process_conversion (const std::string& s, size_t& i,
-                                       size_t n, int& width, bool& discard,
-                                       char& type, char& modifier,
-                                       octave_idx_type& num_elts)
-{
-  width = 0;
-  discard = false;
-  modifier = '\0';
-  type = '\0';
-
-  *buf << s[i++];
-
-  bool have_width = false;
-
-  while (i < n)
-    {
-      switch (s[i])
-        {
-        case '*':
-          if (discard)
-            nconv = -1;
-          else
-            {
-              discard = true;
-              *buf << s[i++];
-            }
-          break;
-
-        case '0': case '1': case '2': case '3': case '4':
-        case '5': case '6': case '7': case '8': case '9':
-          if (have_width)
-            nconv = -1;
-          else
-            {
-              char c = s[i++];
-              width = width * 10 + c - '0';
-              have_width = true;
-              *buf << c;
-              while (i < n && isdigit (s[i]))
-                {
-                  c = s[i++];
-                  width = width * 10 + c - '0';
-                  *buf << c;
-                }
-            }
-          break;
-
-        case 'h': case 'l': case 'L':
-          if (modifier != '\0')
-            nconv = -1;
-          else
-            modifier = s[i++];
-          break;
-
-        case 'd': case 'i': case 'o': case 'u': case 'x':
-          if (modifier == 'L')
-            {
-              nconv = -1;
-              break;
-            }
-          goto fini;
-
-        case 'e': case 'f': case 'g':
-          if (modifier == 'h')
-            {
-              nconv = -1;
-              break;
-            }
-
-          // No float or long double conversions, thanks.
-          *buf << 'l';
-
-          goto fini;
-
-        case 'c': case 's': case 'p': case '%': case '[':
-          if (modifier != '\0')
-            {
-              nconv = -1;
-              break;
-            }
-          goto fini;
-
-        fini:
-          {
-            if (finish_conversion (s, i, n, width, discard, type,
-                                   modifier, num_elts) == 0)
-              return;
-          }
-          break;
-
-        default:
-          nconv = -1;
-          break;
-        }
-
-      if (nconv < 0)
-        break;
-    }
-
-  nconv = -1;
-}
-
-int
-scanf_format_list::finish_conversion (const std::string& s, size_t& i,
-                                      size_t n, int& width, bool discard,
-                                      char& type, char modifier,
-                                      octave_idx_type& num_elts)
-{
-  int retval = 0;
-
-  std::string char_class;
-
-  size_t beg_idx = std::string::npos;
-  size_t end_idx = std::string::npos;
-
-  if (s[i] == '%')
-    {
-      type = '%';
-      *buf << s[i++];
-    }
-  else
-    {
-      type = s[i];
-
-      if (s[i] == '[')
-        {
-          *buf << s[i++];
-
-          if (i < n)
-            {
-              beg_idx = i;
-
-              if (s[i] == '^')
-                {
-                  type = '^';
-                  *buf << s[i++];
-
-                  if (i < n)
-                    {
-                      beg_idx = i;
-
-                      if (s[i] == ']')
-                        *buf << s[i++];
-                    }
-                }
-              else if (s[i] == ']')
-                *buf << s[i++];
-            }
-
-          while (i < n && s[i] != ']')
-            *buf << s[i++];
-
-          if (i < n && s[i] == ']')
-            {
-              end_idx = i-1;
-              *buf << s[i++];
-            }
-
-          if (s[i-1] != ']')
-            retval = nconv = -1;
-        }
-      else
-        *buf << s[i++];
-
-      nconv++;
-    }
-
-  if (nconv >= 0)
-    {
-      if (beg_idx != std::string::npos && end_idx != std::string::npos)
-        char_class = expand_char_class (s.substr (beg_idx,
-                                                  end_idx - beg_idx + 1));
-
-      add_elt_to_list (width, discard, type, modifier, num_elts, char_class);
-    }
-
-  return retval;
-}
-
-void
-scanf_format_list::printme (void) const
-{
-  octave_idx_type n = list.length ();
-
-  for (octave_idx_type i = 0; i < n; i++)
-    {
-      scanf_format_elt *elt = list(i);
-
-      std::cerr
-        << "width:      " << elt->width << "\n"
-        << "discard:    " << elt->discard << "\n"
-        << "type:       ";
-
-      if (elt->type == scanf_format_elt::literal_conversion)
-        std::cerr << "literal text\n";
-      else if (elt->type == scanf_format_elt::whitespace_conversion)
-        std::cerr << "whitespace\n";
-      else
-        std::cerr << elt->type << "\n";
-
-      std::cerr
-        << "modifier:   " << elt->modifier << "\n"
-        << "char_class: `" << undo_string_escapes (elt->char_class) << "'\n"
-        << "text:       `" << undo_string_escapes (elt->text) << "'\n\n";
-    }
-}
-
-bool
-scanf_format_list::all_character_conversions (void)
-{
-  octave_idx_type n = list.length ();
-
-  if (n > 0)
-    {
-      for (octave_idx_type i = 0; i < n; i++)
-        {
-          scanf_format_elt *elt = list(i);
-
-          switch (elt->type)
-            {
-            case 'c': case 's': case '%': case '[': case '^':
-            case scanf_format_elt::literal_conversion:
-            case scanf_format_elt::whitespace_conversion:
-              break;
-
-            default:
-              return false;
-              break;
-            }
-        }
-
-      return true;
-    }
-  else
-    return false;
-}
-
-bool
-scanf_format_list::all_numeric_conversions (void)
-{
-  octave_idx_type n = list.length ();
-
-  if (n > 0)
-    {
-      for (octave_idx_type i = 0; i < n; i++)
-        {
-          scanf_format_elt *elt = list(i);
-
-          switch (elt->type)
-            {
-            case 'd': case 'i': case 'o': case 'u': case 'x':
-            case 'e': case 'f': case 'g':
-              break;
-
-            default:
-              return false;
-              break;
-            }
-        }
-
-      return true;
-    }
-  else
-    return false;
-}
-
-// Ugh again.
-
-printf_format_list::printf_format_list (const std::string& s)
-  : nconv (0), curr_idx (0), list (dim_vector (16, 1)), buf (0)
-{
-  octave_idx_type num_elts = 0;
-
-  size_t n = s.length ();
-
-  size_t i = 0;
-
-  int args = 0;
-  std::string flags;
-  int fw = 0;
-  int prec = 0;
-  char modifier = '\0';
-  char type = '\0';
-
-  bool have_more = true;
-  bool empty_buf = true;
-
-  if (n == 0)
-    {
-      printf_format_elt *elt
-        = new printf_format_elt ("", args, fw, prec, flags, type, modifier);
-
-      list(num_elts++) = elt;
-
-      list.resize (dim_vector (num_elts, 1));
-    }
-  else
-    {
-      while (i < n)
-        {
-          have_more = true;
-
-          if (! buf)
-            {
-              buf = new std::ostringstream ();
-              empty_buf = true;
-            }
-
-          switch (s[i])
-            {
-            case '%':
-              {
-                if (empty_buf)
-                  {
-                    process_conversion (s, i, n, args, flags, fw, prec,
-                                        type, modifier, num_elts);
-
-                    have_more = (buf != 0);
-                  }
-                else
-                  add_elt_to_list (args, flags, fw, prec, type, modifier,
-                                   num_elts);
-              }
-              break;
-
-            default:
-              {
-                args = 0;
-                flags = "";
-                fw = 0;
-                prec = 0;
-                modifier = '\0';
-                type = '\0';
-                *buf << s[i++];
-                empty_buf = false;
-              }
-              break;
-            }
-
-          if (nconv < 0)
-            {
-              have_more = false;
-              break;
-            }
-        }
-
-      if (have_more)
-        add_elt_to_list (args, flags, fw, prec, type, modifier, num_elts);
-
-      list.resize (dim_vector (num_elts, 1));
-
-      delete buf;
-    }
-}
-
-printf_format_list::~printf_format_list (void)
-{
-  octave_idx_type n = list.length ();
-
-  for (octave_idx_type i = 0; i < n; i++)
-    {
-      printf_format_elt *elt = list(i);
-      delete elt;
-    }
-}
-
-void
-printf_format_list::add_elt_to_list (int args, const std::string& flags,
-                                     int fw, int prec, char type,
-                                     char modifier, octave_idx_type& num_elts)
-{
-  if (buf)
-    {
-      std::string text = buf->str ();
-
-      if (! text.empty ())
-        {
-          printf_format_elt *elt
-            = new printf_format_elt (text.c_str (), args, fw, prec, flags,
-                                     type, modifier);
-
-          if (num_elts == list.length ())
-            list.resize (dim_vector (2 * num_elts, 1));
-
-          list(num_elts++) = elt;
-        }
-
-      delete buf;
-      buf = 0;
-    }
-}
-
-void
-printf_format_list::process_conversion
-  (const std::string& s, size_t& i, size_t n, int& args, std::string& flags,
-   int& fw, int& prec, char& modifier, char& type, octave_idx_type& num_elts)
-{
-  args = 0;
-  flags = "";
-  fw = 0;
-  prec = 0;
-  modifier = '\0';
-  type = '\0';
-
-  *buf << s[i++];
-
-  bool nxt = false;
-
-  while (i < n)
-    {
-      switch (s[i])
-        {
-        case '-': case '+': case ' ': case '0': case '#':
-          flags += s[i];
-          *buf << s[i++];
-          break;
-
-        default:
-          nxt = true;
-          break;
-        }
-
-      if (nxt)
-        break;
-    }
-
-  if (i < n)
-    {
-      if (s[i] == '*')
-        {
-          fw = -1;
-          args++;
-          *buf << s[i++];
-        }
-      else
-        {
-          if (isdigit (s[i]))
-            {
-              int nn = 0;
-              std::string tmp = s.substr (i);
-              sscanf (tmp.c_str (), "%d%n", &fw, &nn);
-            }
-
-          while (i < n && isdigit (s[i]))
-            *buf << s[i++];
-        }
-    }
-
-  if (i < n && s[i] == '.')
-    {
-      *buf << s[i++];
-
-      if (i < n)
-        {
-          if (s[i] == '*')
-            {
-              prec = -1;
-              args++;
-              *buf << s[i++];
-            }
-          else
-            {
-              if (isdigit (s[i]))
-                {
-                  int nn = 0;
-                  std::string tmp = s.substr (i);
-                  sscanf (tmp.c_str (), "%d%n", &prec, &nn);
-                }
-
-              while (i < n && isdigit (s[i]))
-                *buf << s[i++];
-            }
-        }
-    }
-
-  if (i < n)
-    {
-      switch (s[i])
-        {
-        case 'h': case 'l': case 'L':
-          modifier = s[i];
-          *buf << s[i++];
-          break;
-
-        default:
-          break;
-        }
-    }
-
-  if (i < n)
-    finish_conversion (s, i, args, flags, fw, prec, modifier, type, num_elts);
-  else
-    nconv = -1;
-}
-
-void
-printf_format_list::finish_conversion
-  (const std::string& s, size_t& i, int args, const std::string& flags,
-   int fw, int prec, char modifier, char& type, octave_idx_type& num_elts)
-
-{
-  switch (s[i])
-    {
-    case 'd': case 'i': case 'o': case 'x': case 'X':
-    case 'u': case 'c':
-      if (modifier == 'L')
-        {
-          nconv = -1;
-          break;
-        }
-      goto fini;
-
-    case 'f': case 'e': case 'E': case 'g': case 'G':
-      if (modifier == 'h' || modifier == 'l')
-        {
-          nconv = -1;
-          break;
-        }
-      goto fini;
-
-    case 's': case 'p': case '%':
-      if (modifier != '\0')
-        {
-          nconv = -1;
-          break;
-        }
-      goto fini;
-
-    fini:
-
-      type = s[i];
-
-      *buf << s[i++];
-
-      if (type != '%' || args != 0)
-        nconv++;
-
-      if (type != '%')
-        args++;
-
-      add_elt_to_list (args, flags, fw, prec, type, modifier, num_elts);
-
-      break;
-
-    default:
-      nconv = -1;
-      break;
-    }
-}
-
-void
-printf_format_list::printme (void) const
-{
-  int n = list.length ();
-
-  for (int i = 0; i < n; i++)
-    {
-      printf_format_elt *elt = list(i);
-
-      std::cerr
-        << "args:     " << elt->args << "\n"
-        << "flags:    `" << elt->flags << "'\n"
-        << "width:    " << elt->fw << "\n"
-        << "prec:     " << elt->prec << "\n"
-        << "type:     `" << elt->type << "'\n"
-        << "modifier: `" << elt->modifier << "'\n"
-        << "text:     `" << undo_string_escapes (elt->text) << "'\n\n";
-    }
-}
-
-void
-octave_base_stream::error (const std::string& msg)
-{
-  fail = true;
-  errmsg = msg;
-}
-
-void
-octave_base_stream::error (const std::string& who, const std::string& msg)
-{
-  fail = true;
-  errmsg = who + ": " + msg;
-}
-
-void
-octave_base_stream::clear (void)
-{
-  fail = false;
-  errmsg = "";
-}
-
-void
-octave_base_stream::clearerr (void)
-{
-  std::istream *is = input_stream ();
-  std::ostream *os = output_stream ();
-
-  if (is)
-    is->clear ();
-
-  if (os)
-    os->clear ();
-}
-
-// Functions that are defined for all input streams (input streams
-// are those that define is).
-
-std::string
-octave_base_stream::do_gets (octave_idx_type max_len, bool& err,
-                             bool strip_newline, const std::string& who)
-{
-  std::string retval;
-
-  if ((interactive || forced_interactive) && file_number () == 0)
-    {
-      ::error ("%s: unable to read from stdin while running interactively",
-               who.c_str ());
-
-      return retval;
-    }
-
-  err = false;
-
-  std::istream *isp = input_stream ();
-
-  if (isp)
-    {
-      std::istream& is = *isp;
-
-      std::ostringstream buf;
-
-      int c = 0;
-      int char_count = 0;
-
-      if (max_len != 0)
-        {
-          while (is && (c = is.get ()) != EOF)
-            {
-              char_count++;
-
-              // Handle CRLF, CR, or LF as line ending.
-
-              if (c == '\r')
-                {
-                  if (! strip_newline)
-                    buf << static_cast<char> (c);
-
-                  c = is.get ();
-
-                  if (c != EOF)
-                    {
-                      if (c == '\n')
-                        {
-                          char_count++;
-
-                          if (! strip_newline)
-                            buf << static_cast<char> (c);
-                        }
-                      else
-                        is.putback (c);
-                    }
-
-                  break;
-                }
-              else if (c == '\n')
-                {
-                  if (! strip_newline)
-                    buf << static_cast<char> (c);
-
-                  break;
-                }
-              else
-                buf << static_cast<char> (c);
-
-              if (max_len > 0 && char_count == max_len)
-                break;
-            }
-        }
-
-      if (! is.eof () && char_count > 0)
-        {
-          // GAGME.  Matlab seems to check for EOF even if the last
-          // character in a file is a newline character.  This is NOT
-          // what the corresponding C-library functions do.
-          int disgusting_compatibility_hack = is.get ();
-          if (! is.eof ())
-            is.putback (disgusting_compatibility_hack);
-        }
-
-      if (is.good () || (is.eof () && char_count > 0))
-        retval = buf.str ();
-      else
-        {
-          err = true;
-
-          if (is.eof () && char_count == 0)
-            error (who, "at end of file");
-          else
-            error (who, "read error");
-        }
-    }
-  else
-    {
-      err = true;
-      invalid_operation (who, "reading");
-    }
-
-  return retval;
-}
-
-std::string
-octave_base_stream::getl (octave_idx_type max_len, bool& err, const std::string& who)
-{
-  return do_gets (max_len, err, true, who);
-}
-
-std::string
-octave_base_stream::gets (octave_idx_type max_len, bool& err, const std::string& who)
-{
-  return do_gets (max_len, err, false, who);
-}
-
-long
-octave_base_stream::skipl (long num, bool& err, const std::string& who)
-{
-  long cnt = -1;
-
-  if ((interactive || forced_interactive) && file_number () == 0)
-    {
-      ::error ("%s: unable to read from stdin while running interactively",
-               who.c_str ());
-
-      return count;
-    }
-
-  err = false;
-
-  std::istream *isp = input_stream ();
-
-  if (isp)
-    {
-      std::istream& is = *isp;
-
-      int c = 0, lastc = -1;
-      cnt = 0;
-
-      while (is && (c = is.get ()) != EOF)
-        {
-          // Handle CRLF, CR, or LF as line ending.
-
-          if (c == '\r' || (c == '\n' && lastc != '\r'))
-            {
-              if (++cnt == num)
-                break;
-            }
-
-          lastc = c;
-        }
-
-      // Maybe eat the following \n if \r was just met.
-      if (c == '\r' && is.peek () == '\n')
-       is.get ();
-
-      if (is.bad ())
-        {
-          err = true;
-          error (who, "read error");
-        }
-
-      if (err)
-        cnt = -1;
-    }
-  else
-    {
-      err = true;
-      invalid_operation (who, "reading");
-    }
-
-  return cnt;
-}
-
-#define OCTAVE_SCAN(is, fmt, arg) octave_scan (is, fmt, arg)
-
-template <class T>
-std::istream&
-octave_scan_1 (std::istream& is, const scanf_format_elt& fmt, T* valptr)
-{
-  T& ref = *valptr;
-
-  switch (fmt.type)
-    {
-    case 'o':
-      is >> std::oct >> ref >> std::dec;
-      break;
-
-    case 'x':
-      is >> std::hex >> ref >> std::dec;
-      break;
-
-    case 'i':
-      {
-        int c1 = EOF;
-
-        while (is && (c1 = is.get ()) != EOF && isspace (c1))
-          /* skip whitespace */;
-
-        if (c1 != EOF)
-          {
-            if (c1 == '0')
-              {
-                int c2 = is.peek ();
-
-                if (c2 == 'x' || c2 == 'X')
-                  {
-                    is.ignore ();
-                    if (std::isxdigit (is.peek ()))
-                      is >> std::hex >> ref >> std::dec;
-                    else
-                      ref = 0;
-                  }
-                else
-                  {
-                    if (c2 == '0' || c2 == '1' || c2 == '2'
-                        || c2 == '3' || c2 == '4' || c2 == '5'
-                        || c2 == '6' || c2 == '7')
-                      is >> std::oct >> ref >> std::dec;
-                    else
-                      ref = 0;
-                  }
-              }
-            else
-              {
-                is.putback (c1);
-
-                is >> ref;
-              }
-          }
-      }
-      break;
-
-    default:
-      is >> ref;
-      break;
-    }
-
-  return is;
-}
-
-template <class T>
-std::istream&
-octave_scan (std::istream& is, const scanf_format_elt& fmt, T* valptr)
-{
-  if (fmt.width)
-    {
-      // Limit input to fmt.width characters by reading into a
-      // temporary stringstream buffer.
-
-      std::string tmp;
-
-      is.width (fmt.width);
-      is >> tmp;
-
-      std::istringstream ss (tmp);
-
-      octave_scan_1 (ss, fmt, valptr);
-    }
-  else
-    octave_scan_1 (is, fmt, valptr);
-
-  return is;
-}
-
-// Note that this specialization is only used for reading characters, not
-// character strings. See BEGIN_S_CONVERSION for details.
-
-template<>
-std::istream&
-octave_scan<> (std::istream& is, const scanf_format_elt& /* fmt */,
-               char* valptr)
-{
-  return is >> valptr;
-}
-
-template std::istream&
-octave_scan (std::istream&, const scanf_format_elt&, int*);
-
-template std::istream&
-octave_scan (std::istream&, const scanf_format_elt&, long int*);
-
-template std::istream&
-octave_scan (std::istream&, const scanf_format_elt&, short int*);
-
-template std::istream&
-octave_scan (std::istream&, const scanf_format_elt&, unsigned int*);
-
-template std::istream&
-octave_scan (std::istream&, const scanf_format_elt&, unsigned long int*);
-
-template std::istream&
-octave_scan (std::istream&, const scanf_format_elt&, unsigned short int*);
-
-#if 0
-template std::istream&
-octave_scan (std::istream&, const scanf_format_elt&, float*);
-#endif
-
-template<>
-std::istream&
-octave_scan<> (std::istream& is, const scanf_format_elt& fmt, double* valptr)
-{
-  double& ref = *valptr;
-
-  switch (fmt.type)
-    {
-    case 'e':
-    case 'f':
-    case 'g':
-      {
-        int c1 = EOF;
-
-        while (is && (c1 = is.get ()) != EOF && isspace (c1))
-          /* skip whitespace */;
-
-        if (c1 != EOF)
-          {
-            is.putback (c1);
-
-            ref = octave_read_value<double> (is);
-          }
-      }
-      break;
-
-    default:
-      panic_impossible ();
-      break;
-    }
-
-  return is;
-}
-
-template <class T>
-void
-do_scanf_conv (std::istream& is, const scanf_format_elt& fmt,
-               T valptr, Matrix& mval, double *data, octave_idx_type& idx,
-               octave_idx_type& conversion_count, octave_idx_type nr, octave_idx_type max_size,
-               bool discard)
-{
-  OCTAVE_SCAN (is, fmt, valptr);
-
-  if (is)
-    {
-      if (idx == max_size && ! discard)
-        {
-          max_size *= 2;
-
-          if (nr > 0)
-            mval.resize (nr, max_size / nr, 0.0);
-          else
-            mval.resize (max_size, 1, 0.0);
-
-          data = mval.fortran_vec ();
-        }
-
-      if (! discard)
-        {
-          conversion_count++;
-          data[idx++] = *(valptr);
-        }
-    }
-}
-
-template void
-do_scanf_conv (std::istream&, const scanf_format_elt&, int*,
-               Matrix&, double*, octave_idx_type&, octave_idx_type&, octave_idx_type, octave_idx_type, bool);
-
-template void
-do_scanf_conv (std::istream&, const scanf_format_elt&, long int*,
-               Matrix&, double*, octave_idx_type&, octave_idx_type&, octave_idx_type, octave_idx_type, bool);
-
-template void
-do_scanf_conv (std::istream&, const scanf_format_elt&, short int*,
-               Matrix&, double*, octave_idx_type&, octave_idx_type&, octave_idx_type, octave_idx_type, bool);
-
-template void
-do_scanf_conv (std::istream&, const scanf_format_elt&, unsigned int*,
-               Matrix&, double*, octave_idx_type&, octave_idx_type&, octave_idx_type, octave_idx_type, bool);
-
-template void
-do_scanf_conv (std::istream&, const scanf_format_elt&, unsigned long int*,
-               Matrix&, double*, octave_idx_type&, octave_idx_type&, octave_idx_type, octave_idx_type, bool);
-
-template void
-do_scanf_conv (std::istream&, const scanf_format_elt&, unsigned short int*,
-               Matrix&, double*, octave_idx_type&, octave_idx_type&, octave_idx_type, octave_idx_type, bool);
-
-#if 0
-template void
-do_scanf_conv (std::istream&, const scanf_format_elt&, float*,
-               Matrix&, double*, octave_idx_type&, octave_idx_type&, octave_idx_type, octave_idx_type, bool);
-#endif
-
-template void
-do_scanf_conv (std::istream&, const scanf_format_elt&, double*,
-               Matrix&, double*, octave_idx_type&, octave_idx_type&, octave_idx_type, octave_idx_type, bool);
-
-#define DO_WHITESPACE_CONVERSION() \
-  do \
-    { \
-      int c = EOF; \
- \
-      while (is && (c = is.get ()) != EOF && isspace (c)) \
-        /* skip whitespace */; \
- \
-      if (c != EOF) \
-        is.putback (c); \
-    } \
-  while (0)
-
-#define DO_LITERAL_CONVERSION() \
-  do \
-    { \
-      int c = EOF; \
- \
-      int n = strlen (fmt); \
-      int i = 0; \
- \
-      while (i < n && is && (c = is.get ()) != EOF) \
-        { \
-          if (c == static_cast<unsigned char> (fmt[i])) \
-            { \
-              i++; \
-              continue; \
-            } \
-          else \
-            { \
-              is.putback (c); \
-              break; \
-            } \
-        } \
- \
-      if (i != n) \
-        is.setstate (std::ios::failbit); \
-    } \
-  while (0)
-
-#define DO_PCT_CONVERSION() \
-  do \
-    { \
-      int c = is.get (); \
- \
-      if (c != EOF) \
-        { \
-          if (c != '%') \
-            { \
-              is.putback (c); \
-              is.setstate (std::ios::failbit); \
-            } \
-        } \
-      else \
-        is.setstate (std::ios::failbit); \
-    } \
-  while (0)
-
-#define BEGIN_C_CONVERSION() \
-  is.unsetf (std::ios::skipws); \
- \
-  int width = elt->width ? elt->width : 1; \
- \
-  std::string tmp (width, '\0'); \
- \
-  int c = EOF; \
-  int n = 0; \
- \
-  while (is && n < width && (c = is.get ()) != EOF) \
-    tmp[n++] = static_cast<char> (c); \
- \
-  if (n > 0 && c == EOF) \
-    is.clear (); \
- \
-  tmp.resize (n)
-
-// For a `%s' format, skip initial whitespace and then read until the
-// next whitespace character or until WIDTH characters have been read.
-#define BEGIN_S_CONVERSION() \
-  int width = elt->width; \
- \
-  std::string tmp; \
- \
-  do \
-    { \
-      if (width) \
-        { \
-          tmp = std::string (width, '\0'); \
- \
-          int c = EOF; \
- \
-          int n = 0; \
- \
-          while (is && (c = is.get ()) != EOF) \
-            { \
-              if (! isspace (c)) \
-                { \
-                  tmp[n++] = static_cast<char> (c); \
-                  break; \
-                } \
-            } \
- \
-          while (is && n < width && (c = is.get ()) != EOF) \
-            { \
-              if (isspace (c)) \
-                { \
-                  is.putback (c); \
-                  break; \
-                } \
-              else \
-                tmp[n++] = static_cast<char> (c); \
-            } \
- \
-          if (n > 0 && c == EOF) \
-            is.clear (); \
- \
-          tmp.resize (n); \
-        } \
-      else \
-        { \
-          is >> std::ws >> tmp; \
-        } \
-    } \
-  while (0)
-
-// This format must match a nonempty sequence of characters.
-#define BEGIN_CHAR_CLASS_CONVERSION() \
-  int width = elt->width; \
- \
-  std::string tmp; \
- \
-  do \
-    { \
-      if (! width) \
-        width = INT_MAX; \
- \
-      std::ostringstream buf; \
- \
-      std::string char_class = elt->char_class; \
- \
-      int c = EOF; \
- \
-      if (elt->type == '[') \
-        { \
-          int chars_read = 0; \
-          while (is && chars_read++ < width && (c = is.get ()) != EOF \
-                 && char_class.find (c) != std::string::npos) \
-            buf << static_cast<char> (c); \
-        } \
-      else \
-        { \
-          int chars_read = 0; \
-          while (is && chars_read++ < width && (c = is.get ()) != EOF \
-                 && char_class.find (c) == std::string::npos) \
-            buf << static_cast<char> (c); \
-        } \
- \
-      if (width == INT_MAX && c != EOF) \
-        is.putback (c); \
- \
-      tmp = buf.str (); \
- \
-      if (tmp.empty ()) \
-        is.setstate (std::ios::failbit); \
-      else if (c == EOF) \
-        is.clear (); \
- \
-    } \
-  while (0)
-
-#define FINISH_CHARACTER_CONVERSION() \
-  do \
-    { \
-      width = tmp.length (); \
- \
-      if (is) \
-        { \
-          int i = 0; \
- \
-          if (! discard) \
-            { \
-              conversion_count++; \
- \
-              while (i < width) \
-                { \
-                  if (data_index == max_size) \
-                    { \
-                      max_size *= 2; \
- \
-                      if (all_char_conv) \
-                        { \
-                          if (one_elt_size_spec) \
-                            mval.resize (1, max_size, 0.0); \
-                          else if (nr > 0) \
-                            mval.resize (nr, max_size / nr, 0.0); \
-                          else \
-                            panic_impossible (); \
-                        } \
-                      else if (nr > 0) \
-                        mval.resize (nr, max_size / nr, 0.0); \
-                      else \
-                        mval.resize (max_size, 1, 0.0); \
- \
-                      data = mval.fortran_vec (); \
-                    } \
- \
-                  data[data_index++] = tmp[i++]; \
-                } \
-            } \
-        } \
-    } \
-  while (0)
-
-octave_value
-octave_base_stream::do_scanf (scanf_format_list& fmt_list,
-                              octave_idx_type nr, octave_idx_type nc, bool one_elt_size_spec,
-                              octave_idx_type& conversion_count, const std::string& who)
-{
-  octave_value retval = Matrix ();
-
-  if ((interactive || forced_interactive) && file_number () == 0)
-    {
-      ::error ("%s: unable to read from stdin while running interactively",
-               who.c_str ());
-
-      return retval;
-    }
-
-  conversion_count = 0;
-
-  octave_idx_type nconv = fmt_list.num_conversions ();
-
-  octave_idx_type data_index = 0;
-
-  if (nr == 0 || nc == 0)
-    {
-      if (one_elt_size_spec)
-        nc = 0;
-
-      return Matrix (nr, nc, 0.0);
-    }
-
-  std::istream *isp = input_stream ();
-
-  bool all_char_conv = fmt_list.all_character_conversions ();
-
-  Matrix mval;
-  double *data = 0;
-  octave_idx_type max_size = 0;
-  octave_idx_type max_conv = 0;
-
-  octave_idx_type final_nr = 0;
-  octave_idx_type final_nc = 0;
-
-  if (all_char_conv)
-    {
-      // Any of these could be resized later (if we have %s
-      // conversions, we may read more than one element for each
-      // conversion).
-
-      if (one_elt_size_spec)
-        {
-          max_size = 512;
-          mval.resize (1, max_size, 0.0);
-
-          if (nr > 0)
-            max_conv = nr;
-        }
-      else if (nr > 0)
-        {
-          if (nc > 0)
-            {
-              mval.resize (nr, nc, 0.0);
-              max_size = max_conv = nr * nc;
-            }
-          else
-            {
-              mval.resize (nr, 32, 0.0);
-              max_size = nr * 32;
-            }
-        }
-      else
-        panic_impossible ();
-    }
-  else if (nr > 0)
-    {
-      if (nc > 0)
-        {
-          // Will not resize later.
-          mval.resize (nr, nc, 0.0);
-          max_size = nr * nc;
-          max_conv = max_size;
-        }
-      else
-        {
-          // Maybe resize later.
-          mval.resize (nr, 32, 0.0);
-          max_size = nr * 32;
-        }
-    }
-  else
-    {
-      // Maybe resize later.
-      mval.resize (32, 1, 0.0);
-      max_size = 32;
-    }
-
-  data = mval.fortran_vec ();
-
-  if (isp)
-    {
-      std::istream& is = *isp;
-
-      const scanf_format_elt *elt = fmt_list.first ();
-
-      std::ios::fmtflags flags = is.flags ();
-
-      octave_idx_type trips = 0;
-
-      octave_idx_type num_fmt_elts = fmt_list.length ();
-
-      for (;;)
-        {
-          octave_quit ();
-
-          if (elt)
-            {
-              if (! (elt->type == scanf_format_elt::whitespace_conversion
-                     || elt->type == scanf_format_elt::literal_conversion
-                     || elt->type == '%')
-                  && max_conv > 0 && conversion_count == max_conv)
-                {
-                  if (all_char_conv && one_elt_size_spec)
-                    {
-                      final_nr = 1;
-                      final_nc = data_index;
-                    }
-                  else
-                    {
-                      final_nr = nr;
-                      final_nc = (data_index - 1) / nr + 1;
-                    }
-
-                  break;
-                }
-              else if (data_index == max_size)
-                {
-                  max_size *= 2;
-
-                  if (all_char_conv)
-                    {
-                      if (one_elt_size_spec)
-                        mval.resize (1, max_size, 0.0);
-                      else if (nr > 0)
-                        mval.resize (nr, max_size / nr, 0.0);
-                      else
-                        panic_impossible ();
-                    }
-                  else if (nr > 0)
-                    mval.resize (nr, max_size / nr, 0.0);
-                  else
-                    mval.resize (max_size, 1, 0.0);
-
-                  data = mval.fortran_vec ();
-                }
-
-              const char *fmt = elt->text;
-
-              bool discard = elt->discard;
-
-              switch (elt->type)
-                {
-                case scanf_format_elt::whitespace_conversion:
-                  DO_WHITESPACE_CONVERSION ();
-                  break;
-
-                case scanf_format_elt::literal_conversion:
-                  DO_LITERAL_CONVERSION ();
-                  break;
-
-                case '%':
-                  DO_PCT_CONVERSION ();
-                  break;
-
-                case 'd': case 'i':
-                  {
-                    switch (elt->modifier)
-                      {
-                      case 'h':
-                        {
-                          short int tmp;
-                          do_scanf_conv (is, *elt, &tmp, mval, data,
-                                         data_index, conversion_count,
-                                         nr, max_size, discard);
-                        }
-                        break;
-
-                      case 'l':
-                        {
-                          long int tmp;
-                          do_scanf_conv (is, *elt, &tmp, mval, data,
-                                         data_index, conversion_count,
-                                         nr, max_size, discard);
-                        }
-                        break;
-
-                      default:
-                        {
-                          int tmp;
-                          do_scanf_conv (is, *elt, &tmp, mval, data,
-                                         data_index, conversion_count,
-                                         nr, max_size, discard);
-                        }
-                        break;
-                      }
-                  }
-                  break;
-
-                case 'o': case 'u': case 'x':
-                  {
-                    switch (elt->modifier)
-                      {
-                      case 'h':
-                        {
-                          unsigned short int tmp;
-                          do_scanf_conv (is, *elt, &tmp, mval, data,
-                                         data_index, conversion_count,
-                                         nr, max_size, discard);
-                        }
-                        break;
-
-                      case 'l':
-                        {
-                          unsigned long int tmp;
-                          do_scanf_conv (is, *elt, &tmp, mval, data,
-                                         data_index, conversion_count,
-                                         nr, max_size, discard);
-                        }
-                        break;
-
-                      default:
-                        {
-                          unsigned int tmp;
-                          do_scanf_conv (is, *elt, &tmp, mval, data,
-                                         data_index, conversion_count,
-                                         nr, max_size, discard);
-                        }
-                        break;
-                      }
-                  }
-                  break;
-
-                case 'e': case 'f': case 'g':
-                  {
-                    double tmp;
-
-                    do_scanf_conv (is, *elt, &tmp, mval, data,
-                                   data_index, conversion_count,
-                                   nr, max_size, discard);
-                  }
-                  break;
-
-                case 'c':
-                  {
-                    BEGIN_C_CONVERSION ();
-
-                    FINISH_CHARACTER_CONVERSION ();
-
-                    is.setf (flags);
-                  }
-                  break;
-
-                case 's':
-                  {
-                    BEGIN_S_CONVERSION ();
-
-                    FINISH_CHARACTER_CONVERSION ();
-                  }
-                  break;
-
-                case '[': case '^':
-                  {
-                    BEGIN_CHAR_CLASS_CONVERSION ();
-
-                    FINISH_CHARACTER_CONVERSION ();
-                  }
-                  break;
-
-                case 'p':
-                  error ("%s: unsupported format specifier", who.c_str ());
-                  break;
-
-                default:
-                  error ("%s: internal format error", who.c_str ());
-                  break;
-                }
-
-              if (! ok ())
-                {
-                  break;
-                }
-              else if (! is)
-                {
-                  if (all_char_conv)
-                    {
-                      if (one_elt_size_spec)
-                        {
-                          final_nr = 1;
-                          final_nc = data_index;
-                        }
-                      else if (data_index > nr)
-                        {
-                          final_nr = nr;
-                          final_nc = (data_index - 1) / nr + 1;
-                        }
-                      else
-                        {
-                          final_nr = data_index;
-                          final_nc = 1;
-                        }
-                    }
-                  else if (nr > 0)
-                    {
-                      if (data_index > nr)
-                        {
-                          final_nr = nr;
-                          final_nc = (data_index - 1) / nr + 1;
-                        }
-                      else
-                        {
-                          final_nr = data_index;
-                          final_nc = 1;
-                        }
-                    }
-                  else
-                    {
-                      final_nr = data_index;
-                      final_nc = 1;
-                    }
-
-                  // If it looks like we have a matching failure, then
-                  // reset the failbit in the stream state.
-
-                  if (is.rdstate () & std::ios::failbit)
-                    is.clear (is.rdstate () & (~std::ios::failbit));
-
-                  // FIXME -- is this the right thing to do?
-
-                  if (interactive && name () == "stdin")
-                    {
-                      is.clear ();
-
-                      // Skip to end of line.
-
-                      bool err;
-                      do_gets (-1, err, false, who);
-                    }
-
-                  break;
-                }
-            }
-          else
-            {
-              error ("%s: internal format error", who.c_str ());
-              break;
-            }
-
-          if (nconv == 0 && ++trips == num_fmt_elts)
-            {
-              if (all_char_conv && one_elt_size_spec)
-                {
-                  final_nr = 1;
-                  final_nc = data_index;
-                }
-              else
-                {
-                  final_nr = nr;
-                  final_nc = (data_index - 1) / nr + 1;
-                }
-
-              break;
-            }
-          else
-            elt = fmt_list.next (nconv > 0);
-        }
-    }
-
-  if (ok ())
-    {
-      mval.resize (final_nr, final_nc, 0.0);
-
-      retval = mval;
-
-      if (all_char_conv)
-        retval = retval.convert_to_str (false, true);
-    }
-
-  return retval;
-}
-
-octave_value
-octave_base_stream::scanf (const std::string& fmt, const Array<double>& size,
-                           octave_idx_type& conversion_count, const std::string& who)
-{
-  octave_value retval = Matrix ();
-
-  conversion_count = 0;
-
-  std::istream *isp = input_stream ();
-
-  if (isp)
-    {
-      scanf_format_list fmt_list (fmt);
-
-      if (fmt_list.num_conversions () == -1)
-        ::error ("%s: invalid format specified", who.c_str ());
-      else
-        {
-        octave_idx_type nr = -1;
-        octave_idx_type nc = -1;
-
-        bool one_elt_size_spec;
-
-        get_size (size, nr, nc, one_elt_size_spec, who);
-
-        if (! error_state)
-          retval = do_scanf (fmt_list, nr, nc, one_elt_size_spec,
-                             conversion_count, who);
-        }
-    }
-  else
-    invalid_operation (who, "reading");
-
-  return retval;
-}
-
-bool
-octave_base_stream::do_oscanf (const scanf_format_elt *elt,
-                               octave_value& retval, const std::string& who)
-{
-  bool quit = false;
-
-  std::istream *isp = input_stream ();
-
-  if (isp)
-    {
-      std::istream& is = *isp;
-
-      std::ios::fmtflags flags = is.flags ();
-
-      if (elt)
-        {
-          const char *fmt = elt->text;
-
-          bool discard = elt->discard;
-
-          switch (elt->type)
-            {
-            case scanf_format_elt::whitespace_conversion:
-              DO_WHITESPACE_CONVERSION ();
-              break;
-
-            case scanf_format_elt::literal_conversion:
-              DO_LITERAL_CONVERSION ();
-              break;
-
-            case '%':
-              {
-                DO_PCT_CONVERSION ();
-
-                if (! is)
-                  quit = true;
-
-              }
-              break;
-
-            case 'd': case 'i':
-              {
-                int tmp;
-
-                if (OCTAVE_SCAN (is, *elt, &tmp))
-                  {
-                    if (! discard)
-                      retval = tmp;
-                  }
-                else
-                  quit = true;
-              }
-              break;
-
-            case 'o': case 'u': case 'x':
-              {
-                long int tmp;
-
-                if (OCTAVE_SCAN (is, *elt, &tmp))
-                  {
-                    if (! discard)
-                      retval = tmp;
-                  }
-                else
-                  quit = true;
-              }
-              break;
-
-            case 'e': case 'f': case 'g':
-              {
-                double tmp;
-
-                if (OCTAVE_SCAN (is, *elt, &tmp))
-                  {
-                    if (! discard)
-                      retval = tmp;
-                  }
-                else
-                  quit = true;
-              }
-              break;
-
-            case 'c':
-              {
-                BEGIN_C_CONVERSION ();
-
-                if (! discard)
-                  retval = tmp;
-
-                if (! is)
-                  quit = true;
-
-                is.setf (flags);
-              }
-              break;
-
-            case 's':
-              {
-                BEGIN_S_CONVERSION ();
-
-                if (! discard)
-                  retval = tmp;
-
-                if (! is)
-                  quit = true;
-              }
-              break;
-
-            case '[': case '^':
-              {
-                BEGIN_CHAR_CLASS_CONVERSION ();
-
-                if (! discard)
-                  retval = tmp;
-
-                if (! is)
-                  quit = true;
-              }
-              break;
-
-            case 'p':
-              error ("%s: unsupported format specifier", who.c_str ());
-              break;
-
-            default:
-              error ("%s: internal format error", who.c_str ());
-              break;
-            }
-        }
-
-      if (ok () && is.fail ())
-        {
-          error ("%s: read error", who.c_str ());
-
-          // FIXME -- is this the right thing to do?
-
-          if (interactive && name () == "stdin")
-            {
-              // Skip to end of line.
-
-              bool err;
-              do_gets (-1, err, false, who);
-            }
-        }
-    }
-
-  return quit;
-}
-
-octave_value_list
-octave_base_stream::oscanf (const std::string& fmt, const std::string& who)
-{
-  octave_value_list retval;
-
-  std::istream *isp = input_stream ();
-
-  if (isp)
-    {
-      std::istream& is = *isp;
-
-      scanf_format_list fmt_list (fmt);
-
-      octave_idx_type nconv = fmt_list.num_conversions ();
-
-      if (nconv == -1)
-        ::error ("%s: invalid format specified", who.c_str ());
-      else
-        {
-          is.clear ();
-
-          octave_idx_type len = fmt_list.length ();
-
-          retval.resize (nconv+2, Matrix ());
-
-          const scanf_format_elt *elt = fmt_list.first ();
-
-          int num_values = 0;
-
-          bool quit = false;
-
-          for (octave_idx_type i = 0; i < len; i++)
-            {
-              octave_value tmp;
-
-              quit = do_oscanf (elt, tmp, who);
-
-              if (quit)
-                break;
-              else
-                {
-                  if (tmp.is_defined ())
-                    retval(num_values++) = tmp;
-
-                  if (! ok ())
-                    break;
-
-                  elt = fmt_list.next (nconv > 0);
-                }
-            }
-
-          retval(nconv) = num_values;
-
-          int err_num;
-          retval(nconv+1) = error (false, err_num);
-
-          if (! quit)
-            {
-              // Pick up any trailing stuff.
-              if (ok () && len > nconv)
-                {
-                  octave_value tmp;
-
-                  elt = fmt_list.next ();
-
-                  do_oscanf (elt, tmp, who);
-                }
-            }
-        }
-    }
-  else
-    invalid_operation (who, "reading");
-
-  return retval;
-}
-
-// Functions that are defined for all output streams (output streams
-// are those that define os).
-
-int
-octave_base_stream::flush (void)
-{
-  int retval = -1;
-
-  std::ostream *os = output_stream ();
-
-  if (os)
-    {
-      os->flush ();
-
-      if (os->good ())
-        retval = 0;
-    }
-  else
-    invalid_operation ("fflush", "writing");
-
-  return retval;
-}
-
-class
-printf_value_cache
-{
-public:
-
-  enum state { ok, conversion_error };
-
-  printf_value_cache (const octave_value_list& args, const std::string& who)
-    : values (args), val_idx (0), elt_idx (0),
-      n_vals (values.length ()), n_elts (0), data (0),
-      curr_state (ok)
-  {
-    for (octave_idx_type i = 0; i < values.length (); i++)
-      {
-        octave_value val = values(i);
-
-        if (val.is_map () || val.is_cell () || val.is_object ())
-          {
-            gripe_wrong_type_arg (who, val);
-            break;
-          }
-      }
-  }
-
-  ~printf_value_cache (void) { }
-
-  // Get the current value as a double and advance the internal pointer.
-  double double_value (void);
-
-  // Get the current value as an int and advance the internal pointer.
-  int int_value (void);
-
-  // Get the current value as a string and advance the internal pointer.
-  std::string string_value (void);
-
-  operator bool () const { return (curr_state == ok); }
-
-  bool exhausted (void) { return (val_idx >= n_vals); }
-
-private:
-
-  const octave_value_list values;
-  int val_idx;
-  int elt_idx;
-  int n_vals;
-  int n_elts;
-  const double *data;
-  NDArray curr_val;
-  state curr_state;
-
-  // Must create value cache with values!
-
-  printf_value_cache (void);
-
-  // No copying!
-
-  printf_value_cache (const printf_value_cache&);
-
-  printf_value_cache& operator = (const printf_value_cache&);
-};
-
-double
-printf_value_cache::double_value (void)
-{
-  double retval = 0.0;
-
-  if (exhausted ())
-    curr_state = conversion_error;
-
-  while (! exhausted ())
-    {
-      if (! data)
-        {
-          octave_value tmp_val = values (val_idx);
-
-          // Force string conversion here for compatibility.
-
-          curr_val = tmp_val.array_value (true);
-
-          if (! error_state)
-            {
-              elt_idx = 0;
-              n_elts = curr_val.length ();
-              data = curr_val.data ();
-            }
-          else
-            {
-              curr_state = conversion_error;
-              break;
-            }
-        }
-
-      if (elt_idx < n_elts)
-        {
-          retval = data[elt_idx++];
-
-          if (elt_idx >= n_elts)
-            {
-              elt_idx = 0;
-              val_idx++;
-              data = 0;
-            }
-
-          break;
-        }
-      else
-        {
-          val_idx++;
-          data = 0;
-
-          if (n_elts == 0 && exhausted ())
-            curr_state = conversion_error;
-
-          continue;
-        }
-    }
-
-  return retval;
-}
-
-int
-printf_value_cache::int_value (void)
-{
-  int retval = 0;
-
-  double dval = double_value ();
-
-  if (! error_state)
-    {
-      if (D_NINT (dval) == dval)
-        retval = NINT (dval);
-      else
-        curr_state = conversion_error;
-    }
-
-  return retval;
-}
-
-std::string
-printf_value_cache::string_value (void)
-{
-  std::string retval;
-
-  if (exhausted ())
-    curr_state = conversion_error;
-  else
-    {
-      octave_value tval = values (val_idx++);
-
-      if (tval.rows () == 1)
-        retval = tval.string_value ();
-      else
-        {
-          // In the name of Matlab compatibility.
-
-          charMatrix chm = tval.char_matrix_value ();
-
-          octave_idx_type nr = chm.rows ();
-          octave_idx_type nc = chm.columns ();
-
-          int k = 0;
-
-          retval.resize (nr * nc, '\0');
-
-          for (octave_idx_type j = 0; j < nc; j++)
-            for (octave_idx_type i = 0; i < nr; i++)
-              retval[k++] = chm(i,j);
-        }
-
-      if (error_state)
-        curr_state = conversion_error;
-    }
-
-  return retval;
-}
-
-// Ugh again and again.
-
-template <class T>
-int
-do_printf_conv (std::ostream& os, const char *fmt, int nsa, int sa_1,
-                int sa_2, T arg, const std::string& who)
-{
-  int retval = 0;
-
-  switch (nsa)
-    {
-    case 2:
-      retval = octave_format (os, fmt, sa_1, sa_2, arg);
-      break;
-
-    case 1:
-      retval = octave_format (os, fmt, sa_1, arg);
-      break;
-
-    case 0:
-      retval = octave_format (os, fmt, arg);
-      break;
-
-    default:
-      ::error ("%s: internal error handling format", who.c_str ());
-      break;
-    }
-
-  return retval;
-}
-
-template int
-do_printf_conv (std::ostream&, const char*, int, int, int, int,
-                const std::string&);
-
-template int
-do_printf_conv (std::ostream&, const char*, int, int, int, long,
-                const std::string&);
-
-template int
-do_printf_conv (std::ostream&, const char*, int, int, int, unsigned int,
-                const std::string&);
-
-template int
-do_printf_conv (std::ostream&, const char*, int, int, int, unsigned long,
-                const std::string&);
-
-template int
-do_printf_conv (std::ostream&, const char*, int, int, int, double,
-                const std::string&);
-
-template int
-do_printf_conv (std::ostream&, const char*, int, int, int, const char*,
-                const std::string&);
-
-#define DO_DOUBLE_CONV(TQUAL) \
-  do \
-    { \
-      if (val > std::numeric_limits<TQUAL long>::max () \
-          || val < std::numeric_limits<TQUAL long>::min ()) \
-        { \
-          std::string tfmt = fmt; \
- \
-          tfmt.replace (tfmt.rfind (elt->type), 1, ".f"); \
- \
-          if (elt->modifier == 'l') \
-            tfmt.replace (tfmt.rfind (elt->modifier), 1, ""); \
- \
-          retval += do_printf_conv (os, tfmt.c_str (), nsa, sa_1, sa_2, \
-                                    val, who); \
-        } \
-      else \
-        retval += do_printf_conv (os, fmt, nsa, sa_1, sa_2, \
-                                  static_cast<TQUAL long> (val), who); \
-    } \
-  while (0)
-
-int
-octave_base_stream::do_printf (printf_format_list& fmt_list,
-                               const octave_value_list& args,
-                               const std::string& who)
-{
-  int retval = 0;
-
-  octave_idx_type nconv = fmt_list.num_conversions ();
-
-  std::ostream *osp = output_stream ();
-
-  if (osp)
-    {
-      std::ostream& os = *osp;
-
-      const printf_format_elt *elt = fmt_list.first ();
-
-      printf_value_cache val_cache (args, who);
-
-      if (error_state)
-        return retval;
-
-      for (;;)
-        {
-          octave_quit ();
-
-          if (elt)
-            {
-              // NSA is the number of `star' args to convert.
-
-              int nsa = (elt->fw < 0) + (elt->prec < 0);
-
-              int sa_1 = 0;
-              int sa_2 = 0;
-
-              if (nsa > 0)
-                {
-                  sa_1 = val_cache.int_value ();
-
-                  if (! val_cache)
-                    break;
-                  else
-                    {
-                      if (nsa > 1)
-                        {
-                          sa_2 = val_cache.int_value ();
-
-                          if (! val_cache)
-                            break;
-                        }
-                    }
-                }
-
-              const char *fmt = elt->text;
-
-              if (elt->type == '%')
-                {
-                  os << "%";
-                  retval++;
-                }
-              else if (elt->args == 0 && elt->text)
-                {
-                  os << elt->text;
-                  retval += strlen (elt->text);
-                }
-              else if (elt->type == 's')
-                {
-                  std::string val = val_cache.string_value ();
-
-                  if (val_cache)
-                    retval += do_printf_conv (os, fmt, nsa, sa_1,
-                                              sa_2, val.c_str (), who);
-                  else
-                    break;
-                }
-              else
-                {
-                  double val = val_cache.double_value ();
-
-                  if (val_cache)
-                    {
-                      if (lo_ieee_isnan (val) || xisinf (val))
-                        {
-                          std::string tfmt = fmt;
-                          std::string::size_type i1, i2;
-
-                          tfmt.replace ((i1 = tfmt.rfind (elt->type)),
-                                        1, 1, 's');
-
-                          if ((i2 = tfmt.rfind ('.')) != std::string::npos && i2 < i1)
-                            {
-                              tfmt.erase (i2, i1-i2);
-                              if (elt->prec < 0)
-                                nsa--;
-                            }
-
-                          const char *tval = xisinf (val)
-                            ? (val < 0 ? "-Inf" : "Inf")
-                            : (lo_ieee_is_NA (val) ? "NA" : "NaN");
-
-                          retval += do_printf_conv (os, tfmt.c_str (),
-                                                    nsa, sa_1, sa_2,
-                                                    tval, who);
-                        }
-                      else
-                        {
-                          char type = elt->type;
-
-                          switch (type)
-                            {
-                            case 'd': case 'i': case 'c':
-                              DO_DOUBLE_CONV (OCTAVE_EMPTY_CPP_ARG);
-                              break;
-
-                            case 'o': case 'x': case 'X': case 'u':
-                              DO_DOUBLE_CONV (unsigned);
-                              break;
-
-                            case 'f': case 'e': case 'E':
-                            case 'g': case 'G':
-                              retval
-                                += do_printf_conv (os, fmt, nsa, sa_1, sa_2,
-                                                   val, who);
-                              break;
-
-                            default:
-                              error ("%s: invalid format specifier",
-                                     who.c_str ());
-                              return -1;
-                              break;
-                            }
-                        }
-                    }
-                  else
-                    break;
-                }
-
-              if (! os)
-                {
-                  error ("%s: write error", who.c_str ());
-                  break;
-                }
-            }
-          else
-            {
-              ::error ("%s: internal error handling format", who.c_str ());
-              retval = -1;
-              break;
-            }
-
-          elt = fmt_list.next (nconv > 0 && ! val_cache.exhausted ());
-
-          if (! elt || (val_cache.exhausted () && elt->args > 0))
-            break;
-        }
-    }
-  else
-    invalid_operation (who, "writing");
-
-  return retval;
-}
-
-int
-octave_base_stream::printf (const std::string& fmt,
-                            const octave_value_list& args,
-                            const std::string& who)
-{
-  int retval = 0;
-
-  printf_format_list fmt_list (fmt);
-
-  if (fmt_list.num_conversions () == -1)
-    ::error ("%s: invalid format specified", who.c_str ());
-  else
-    retval = do_printf (fmt_list, args, who);
-
-  return retval;
-}
-
-int
-octave_base_stream::puts (const std::string& s, const std::string& who)
-{
-  int retval = -1;
-
-  std::ostream *osp = output_stream ();
-
-  if (osp)
-    {
-      std::ostream& os = *osp;
-
-      os << s;
-
-      if (os)
-        {
-          // FIXME -- why does this seem to be necessary?
-          // Without it, output from a loop like
-          //
-          //   for i = 1:100, fputs (stdout, "foo\n"); endfor
-          //
-          // doesn't seem to go to the pager immediately.
-
-          os.flush ();
-
-          if (os)
-            retval = 0;
-          else
-            error ("%s: write error", who.c_str ());
-        }
-      else
-        error ("%s: write error", who.c_str ());
-    }
-  else
-    invalid_operation (who, "writing");
-
-  return retval;
-}
-
-// Return current error message for this stream.
-
-std::string
-octave_base_stream::error (bool clear_err, int& err_num)
-{
-  err_num = fail ? -1 : 0;
-
-  std::string tmp = errmsg;
-
-  if (clear_err)
-    clear ();
-
-  return tmp;
-}
-
-void
-octave_base_stream::invalid_operation (const std::string& who, const char *rw)
-{
-  // Note that this is not ::error () !
-
-  error (who, std::string ("stream not open for ") + rw);
-}
-
-octave_stream::octave_stream (octave_base_stream *bs)
-  : rep (bs)
-{
-  if (rep)
-    rep->count = 1;
-}
-
-octave_stream::~octave_stream (void)
-{
-  if (rep && --rep->count == 0)
-    delete rep;
-}
-
-octave_stream::octave_stream (const octave_stream& s)
-  : rep (s.rep)
-{
-  if (rep)
-    rep->count++;
-}
-
-octave_stream&
-octave_stream::operator = (const octave_stream& s)
-{
-  if (rep != s.rep)
-    {
-      if (rep && --rep->count == 0)
-        delete rep;
-
-      rep = s.rep;
-
-      if (rep)
-        rep->count++;
-    }
-
-  return *this;
-}
-
-int
-octave_stream::flush (void)
-{
-  int retval = -1;
-
-  if (stream_ok ())
-    retval = rep->flush ();
-
-  return retval;
-}
-
-std::string
-octave_stream::getl (octave_idx_type max_len, bool& err, const std::string& who)
-{
-  std::string retval;
-
-  if (stream_ok ())
-    retval = rep->getl (max_len, err, who);
-
-  return retval;
-}
-
-std::string
-octave_stream::getl (const octave_value& tc_max_len, bool& err,
-                     const std::string& who)
-{
-  std::string retval;
-
-  err = false;
-
-  int conv_err = 0;
-
-  int max_len = -1;
-
-  if (tc_max_len.is_defined ())
-    {
-      max_len = convert_to_valid_int (tc_max_len, conv_err);
-
-      if (conv_err || max_len < 0)
-        {
-          err = true;
-          ::error ("%s: invalid maximum length specified", who.c_str ());
-        }
-    }
-
-  if (! error_state)
-    retval = getl (max_len, err, who);
-
-  return retval;
-}
-
-std::string
-octave_stream::gets (octave_idx_type max_len, bool& err, const std::string& who)
-{
-  std::string retval;
-
-  if (stream_ok ())
-    retval = rep->gets (max_len, err, who);
-
-  return retval;
-}
-
-std::string
-octave_stream::gets (const octave_value& tc_max_len, bool& err,
-                     const std::string& who)
-{
-  std::string retval;
-
-  err = false;
-
-  int conv_err = 0;
-
-  int max_len = -1;
-
-  if (tc_max_len.is_defined ())
-    {
-      max_len = convert_to_valid_int (tc_max_len, conv_err);
-
-      if (conv_err || max_len < 0)
-        {
-          err = true;
-          ::error ("%s: invalid maximum length specified", who.c_str ());
-        }
-    }
-
-  if (! error_state)
-    retval = gets (max_len, err, who);
-
-  return retval;
-}
-
-long
-octave_stream::skipl (long count, bool& err, const std::string& who)
-{
-  long retval = -1;
-
-  if (stream_ok ())
-    retval = rep->skipl (count, err, who);
-
-  return retval;
-}
-
-long
-octave_stream::skipl (const octave_value& tc_count, bool& err, const std::string& who)
-{
-  long retval = -1;
-
-  err = false;
-
-  int conv_err = 0;
-
-  int count = 1;
-
-  if (tc_count.is_defined ())
-    {
-      if (tc_count.is_scalar_type () && xisinf (tc_count.scalar_value ()))
-        count = -1;
-      else
-        {
-          count = convert_to_valid_int (tc_count, conv_err);
-
-          if (conv_err || count < 0)
-            {
-              err = true;
-              ::error ("%s: invalid number of lines specified", who.c_str ());
-            }
-        }
-    }
-
-  if (! error_state)
-    retval = skipl (count, err, who);
-
-  return retval;
-}
-
-int
-octave_stream::seek (long offset, int origin)
-{
-  int status = -1;
-
-  if (stream_ok ())
-    {
-      clearerr ();
-
-      // Find current position so we can return to it if needed.
-
-      long orig_pos = rep->tell ();
-
-      // Move to end of file.  If successful, find the offset of the end.
-
-      status = rep->seek (0, SEEK_END);
-
-      if (status == 0)
-        {
-          long eof_pos = rep->tell ();
-
-          if (origin == SEEK_CUR)
-            {
-              // Move back to original position, otherwise we will be
-              // seeking from the end of file which is probably not the
-              // original location.
-
-              rep->seek (orig_pos, SEEK_SET);
-            }
-
-          // Attempt to move to desired position; may be outside bounds
-          // of existing file.
-
-          status = rep->seek (offset, origin);
-
-          if (status == 0)
-            {
-              // Where are we after moving to desired position?
-
-              long desired_pos = rep->tell ();
-
-              // I don't think save_pos can be less than zero, but we'll
-              // check anyway...
-
-              if (desired_pos > eof_pos || desired_pos < 0)
-                {
-                  // Seek outside bounds of file.  Failure should leave
-                  // position unchanged.
-
-                  rep->seek (orig_pos, SEEK_SET);
-
-                  status = -1;
-                }
-            }
-          else
-            {
-              // Seeking to the desired position failed.  Move back to
-              // original position and return failure status.
-
-              rep->seek (orig_pos, SEEK_SET);
-
-              status = -1;
-            }
-        }
-    }
-
-  return status;
-}
-
-int
-octave_stream::seek (const octave_value& tc_offset,
-                     const octave_value& tc_origin)
-{
-  int retval = -1;
-
-  long xoffset = tc_offset.long_value (true);
-
-  if (! error_state)
-    {
-      int conv_err = 0;
-
-      int origin = SEEK_SET;
-
-      if (tc_origin.is_string ())
-        {
-          std::string xorigin = tc_origin.string_value ();
-
-          if (xorigin == "bof")
-            origin = SEEK_SET;
-          else if (xorigin == "cof")
-            origin = SEEK_CUR;
-          else if (xorigin == "eof")
-            origin = SEEK_END;
-          else
-            conv_err = -1;
-        }
-      else
-        {
-          int xorigin = convert_to_valid_int (tc_origin, conv_err);
-
-          if (! conv_err)
-            {
-              if (xorigin == -1)
-                origin = SEEK_SET;
-              else if (xorigin == 0)
-                origin = SEEK_CUR;
-              else if (xorigin == 1)
-                origin = SEEK_END;
-              else
-                conv_err = -1;
-            }
-        }
-
-      if (! conv_err)
-        {
-          retval = seek (xoffset, origin);
-
-          if (retval != 0)
-            error ("fseek: failed to seek to requested position");
-        }
-      else
-        error ("fseek: invalid value for origin");
-    }
-  else
-    error ("fseek: invalid value for offset");
-
-  return retval;
-}
-
-long
-octave_stream::tell (void)
-{
-  long retval = -1;
-
-  if (stream_ok ())
-    retval = rep->tell ();
-
-  return retval;
-}
-
-int
-octave_stream::rewind (void)
-{
-  return seek (0, SEEK_SET);
-}
-
-bool
-octave_stream::is_open (void) const
-{
-  bool retval = false;
-
-  if (stream_ok ())
-    retval = rep->is_open ();
-
-  return retval;
-}
-
-void
-octave_stream::close (void)
-{
-  if (stream_ok ())
-    rep->close ();
-}
-
-template <class RET_T, class READ_T>
-octave_value
-do_read (octave_stream& strm, octave_idx_type nr, octave_idx_type nc, octave_idx_type block_size,
-         octave_idx_type skip, bool do_float_fmt_conv, bool do_NA_conv,
-         oct_mach_info::float_format from_flt_fmt, octave_idx_type& count)
-{
-  octave_value retval;
-
-  RET_T nda;
-
-  count = 0;
-
-  typedef typename RET_T::element_type ELMT;
-  ELMT elt_zero = ELMT ();
-
-  ELMT *dat = 0;
-
-  octave_idx_type max_size = 0;
-
-  octave_idx_type final_nr = 0;
-  octave_idx_type final_nc = 1;
-
-  if (nr > 0)
-    {
-      if (nc > 0)
-        {
-          nda.resize (dim_vector (nr, nc), elt_zero);
-          dat = nda.fortran_vec ();
-          max_size = nr * nc;
-        }
-      else
-        {
-          nda.resize (dim_vector (nr, 32), elt_zero);
-          dat = nda.fortran_vec ();
-          max_size = nr * 32;
-        }
-    }
-  else
-    {
-      nda.resize (dim_vector (32, 1), elt_zero);
-      dat = nda.fortran_vec ();
-      max_size = 32;
-    }
-
-  // FIXME -- byte order for Cray?
-
-  bool swap = false;
-
-  if (oct_mach_info::words_big_endian ())
-    swap = (from_flt_fmt == oct_mach_info::flt_fmt_ieee_little_endian
-            || from_flt_fmt == oct_mach_info::flt_fmt_vax_g
-            || from_flt_fmt == oct_mach_info::flt_fmt_vax_g);
-  else
-    swap = (from_flt_fmt == oct_mach_info::flt_fmt_ieee_big_endian);
-
-  union
-  {
-    char buf[sizeof (typename strip_template_param<octave_int, READ_T>::type)];
-    typename strip_template_param<octave_int, READ_T>::type val;
-  } u;
-
-  std::istream *isp = strm.input_stream ();
-
-  if (isp)
-    {
-      std::istream& is = *isp;
-
-      octave_idx_type elts_read = 0;
-
-      for (;;)
-        {
-          // FIXME -- maybe there should be a special case for
-          // skip == 0.
-
-          if (is)
-            {
-              if (nr > 0 && nc > 0 && count == max_size)
-                {
-                  final_nr = nr;
-                  final_nc = nc;
-
-                  break;
-                }
-
-              is.read (u.buf, sizeof (typename strip_template_param<octave_int, READ_T>::type));
-
-              // We only swap bytes for integer types.  For float
-              // types, the format conversion will also handle byte
-              // swapping.
-
-              if (swap)
-                swap_bytes<sizeof (typename strip_template_param<octave_int, READ_T>::type)> (u.buf);
-              else if (do_float_fmt_conv)
-                do_float_format_conversion
-                  (u.buf,
-                   sizeof (typename strip_template_param<octave_int, READ_T>::type),
-                   1, from_flt_fmt, oct_mach_info::float_format ());
-
-              typename RET_T::element_type tmp
-                = static_cast <typename RET_T::element_type> (u.val);
-
-              if (is)
-                {
-                  if (count == max_size)
-                    {
-                      max_size *= 2;
-
-                      if (nr > 0)
-                        nda.resize (dim_vector (nr, max_size / nr),
-                                    elt_zero);
-                      else
-                        nda.resize (dim_vector (max_size, 1), elt_zero);
-
-                      dat = nda.fortran_vec ();
-                    }
-
-                  if (do_NA_conv && __lo_ieee_is_old_NA (tmp))
-                    tmp = __lo_ieee_replace_old_NA (tmp);
-
-                  dat[count++] = tmp;
-
-                  elts_read++;
-                }
-
-              int seek_status = 0;
-
-              if (skip != 0 && elts_read == block_size)
-                {
-                  seek_status = strm.seek (skip, SEEK_CUR);
-                  elts_read = 0;
-                }
-
-              if (is.eof () || seek_status < 0)
-                {
-                  if (nr > 0)
-                    {
-                      if (count > nr)
-                        {
-                          final_nr = nr;
-                          final_nc = (count - 1) / nr + 1;
-                        }
-                      else
-                        {
-                          final_nr = count;
-                          final_nc = 1;
-                        }
-                    }
-                  else
-                    {
-                      final_nr = count;
-                      final_nc = 1;
-                    }
-
-                  break;
-                }
-            }
-          else if (is.eof ())
-            break;
-        }
-    }
-
-  nda.resize (dim_vector (final_nr, final_nc), elt_zero);
-
-  retval = nda;
-
-  return retval;
-}
-
-#define DO_READ_VAL_TEMPLATE(RET_T, READ_T) \
-  template octave_value \
-  do_read<RET_T, READ_T> (octave_stream&, octave_idx_type, octave_idx_type, octave_idx_type, octave_idx_type, bool, bool, \
-                          oct_mach_info::float_format, octave_idx_type&)
-
-// FIXME -- should we only have float if it is a different
-// size from double?
-
-#define INSTANTIATE_DO_READ(VAL_T) \
-  DO_READ_VAL_TEMPLATE (VAL_T, octave_int8); \
-  DO_READ_VAL_TEMPLATE (VAL_T, octave_uint8); \
-  DO_READ_VAL_TEMPLATE (VAL_T, octave_int16); \
-  DO_READ_VAL_TEMPLATE (VAL_T, octave_uint16); \
-  DO_READ_VAL_TEMPLATE (VAL_T, octave_int32); \
-  DO_READ_VAL_TEMPLATE (VAL_T, octave_uint32); \
-  DO_READ_VAL_TEMPLATE (VAL_T, octave_int64); \
-  DO_READ_VAL_TEMPLATE (VAL_T, octave_uint64); \
-  DO_READ_VAL_TEMPLATE (VAL_T, float); \
-  DO_READ_VAL_TEMPLATE (VAL_T, double); \
-  DO_READ_VAL_TEMPLATE (VAL_T, char); \
-  DO_READ_VAL_TEMPLATE (VAL_T, signed char); \
-  DO_READ_VAL_TEMPLATE (VAL_T, unsigned char)
-
-INSTANTIATE_DO_READ (int8NDArray);
-INSTANTIATE_DO_READ (uint8NDArray);
-INSTANTIATE_DO_READ (int16NDArray);
-INSTANTIATE_DO_READ (uint16NDArray);
-INSTANTIATE_DO_READ (int32NDArray);
-INSTANTIATE_DO_READ (uint32NDArray);
-INSTANTIATE_DO_READ (int64NDArray);
-INSTANTIATE_DO_READ (uint64NDArray);
-INSTANTIATE_DO_READ (FloatNDArray);
-INSTANTIATE_DO_READ (NDArray);
-INSTANTIATE_DO_READ (charNDArray);
-INSTANTIATE_DO_READ (boolNDArray);
-
-typedef octave_value (*read_fptr) (octave_stream&, octave_idx_type, octave_idx_type, octave_idx_type, octave_idx_type, bool, bool,
-                                   oct_mach_info::float_format ffmt, octave_idx_type&);
-
-#define FILL_TABLE_ROW(R, VAL_T) \
-  read_fptr_table[R][oct_data_conv::dt_int8] = do_read<VAL_T, octave_int8>; \
-  read_fptr_table[R][oct_data_conv::dt_uint8] = do_read<VAL_T, octave_uint8>; \
-  read_fptr_table[R][oct_data_conv::dt_int16] = do_read<VAL_T, octave_int16>; \
-  read_fptr_table[R][oct_data_conv::dt_uint16] = do_read<VAL_T, octave_uint16>; \
-  read_fptr_table[R][oct_data_conv::dt_int32] = do_read<VAL_T, octave_int32>; \
-  read_fptr_table[R][oct_data_conv::dt_uint32] = do_read<VAL_T, octave_uint32>; \
-  read_fptr_table[R][oct_data_conv::dt_int64] = do_read<VAL_T, octave_int64>; \
-  read_fptr_table[R][oct_data_conv::dt_uint64] = do_read<VAL_T, octave_uint64>; \
-  read_fptr_table[R][oct_data_conv::dt_single] = do_read<VAL_T, float>; \
-  read_fptr_table[R][oct_data_conv::dt_double] = do_read<VAL_T, double>; \
-  read_fptr_table[R][oct_data_conv::dt_char] = do_read<VAL_T, char>; \
-  read_fptr_table[R][oct_data_conv::dt_schar] = do_read<VAL_T, signed char>; \
-  read_fptr_table[R][oct_data_conv::dt_uchar] = do_read<VAL_T, unsigned char>; \
-  read_fptr_table[R][oct_data_conv::dt_logical] = do_read<VAL_T, unsigned char>
-
-octave_value
-octave_stream::read (const Array<double>& size, octave_idx_type block_size,
-                     oct_data_conv::data_type input_type,
-                     oct_data_conv::data_type output_type,
-                     octave_idx_type skip, oct_mach_info::float_format ffmt,
-                     octave_idx_type& char_count)
-{
-  static bool initialized = false;
-
-  // Table function pointers for return types x read types.
-
-  static read_fptr read_fptr_table[oct_data_conv::dt_unknown][14];
-
-  if (! initialized)
-    {
-      for (int i = 0; i < oct_data_conv::dt_unknown; i++)
-        for (int j = 0; j < 14; j++)
-          read_fptr_table[i][j] = 0;
-
-      FILL_TABLE_ROW (oct_data_conv::dt_int8, int8NDArray);
-      FILL_TABLE_ROW (oct_data_conv::dt_uint8, uint8NDArray);
-      FILL_TABLE_ROW (oct_data_conv::dt_int16, int16NDArray);
-      FILL_TABLE_ROW (oct_data_conv::dt_uint16, uint16NDArray);
-      FILL_TABLE_ROW (oct_data_conv::dt_int32, int32NDArray);
-      FILL_TABLE_ROW (oct_data_conv::dt_uint32, uint32NDArray);
-      FILL_TABLE_ROW (oct_data_conv::dt_int64, int64NDArray);
-      FILL_TABLE_ROW (oct_data_conv::dt_uint64, uint64NDArray);
-      FILL_TABLE_ROW (oct_data_conv::dt_single, FloatNDArray);
-      FILL_TABLE_ROW (oct_data_conv::dt_double, NDArray);
-      FILL_TABLE_ROW (oct_data_conv::dt_char, charNDArray);
-      FILL_TABLE_ROW (oct_data_conv::dt_schar, charNDArray);
-      FILL_TABLE_ROW (oct_data_conv::dt_uchar, charNDArray);
-      FILL_TABLE_ROW (oct_data_conv::dt_logical, boolNDArray);
-
-      initialized = true;
-    }
-
-  octave_value retval;
-
-  if (stream_ok ())
-    {
-      // FIXME -- we may eventually want to make this extensible.
-
-      // FIXME -- we need a better way to ensure that this
-      // numbering stays consistent with the order of the elements in the
-      // data_type enum in the oct_data_conv class.
-
-      char_count = 0;
-
-      octave_idx_type nr = -1;
-      octave_idx_type nc = -1;
-
-      bool ignore;
-
-      get_size (size, nr, nc, ignore, "fread");
-
-      if (! error_state)
-        {
-          if (nr == 0 || nc == 0)
-            retval = Matrix (nr, nc);
-          else
-            {
-              if (ffmt == oct_mach_info::flt_fmt_unknown)
-                ffmt = float_format ();
-
-              read_fptr fcn = read_fptr_table[output_type][input_type];
-
-              bool do_float_fmt_conv = ((input_type == oct_data_conv::dt_double
-                                         || input_type == oct_data_conv::dt_single)
-                                        && ffmt != float_format ());
-
-              bool do_NA_conv = (output_type == oct_data_conv::dt_double);
-
-              if (fcn)
-                {
-                  retval = (*fcn) (*this, nr, nc, block_size, skip,
-                                   do_float_fmt_conv, do_NA_conv,
-                                   ffmt, char_count);
-
-                  // FIXME -- kluge!
-
-                  if (! error_state
-                      && (output_type == oct_data_conv::dt_char
-                          || output_type == oct_data_conv::dt_schar
-                          || output_type == oct_data_conv::dt_uchar))
-                    retval = retval.char_matrix_value ();
-                }
-              else
-                error ("fread: unable to read and convert requested types");
-            }
-        }
-      else
-        invalid_operation ("fread", "reading");
-    }
-
-  return retval;
-}
-
-octave_idx_type
-octave_stream::write (const octave_value& data, octave_idx_type block_size,
-                      oct_data_conv::data_type output_type, octave_idx_type skip,
-                      oct_mach_info::float_format flt_fmt)
-{
-  octave_idx_type retval = -1;
-
-  if (stream_ok ())
-    {
-      if (! error_state)
-        {
-          if (flt_fmt == oct_mach_info::flt_fmt_unknown)
-            flt_fmt = float_format ();
-
-          octave_idx_type status = data.write (*this, block_size, output_type,
-                                   skip, flt_fmt);
-
-          if (status < 0)
-            error ("fwrite: write error");
-          else
-            retval = status;
-        }
-      else
-        invalid_operation ("fwrite", "writing");
-    }
-
-  return retval;
-}
-
-template <class T>
-void
-write_int (std::ostream& os, bool swap, const T& val)
-{
-  typename T::val_type tmp = val.value ();
-
-  if (swap)
-    swap_bytes<sizeof (typename T::val_type)> (&tmp);
-
-  os.write (reinterpret_cast<const char *> (&tmp),
-            sizeof (typename T::val_type));
-}
-
-template void write_int (std::ostream&, bool, const octave_int8&);
-template void write_int (std::ostream&, bool, const octave_uint8&);
-template void write_int (std::ostream&, bool, const octave_int16&);
-template void write_int (std::ostream&, bool, const octave_uint16&);
-template void write_int (std::ostream&, bool, const octave_int32&);
-template void write_int (std::ostream&, bool, const octave_uint32&);
-template void write_int (std::ostream&, bool, const octave_int64&);
-template void write_int (std::ostream&, bool, const octave_uint64&);
-
-template <class T>
-static inline bool
-do_write (std::ostream& os, const T& val, oct_data_conv::data_type output_type,
-          oct_mach_info::float_format flt_fmt, bool swap,
-          bool do_float_conversion)
-{
-  bool retval = true;
-
-  // For compatibility, Octave converts to the output type, then
-  // writes.  This means that truncation happens on the conversion.
-  // For example, the following program prints 0:
-  //
-  //   x = int8 (-1)
-  //   f = fopen ("foo.dat", "w");
-  //   fwrite (f, x, "unsigned char");
-  //   fclose (f);
-  //   f = fopen ("foo.dat", "r");
-  //   y = fread (f, 1, "unsigned char");
-  //   printf ("%d\n", y);
-
-  switch (output_type)
-    {
-    case oct_data_conv::dt_char:
-    case oct_data_conv::dt_schar:
-    case oct_data_conv::dt_int8:
-      write_int (os, swap, octave_int8 (val));
-      break;
-
-    case oct_data_conv::dt_uchar:
-    case oct_data_conv::dt_uint8:
-      write_int (os, swap, octave_uint8 (val));
-      break;
-
-    case oct_data_conv::dt_int16:
-      write_int (os, swap, octave_int16 (val));
-      break;
-
-    case oct_data_conv::dt_uint16:
-      write_int (os, swap, octave_uint16 (val));
-      break;
-
-    case oct_data_conv::dt_int32:
-      write_int (os, swap, octave_int32 (val));
-      break;
-
-    case oct_data_conv::dt_uint32:
-      write_int (os, swap, octave_uint32 (val));
-      break;
-
-    case oct_data_conv::dt_int64:
-      write_int (os, swap, octave_int64 (val));
-      break;
-
-    case oct_data_conv::dt_uint64:
-      write_int (os, swap, octave_uint64 (val));
-      break;
-
-    case oct_data_conv::dt_single:
-      {
-        float f = static_cast<float> (val);
-
-        if (do_float_conversion)
-          do_float_format_conversion (&f, 1, flt_fmt);
-
-        os.write (reinterpret_cast<const char *> (&f), sizeof (float));
-      }
-      break;
-
-    case oct_data_conv::dt_double:
-      {
-        double d = static_cast<double> (val);
-        if (do_float_conversion)
-          do_double_format_conversion (&d, 1, flt_fmt);
-
-        os.write (reinterpret_cast<const char *> (&d), sizeof (double));
-      }
-      break;
-
-    default:
-      retval = false;
-      (*current_liboctave_error_handler)
-        ("write: invalid type specification");
-      break;
-    }
-
-  return retval;
-}
-
-template bool
-do_write (std::ostream&, const octave_int8&, oct_data_conv::data_type,
-          oct_mach_info::float_format, bool, bool);
-
-template bool
-do_write (std::ostream&, const octave_uint8&, oct_data_conv::data_type,
-          oct_mach_info::float_format, bool, bool);
-
-template bool
-do_write (std::ostream&, const octave_int16&, oct_data_conv::data_type,
-          oct_mach_info::float_format, bool, bool);
-
-template bool
-do_write (std::ostream&, const octave_uint16&, oct_data_conv::data_type,
-          oct_mach_info::float_format, bool, bool);
-
-template bool
-do_write (std::ostream&, const octave_int32&, oct_data_conv::data_type,
-          oct_mach_info::float_format, bool, bool);
-
-template bool
-do_write (std::ostream&, const octave_uint32&, oct_data_conv::data_type,
-          oct_mach_info::float_format, bool, bool);
-
-template bool
-do_write (std::ostream&, const octave_int64&, oct_data_conv::data_type,
-          oct_mach_info::float_format, bool, bool);
-
-template bool
-do_write (std::ostream&, const octave_uint64&, oct_data_conv::data_type,
-          oct_mach_info::float_format, bool, bool);
-
-template <class T>
-octave_idx_type
-octave_stream::write (const Array<T>& data, octave_idx_type block_size,
-                      oct_data_conv::data_type output_type,
-                      octave_idx_type skip, oct_mach_info::float_format flt_fmt)
-{
-  octave_idx_type retval = -1;
-
-  bool status = true;
-
-  octave_idx_type count = 0;
-
-  const T *d = data.data ();
-
-  octave_idx_type n = data.length ();
-
-  oct_mach_info::float_format native_flt_fmt
-    = oct_mach_info::float_format ();
-
-  bool do_float_conversion = (flt_fmt != native_flt_fmt);
-
-  // FIXME -- byte order for Cray?
-
-  bool swap = false;
-
-  if (oct_mach_info::words_big_endian ())
-    swap = (flt_fmt == oct_mach_info::flt_fmt_ieee_little_endian
-            || flt_fmt == oct_mach_info::flt_fmt_vax_g
-            || flt_fmt == oct_mach_info::flt_fmt_vax_g);
-  else
-    swap = (flt_fmt == oct_mach_info::flt_fmt_ieee_big_endian);
-
-  for (octave_idx_type i = 0; i < n; i++)
-    {
-      std::ostream *osp = output_stream ();
-
-      if (osp)
-        {
-          std::ostream& os = *osp;
-
-          if (skip != 0 && (i % block_size) == 0)
-            {
-              // Seek to skip when inside bounds of existing file.
-              // Otherwise, write NUL to skip.
-
-              long orig_pos = tell ();
-
-              seek (0, SEEK_END);
-
-              long eof_pos = tell ();
-
-              // Is it possible for this to fail to return us to the
-              // original position?
-              seek (orig_pos, SEEK_SET);
-
-              long remaining = eof_pos - orig_pos;
-
-              if (remaining < skip)
-                {
-                  seek (0, SEEK_END);
-
-                  // FIXME -- probably should try to write larger
-                  // blocks...
-
-                  unsigned char zero = 0;
-                  for (octave_idx_type j = 0; j < skip - remaining; j++)
-                    os.write (reinterpret_cast<const char *> (&zero), 1);
-                }
-              else
-                seek (skip, SEEK_CUR);
-            }
-
-          if (os)
-            {
-              status = do_write (os, d[i], output_type, flt_fmt, swap,
-                                 do_float_conversion);
-
-              if (os && status)
-                count++;
-              else
-                break;
-            }
-          else
-            {
-              status = false;
-              break;
-            }
-        }
-      else
-        {
-          status = false;
-          break;
-        }
-    }
-
-  if (status)
-    retval = count;
-
-  return retval;
-}
-
-template octave_idx_type
-octave_stream::write (const Array<char>&, octave_idx_type,
-                      oct_data_conv::data_type,
-                      octave_idx_type, oct_mach_info::float_format);
-
-template octave_idx_type
-octave_stream::write (const Array<bool>&, octave_idx_type,
-                      oct_data_conv::data_type,
-                      octave_idx_type, oct_mach_info::float_format);
-
-template octave_idx_type
-octave_stream::write (const Array<double>&, octave_idx_type,
-                      oct_data_conv::data_type,
-                      octave_idx_type, oct_mach_info::float_format);
-
-template octave_idx_type
-octave_stream::write (const Array<float>&, octave_idx_type,
-                      oct_data_conv::data_type,
-                      octave_idx_type, oct_mach_info::float_format);
-
-template octave_idx_type
-octave_stream::write (const Array<octave_int8>&, octave_idx_type,
-                      oct_data_conv::data_type,
-                      octave_idx_type, oct_mach_info::float_format);
-
-template octave_idx_type
-octave_stream::write (const Array<octave_uint8>&, octave_idx_type,
-                      oct_data_conv::data_type,
-                      octave_idx_type, oct_mach_info::float_format);
-
-template octave_idx_type
-octave_stream::write (const Array<octave_int16>&, octave_idx_type,
-                      oct_data_conv::data_type,
-                      octave_idx_type, oct_mach_info::float_format);
-
-template octave_idx_type
-octave_stream::write (const Array<octave_uint16>&, octave_idx_type,
-                      oct_data_conv::data_type,
-                      octave_idx_type, oct_mach_info::float_format);
-
-template octave_idx_type
-octave_stream::write (const Array<octave_int32>&, octave_idx_type,
-                      oct_data_conv::data_type,
-                      octave_idx_type, oct_mach_info::float_format);
-
-template octave_idx_type
-octave_stream::write (const Array<octave_uint32>&, octave_idx_type,
-                      oct_data_conv::data_type,
-                      octave_idx_type, oct_mach_info::float_format);
-
-template octave_idx_type
-octave_stream::write (const Array<octave_int64>&, octave_idx_type,
-                      oct_data_conv::data_type,
-                      octave_idx_type, oct_mach_info::float_format);
-
-template octave_idx_type
-octave_stream::write (const Array<octave_uint64>&, octave_idx_type,
-                      oct_data_conv::data_type,
-                      octave_idx_type, oct_mach_info::float_format);
-
-octave_value
-octave_stream::scanf (const std::string& fmt, const Array<double>& size,
-                      octave_idx_type& count, const std::string& who)
-{
-  octave_value retval;
-
-  if (stream_ok ())
-    retval = rep->scanf (fmt, size, count, who);
-
-  return retval;
-}
-
-octave_value
-octave_stream::scanf (const octave_value& fmt, const Array<double>& size,
-                      octave_idx_type& count, const std::string& who)
-{
-  octave_value retval = Matrix ();
-
-  if (fmt.is_string ())
-    {
-      std::string sfmt = fmt.string_value ();
-
-      if (fmt.is_sq_string ())
-        sfmt = do_string_escapes (sfmt);
-
-      retval = scanf (sfmt, size, count, who);
-    }
-  else
-    {
-      // Note that this is not ::error () !
-
-      error (who + ": format must be a string");
-    }
-
-  return retval;
-}
-
-octave_value_list
-octave_stream::oscanf (const std::string& fmt, const std::string& who)
-{
-  octave_value_list retval;
-
-  if (stream_ok ())
-    retval = rep->oscanf (fmt, who);
-
-  return retval;
-}
-
-octave_value_list
-octave_stream::oscanf (const octave_value& fmt, const std::string& who)
-{
-  octave_value_list retval;
-
-  if (fmt.is_string ())
-    {
-      std::string sfmt = fmt.string_value ();
-
-      if (fmt.is_sq_string ())
-        sfmt = do_string_escapes (sfmt);
-
-      retval = oscanf (sfmt, who);
-    }
-  else
-    {
-      // Note that this is not ::error () !
-
-      error (who + ": format must be a string");
-    }
-
-  return retval;
-}
-
-int
-octave_stream::printf (const std::string& fmt, const octave_value_list& args,
-                       const std::string& who)
-{
-  int retval = -1;
-
-  if (stream_ok ())
-    retval = rep->printf (fmt, args, who);
-
-  return retval;
-}
-
-int
-octave_stream::printf (const octave_value& fmt, const octave_value_list& args,
-                       const std::string& who)
-{
-  int retval = 0;
-
-  if (fmt.is_string ())
-    {
-      std::string sfmt = fmt.string_value ();
-
-      if (fmt.is_sq_string ())
-        sfmt = do_string_escapes (sfmt);
-
-      retval = printf (sfmt, args, who);
-    }
-  else
-    {
-      // Note that this is not ::error () !
-
-      error (who + ": format must be a string");
-    }
-
-  return retval;
-}
-
-int
-octave_stream::puts (const std::string& s, const std::string& who)
-{
-  int retval = -1;
-
-  if (stream_ok ())
-    retval = rep->puts (s, who);
-
-  return retval;
-}
-
-// FIXME -- maybe this should work for string arrays too.
-
-int
-octave_stream::puts (const octave_value& tc_s, const std::string& who)
-{
-  int retval = -1;
-
-  if (tc_s.is_string ())
-    {
-      std::string s = tc_s.string_value ();
-      retval = puts (s, who);
-    }
-  else
-    {
-      // Note that this is not ::error () !
-
-      error (who + ": argument must be a string");
-    }
-
-  return retval;
-}
-
-bool
-octave_stream::eof (void) const
-{
-  int retval = -1;
-
-  if (stream_ok ())
-    retval = rep->eof ();
-
-  return retval;
-}
-
-std::string
-octave_stream::error (bool clear, int& err_num)
-{
-  std::string retval = "invalid stream object";
-
-  if (stream_ok (false))
-    retval = rep->error (clear, err_num);
-
-  return retval;
-}
-
-std::string
-octave_stream::name (void) const
-{
-  std::string retval;
-
-  if (stream_ok ())
-    retval = rep->name ();
-
-  return retval;
-}
-
-int
-octave_stream::mode (void) const
-{
-  int retval = 0;
-
-  if (stream_ok ())
-    retval = rep->mode ();
-
-  return retval;
-}
-
-oct_mach_info::float_format
-octave_stream::float_format (void) const
-{
-  oct_mach_info::float_format retval = oct_mach_info::flt_fmt_unknown;
-
-  if (stream_ok ())
-    retval = rep->float_format ();
-
-  return retval;
-}
-
-std::string
-octave_stream::mode_as_string (int mode)
-{
-  std::string retval = "???";
-  std::ios::openmode in_mode = static_cast<std::ios::openmode> (mode);
-
-  if (in_mode == std::ios::in)
-    retval = "r";
-  else if (in_mode == std::ios::out
-           || in_mode == (std::ios::out | std::ios::trunc))
-    retval = "w";
-  else if (in_mode == (std::ios::out | std::ios::app))
-    retval = "a";
-  else if (in_mode == (std::ios::in | std::ios::out))
-    retval = "r+";
-  else if (in_mode == (std::ios::in | std::ios::out | std::ios::trunc))
-    retval = "w+";
-  else if (in_mode == (std::ios::in | std::ios::out | std::ios::ate))
-    retval = "a+";
-  else if (in_mode == (std::ios::in | std::ios::binary))
-    retval = "rb";
-  else if (in_mode == (std::ios::out | std::ios::binary)
-           || in_mode == (std::ios::out | std::ios::trunc | std::ios::binary))
-    retval = "wb";
-  else if (in_mode == (std::ios::out | std::ios::app | std::ios::binary))
-    retval = "ab";
-  else if (in_mode == (std::ios::in | std::ios::out | std::ios::binary))
-    retval = "r+b";
-  else if (in_mode == (std::ios::in | std::ios::out | std::ios::trunc
-                       | std::ios::binary))
-    retval = "w+b";
-  else if (in_mode == (std::ios::in | std::ios::out | std::ios::ate
-                       | std::ios::binary))
-    retval = "a+b";
-
-  return retval;
-}
-
-octave_stream_list *octave_stream_list::instance = 0;
-
-bool
-octave_stream_list::instance_ok (void)
-{
-  bool retval = true;
-
-  if (! instance)
-    {
-      instance = new octave_stream_list ();
-
-      if (instance)
-        singleton_cleanup_list::add (cleanup_instance);
-    }
-
-  if (! instance)
-    {
-      ::error ("unable to create stream list object!");
-
-      retval = false;
-    }
-
-  return retval;
-}
-
-int
-octave_stream_list::insert (octave_stream& os)
-{
-  return (instance_ok ()) ? instance->do_insert (os) : -1;
-}
-
-octave_stream
-octave_stream_list::lookup (int fid, const std::string& who)
-{
-  return (instance_ok ()) ? instance->do_lookup (fid, who) : octave_stream ();
-}
-
-octave_stream
-octave_stream_list::lookup (const octave_value& fid, const std::string& who)
-{
-  return (instance_ok ()) ? instance->do_lookup (fid, who) : octave_stream ();
-}
-
-int
-octave_stream_list::remove (int fid, const std::string& who)
-{
-  return (instance_ok ()) ? instance->do_remove (fid, who) : -1;
-}
-
-int
-octave_stream_list::remove (const octave_value& fid, const std::string& who)
-{
-  return (instance_ok ()) ? instance->do_remove (fid, who) : -1;
-}
-
-void
-octave_stream_list::clear (bool flush)
-{
-  if (instance)
-    instance->do_clear (flush);
-}
-
-string_vector
-octave_stream_list::get_info (int fid)
-{
-  return (instance_ok ()) ? instance->do_get_info (fid) : string_vector ();
-}
-
-string_vector
-octave_stream_list::get_info (const octave_value& fid)
-{
-  return (instance_ok ()) ? instance->do_get_info (fid) : string_vector ();
-}
-
-std::string
-octave_stream_list::list_open_files (void)
-{
-  return (instance_ok ()) ? instance->do_list_open_files () : std::string ();
-}
-
-octave_value
-octave_stream_list::open_file_numbers (void)
-{
-  return (instance_ok ())
-    ? instance->do_open_file_numbers () : octave_value ();
-}
-
-int
-octave_stream_list::get_file_number (const octave_value& fid)
-{
-  return (instance_ok ()) ? instance->do_get_file_number (fid) : -1;
-}
-
-int
-octave_stream_list::do_insert (octave_stream& os)
-{
-  // Insert item with key corresponding to file-descriptor.
-
-  int stream_number;
-
-  if ((stream_number = os.file_number ()) == -1)
-    return stream_number;
-
-  // Should we test for "(list.find (stream_number) != list.end ()) &&
-  // list[stream_number].is_open ()" and respond with "error
-  // ("internal error: ...")"? It should not happen except for some
-  // bug or if the user has opened a stream with an interpreted
-  // command, but closed it directly with a system call in an
-  // oct-file; then the kernel knows the fd is free, but Octave does
-  // not know. If it happens, it should not do harm here to simply
-  // overwrite this entry, although the wrong entry might have done
-  // harm before.
-
-  if (list.size () < list.max_size ())
-    list[stream_number] = os;
-  else
-    {
-      stream_number = -1;
-      error ("could not create file id");
-    }
-
-  return stream_number;
-
-}
-
-static void
-gripe_invalid_file_id (int fid, const std::string& who)
-{
-  if (who.empty ())
-    ::error ("invalid stream number = %d", fid);
-  else
-    ::error ("%s: invalid stream number = %d", who.c_str (), fid);
-}
-
-octave_stream
-octave_stream_list::do_lookup (int fid, const std::string& who) const
-{
-  octave_stream retval;
-
-  if (fid >= 0)
-    {
-      if (lookup_cache != list.end () && lookup_cache->first == fid)
-        retval = lookup_cache->second;
-      else
-        {
-          ostrl_map::const_iterator iter = list.find (fid);
-
-          if (iter != list.end ())
-            {
-              retval = iter->second;
-              lookup_cache = iter;
-            }
-          else
-            gripe_invalid_file_id (fid, who);
-        }
-    }
-  else
-    gripe_invalid_file_id (fid, who);
-
-  return retval;
-}
-
-octave_stream
-octave_stream_list::do_lookup (const octave_value& fid,
-                               const std::string& who) const
-{
-  octave_stream retval;
-
-  int i = get_file_number (fid);
-
-  if (! error_state)
-    retval = do_lookup (i, who);
-
-  return retval;
-}
-
-int
-octave_stream_list::do_remove (int fid, const std::string& who)
-{
-  int retval = -1;
-
-  // Can't remove stdin (std::cin), stdout (std::cout), or stderr
-  // (std::cerr).
-
-  if (fid > 2)
-    {
-      ostrl_map::iterator iter = list.find (fid);
-
-      if (iter != list.end ())
-        {
-          octave_stream os = iter->second;
-          list.erase (iter);
-          lookup_cache = list.end ();
-
-          // FIXME: is this check redundant?
-          if (os.is_valid ())
-            {
-              os.close ();
-              retval = 0;
-            }
-          else
-            gripe_invalid_file_id (fid, who);
-        }
-      else
-        gripe_invalid_file_id (fid, who);
-    }
-  else
-    gripe_invalid_file_id (fid, who);
-
-  return retval;
-}
-
-int
-octave_stream_list::do_remove (const octave_value& fid, const std::string& who)
-{
-  int retval = -1;
-
-  if (fid.is_string () && fid.string_value () == "all")
-    {
-      do_clear (false);
-
-      retval = 0;
-    }
-  else
-    {
-      int i = get_file_number (fid);
-
-      if (! error_state)
-        retval = do_remove (i, who);
-    }
-
-  return retval;
-}
-
-void
-octave_stream_list::do_clear (bool flush)
-{
-  if (flush)
-    {
-      // Do flush stdout and stderr.
-
-      list[0].flush ();
-      list[1].flush ();
-    }
-
-  octave_stream saved_os[3];
-  // But don't delete them or stdin.
-  for (ostrl_map::iterator iter = list.begin (); iter != list.end (); iter++)
-    {
-      int fid = iter->first;
-      octave_stream os = iter->second;
-      if (fid < 3)
-        saved_os[fid] = os;
-      else if (os.is_valid ())
-        os.close ();
-    }
-  list.clear ();
-  for (int fid = 0; fid < 3; fid++) list[fid] = saved_os[fid];
-  lookup_cache = list.end ();
-}
-
-string_vector
-octave_stream_list::do_get_info (int fid) const
-{
-  string_vector retval;
-
-  octave_stream os = do_lookup (fid);
-
-  if (os.is_valid ())
-    {
-      retval.resize (3);
-
-      retval(2) = oct_mach_info::float_format_as_string (os.float_format ());
-      retval(1) = octave_stream::mode_as_string (os.mode ());
-      retval(0) = os.name ();
-    }
-  else
-    ::error ("invalid file id = %d", fid);
-
-  return retval;
-}
-
-string_vector
-octave_stream_list::do_get_info (const octave_value& fid) const
-{
-  string_vector retval;
-
-  int conv_err = 0;
-
-  int int_fid = convert_to_valid_int (fid, conv_err);
-
-  if (! conv_err)
-    retval = do_get_info (int_fid);
-  else
-    ::error ("file id must be a file object or integer value");
-
-  return retval;
-}
-
-std::string
-octave_stream_list::do_list_open_files (void) const
-{
-  std::string retval;
-
-  std::ostringstream buf;
-
-  buf << "\n"
-      << "  number  mode  arch       name\n"
-      << "  ------  ----  ----       ----\n";
-
-  for (ostrl_map::const_iterator p = list.begin (); p != list.end (); p++)
-    {
-      octave_stream os = p->second;
-
-      buf << "  "
-          << std::setiosflags (std::ios::right)
-          << std::setw (4) << p->first << "     "
-          << std::setiosflags (std::ios::left)
-          << std::setw (3)
-          << octave_stream::mode_as_string (os.mode ())
-          << "  "
-          << std::setw (9)
-          << oct_mach_info::float_format_as_string (os.float_format ())
-          << "  "
-          << os.name () << "\n";
-    }
-
-  buf << "\n";
-
-  retval = buf.str ();
-
-  return retval;
-}
-
-octave_value
-octave_stream_list::do_open_file_numbers (void) const
-{
-  Matrix retval (1, list.size (), 0.0);
-
-  int num_open = 0;
-
-  for (ostrl_map::const_iterator p = list.begin (); p != list.end (); p++)
-    {
-      // Skip stdin, stdout, and stderr.
-
-      if (p->first > 2 && p->second)
-        retval(0,num_open++) = p->first;
-    }
-
-  retval.resize ((num_open > 0), num_open);
-
-  return retval;
-}
-
-int
-octave_stream_list::do_get_file_number (const octave_value& fid) const
-{
-  int retval = -1;
-
-  if (fid.is_string ())
-    {
-      std::string nm = fid.string_value ();
-
-      for (ostrl_map::const_iterator p = list.begin (); p != list.end (); p++)
-        {
-          // stdin (std::cin), stdout (std::cout), and stderr (std::cerr)
-          // are unnamed.
-
-          if (p->first > 2)
-            {
-              octave_stream os = p->second;
-
-              if (os && os.name () == nm)
-                {
-                  retval = p->first;
-                  break;
-                }
-            }
-        }
-    }
-  else
-    {
-      int conv_err = 0;
-
-      int int_fid = convert_to_valid_int (fid, conv_err);
-
-      if (conv_err)
-        ::error ("file id must be a file object, std::string, or integer value");
-      else
-        retval = int_fid;
-    }
-
-  return retval;
-}
--- a/src/oct-stream.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,738 +0,0 @@
-/*
-
-Copyright (C) 1996-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#if !defined (octave_octave_stream_h)
-#define octave_octave_stream_h 1
-
-class Matrix;
-class string_vector;
-class octave_value;
-class octave_value_list;
-
-#include <iosfwd>
-#include <sstream>
-#include <string>
-#include <map>
-
-#include "Array.h"
-#include "data-conv.h"
-#include "lo-utils.h"
-#include "mach-info.h"
-#include "oct-refcount.h"
-
-class
-OCTINTERP_API
-scanf_format_elt
-{
-public:
-
-  enum special_conversion
-    {
-      whitespace_conversion = 1,
-      literal_conversion = 2
-    };
-
-  scanf_format_elt (const char *txt = 0, int w = 0, bool d = false,
-                    char typ = '\0', char mod = '\0',
-                    const std::string& ch_class = std::string ())
-    : text (strsave (txt)), width (w), discard (d), type (typ),
-      modifier (mod), char_class (ch_class) { }
-
-  scanf_format_elt (const scanf_format_elt& e)
-    : text (strsave (e.text)), width (e.width), discard (e.discard),
-      type (e.type), modifier (e.modifier), char_class (e.char_class) { }
-
-  scanf_format_elt& operator = (const scanf_format_elt& e)
-    {
-      if (this != &e)
-        {
-          text = strsave (e.text);
-          width = e.width;
-          discard = e.discard;
-          type = e.type;
-          modifier = e.modifier;
-          char_class = e.char_class;
-        }
-
-      return *this;
-    }
-
-  ~scanf_format_elt (void) { delete [] text; }
-
-  // The C-style format string.
-  const char *text;
-
-  // The maximum field width.
-  int width;
-
-  // TRUE if we are not storing the result of this conversion.
-  bool discard;
-
-  // Type of conversion -- `d', `i', `o', `u', `x', `e', `f', `g',
-  // `c', `s', `p', `%', or `['.
-  char type;
-
-  // A length modifier -- `h', `l', or `L'.
-  char modifier;
-
-  // The class of characters in a `[' format.
-  std::string char_class;
-};
-
-class
-OCTINTERP_API
-scanf_format_list
-{
-public:
-
-  scanf_format_list (const std::string& fmt = std::string ());
-
-  ~scanf_format_list (void);
-
-  octave_idx_type num_conversions (void) { return nconv; }
-
-  // The length can be different than the number of conversions.
-  // For example, "x %d y %d z" has 2 conversions but the length of
-  // the list is 3 because of the characters that appear after the
-  // last conversion.
-
-  octave_idx_type length (void) { return list.length (); }
-
-  const scanf_format_elt *first (void)
-    {
-      curr_idx = 0;
-      return current ();
-    }
-
-  const scanf_format_elt *current (void) const
-    { return list.length () > 0 ? list.elem (curr_idx) : 0; }
-
-  const scanf_format_elt *next (bool cycle = true)
-    {
-      curr_idx++;
-
-      if (curr_idx >= list.length ())
-        {
-          if (cycle)
-            curr_idx = 0;
-          else
-            return 0;
-        }
-      return current ();
-    }
-
-  void printme (void) const;
-
-  bool ok (void) const { return (nconv >= 0); }
-
-  operator bool () const { return ok (); }
-
-  bool all_character_conversions (void);
-
-  bool all_numeric_conversions (void);
-
-private:
-
-  // Number of conversions specified by this format string, or -1 if
-  // invalid conversions have been found.
-  octave_idx_type nconv;
-
-  // Index to current element;
-  octave_idx_type curr_idx;
-
-  // FIXME -- maybe LIST should be a std::list object?
-  // List of format elements.
-  Array<scanf_format_elt*> list;
-
-  // Temporary buffer.
-  std::ostringstream *buf;
-
-  void add_elt_to_list (int width, bool discard, char type, char modifier,
-                        octave_idx_type& num_elts,
-                        const std::string& char_class = std::string ());
-
-  void process_conversion (const std::string& s, size_t& i, size_t n,
-                           int& width, bool& discard, char& type,
-                           char& modifier, octave_idx_type& num_elts);
-
-  int finish_conversion (const std::string& s, size_t& i, size_t n,
-                         int& width, bool discard, char& type,
-                         char modifier, octave_idx_type& num_elts);
-  // No copying!
-
-  scanf_format_list (const scanf_format_list&);
-
-  scanf_format_list& operator = (const scanf_format_list&);
-};
-
-class
-printf_format_elt
-{
-public:
-
-  printf_format_elt (const char *txt = 0, int n = 0, int w = 0,
-                     int p = 0, const std::string& f = std::string (),
-                     char typ = '\0', char mod = '\0')
-    : text (strsave (txt)), args (n), fw (w), prec (p), flags (f),
-      type (typ), modifier (mod) { }
-
-  printf_format_elt (const printf_format_elt& e)
-    : text (strsave (e.text)), args (e.args), fw (e.fw), prec (e.prec),
-      flags (e.flags), type (e.type), modifier (e.modifier) { }
-
-  printf_format_elt& operator = (const printf_format_elt& e)
-    {
-      if (this != &e)
-        {
-          text = strsave (e.text);
-          args = e.args;
-          fw = e.fw;
-          prec = e.prec;
-          flags = e.flags;
-          type = e.type;
-          modifier = e.modifier;
-        }
-
-      return *this;
-    }
-
-  ~printf_format_elt (void) { delete [] text; }
-
-  // The C-style format string.
-  const char *text;
-
-  // How many args do we expect to consume?
-  int args;
-
-  // Field width.
-  int fw;
-
-  // Precision.
-  int prec;
-
-  // Flags -- `-', `+', ` ', `0', or `#'.
-  std::string flags;
-
-  // Type of conversion -- `d', `i', `o', `x', `X', `u', `c', `s',
-  // `f', `e', `E', `g', `G', `p', or `%'
-  char type;
-
-  // A length modifier -- `h', `l', or `L'.
-  char modifier;
-};
-
-class
-OCTINTERP_API
-printf_format_list
-{
-public:
-
-  printf_format_list (const std::string& fmt = std::string ());
-
-  ~printf_format_list (void);
-
-  octave_idx_type num_conversions (void) { return nconv; }
-
-  const printf_format_elt *first (void)
-    {
-      curr_idx = 0;
-      return current ();
-    }
-
-  const printf_format_elt *current (void) const
-    { return list.length () > 0 ? list.elem (curr_idx) : 0; }
-
-  const printf_format_elt *next (bool cycle = true)
-    {
-      curr_idx++;
-
-      if (curr_idx >= list.length ())
-        {
-          if (cycle)
-            curr_idx = 0;
-          else
-            return 0;
-        }
-
-      return current ();
-    }
-
-  bool last_elt_p (void) { return (curr_idx + 1 == list.length ()); }
-
-  void printme (void) const;
-
-  bool ok (void) const { return (nconv >= 0); }
-
-  operator bool () const { return ok (); }
-
-private:
-
-  // Number of conversions specified by this format string, or -1 if
-  // invalid conversions have been found.
-  octave_idx_type nconv;
-
-  // Index to current element;
-  octave_idx_type curr_idx;
-
-  // FIXME -- maybe LIST should be a std::list object?
-  // List of format elements.
-  Array<printf_format_elt*> list;
-
-  // Temporary buffer.
-  std::ostringstream *buf;
-
-  void add_elt_to_list (int args, const std::string& flags, int fw,
-                        int prec, char type, char modifier,
-                        octave_idx_type& num_elts);
-
-  void process_conversion (const std::string& s, size_t& i, size_t n,
-                           int& args, std::string& flags, int& fw,
-                           int& prec, char& modifier, char& type,
-                           octave_idx_type& num_elts);
-
-  void finish_conversion (const std::string& s, size_t& i, int args,
-                          const std::string& flags, int fw, int prec,
-                          char modifier, char& type,
-                          octave_idx_type& num_elts);
-
-  // No copying!
-
-  printf_format_list (const printf_format_list&);
-
-  printf_format_list& operator = (const printf_format_list&);
-};
-
-// Provide an interface for Octave streams.
-
-class
-OCTINTERP_API
-octave_base_stream
-{
-friend class octave_stream;
-
-public:
-
-  octave_base_stream (std::ios::openmode arg_md = std::ios::in|std::ios::out,
-                      oct_mach_info::float_format ff
-                        = oct_mach_info::native_float_format ())
-    : count (0), md (arg_md), flt_fmt (ff), fail (false), open_state (true),
-      errmsg ()
-  { }
-
-  virtual ~octave_base_stream (void) { }
-
-  // The remaining functions are not specific to input or output only,
-  // and must be provided by the derived classes.
-
-  // Position a stream at OFFSET relative to ORIGIN.
-
-  virtual int seek (long offset, int origin) = 0;
-
-  // Return current stream position.
-
-  virtual long tell (void) = 0;
-
-  // Return TRUE if EOF has been reached on this stream.
-
-  virtual bool eof (void) const = 0;
-
-  // The name of the file.
-
-  virtual std::string name (void) const = 0;
-
-  // If the derived class provides this function and it returns a
-  // pointer to a valid istream, scanf(), read(), getl(), and gets()
-  // will automatically work for this stream.
-
-  virtual std::istream *input_stream (void) { return 0; }
-
-  // If the derived class provides this function and it returns a
-  // pointer to a valid ostream, flush(), write(), and printf() will
-  // automatically work for this stream.
-
-  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; }
-
-  virtual void do_close (void) { }
-
-  void close (void)
-    {
-      if (is_open ())
-        {
-          open_state = false;
-          do_close ();
-        }
-    }
-
-  virtual int file_number (void) const
-  {
-    // Kluge alert!
-
-    if (name () == "stdin")
-      return 0;
-    else if (name () == "stdout")
-      return 1;
-    else if (name () == "stderr")
-      return 2;
-    else
-      return -1;
-  }
-
-  bool ok (void) const { return ! fail; }
-
-  // Return current error message for this stream.
-
-  std::string error (bool clear, int& err_num);
-
-protected:
-
-  int mode (void) const { return md; }
-
-  oct_mach_info::float_format float_format (void) const { return flt_fmt; }
-
-  // Set current error state and set fail to TRUE.
-
-  void error (const std::string& msg);
-  void error (const std::string& who, const std::string& msg);
-
-  // Clear any error message and set fail to FALSE.
-
-  void clear (void);
-
-  // Clear stream state.
-
-  void clearerr (void);
-
-private:
-
-  // A reference count.
-  octave_refcount<octave_idx_type> count;
-
-  // The permission bits for the file.  Should be some combination of
-  // std::ios::open_mode bits.
-  int md;
-
-  // Data format.
-  oct_mach_info::float_format flt_fmt;
-
-  // TRUE if an error has occurred.
-  bool fail;
-
-  // TRUE if this stream is open.
-  bool open_state;
-
-  // Should contain error message if fail is TRUE.
-  std::string errmsg;
-
-  // Functions that are defined for all input streams (input streams
-  // are those that define is).
-
-  std::string do_gets (octave_idx_type max_len, bool& err, bool strip_newline,
-                       const std::string& who /* = "gets" */);
-
-  std::string getl (octave_idx_type max_len, bool& err, const std::string& who /* = "getl" */);
-  std::string gets (octave_idx_type max_len, bool& err, const std::string& who /* = "gets" */);
-  long skipl (long count, bool& err, const std::string& who /* = "skipl" */);
-
-  octave_value do_scanf (scanf_format_list& fmt_list, octave_idx_type nr, octave_idx_type nc,
-                         bool one_elt_size_spec, octave_idx_type& count,
-                         const std::string& who /* = "scanf" */);
-
-  octave_value scanf (const std::string& fmt, const Array<double>& size,
-                      octave_idx_type& count, const std::string& who /* = "scanf" */);
-
-  bool do_oscanf (const scanf_format_elt *elt, octave_value&,
-                  const std::string& who /* = "scanf" */);
-
-  octave_value_list oscanf (const std::string& fmt,
-                            const std::string& who /* = "scanf" */);
-
-  // Functions that are defined for all output streams (output streams
-  // are those that define os).
-
-  int flush (void);
-
-  int do_printf (printf_format_list& fmt_list, const octave_value_list& args,
-                 const std::string& who /* = "printf" */);
-
-  int printf (const std::string& fmt, const octave_value_list& args,
-              const std::string& who /* = "printf" */);
-
-  int puts (const std::string& s, const std::string& who /* = "puts" */);
-
-  // We can always do this in terms of seek(), so the derived class
-  // only has to provide that.
-
-  void invalid_operation (const std::string& who, const char *rw);
-
-  // No copying!
-
-  octave_base_stream (const octave_base_stream&);
-
-  octave_base_stream& operator = (const octave_base_stream&);
-};
-
-class
-OCTINTERP_API
-octave_stream
-{
-public:
-
-  octave_stream (octave_base_stream *bs = 0);
-
-  ~octave_stream (void);
-
-  octave_stream (const octave_stream&);
-
-  octave_stream& operator = (const octave_stream&);
-
-  int flush (void);
-
-  std::string getl (octave_idx_type max_len, bool& err, const std::string& who /* = "getl" */);
-  std::string getl (const octave_value& max_len, bool& err,
-                    const std::string& who /* = "getl" */);
-
-  std::string gets (octave_idx_type max_len, bool& err, const std::string& who /* = "gets" */);
-  std::string gets (const octave_value& max_len, bool& err,
-                    const std::string& who /* = "gets" */);
-
-  long skipl (long count, bool& err, const std::string& who /* = "skipl" */);
-  long skipl (const octave_value& count, bool& err, const std::string& who /* = "skipl" */);
-
-  int seek (long offset, int origin);
-  int seek (const octave_value& offset, const octave_value& origin);
-
-  long tell (void);
-
-  int rewind (void);
-
-  bool is_open (void) const;
-
-  void close (void);
-
-  octave_value read (const Array<double>& size, octave_idx_type block_size,
-                     oct_data_conv::data_type input_type,
-                     oct_data_conv::data_type output_type,
-                     octave_idx_type skip, oct_mach_info::float_format flt_fmt,
-                     octave_idx_type& count);
-
-  octave_idx_type write (const octave_value& data, octave_idx_type block_size,
-             oct_data_conv::data_type output_type,
-             octave_idx_type skip, oct_mach_info::float_format flt_fmt);
-
-  template <class T>
-  octave_idx_type write (const Array<T>&, octave_idx_type block_size,
-             oct_data_conv::data_type output_type,
-             octave_idx_type skip, oct_mach_info::float_format flt_fmt);
-
-  octave_value scanf (const std::string& fmt, const Array<double>& size,
-                      octave_idx_type& count, const std::string& who /* = "scanf" */);
-
-  octave_value scanf (const octave_value& fmt, const Array<double>& size,
-                      octave_idx_type& count, const std::string& who /* = "scanf" */);
-
-  octave_value_list oscanf (const std::string& fmt,
-                            const std::string& who /* = "scanf" */);
-
-  octave_value_list oscanf (const octave_value& fmt,
-                            const std::string& who /* = "scanf" */);
-
-  int printf (const std::string& fmt, const octave_value_list& args,
-              const std::string& who /* = "printf" */);
-
-  int printf (const octave_value& fmt, const octave_value_list& args,
-              const std::string& who /* = "printf" */);
-
-  int puts (const std::string& s, const std::string& who /* = "puts" */);
-  int puts (const octave_value& s, const std::string& who /* = "puts" */);
-
-  bool eof (void) const;
-
-  std::string error (bool clear, int& err_num);
-
-  std::string error (bool clear = false)
-    {
-      int err_num;
-      return error (clear, err_num);
-    }
-
-  // Set the error message and state.
-
-  void error (const std::string& msg)
-    {
-      if (rep)
-        rep->error (msg);
-    }
-
-  void error (const char *msg) { error (std::string (msg)); }
-
-  int file_number (void) { return rep ? rep->file_number () : -1; }
-
-  bool is_valid (void) const { return (rep != 0); }
-
-  bool ok (void) const { return rep && rep->ok (); }
-
-  operator bool () const { return ok (); }
-
-  std::string name (void) const;
-
-  int mode (void) const;
-
-  oct_mach_info::float_format float_format (void) const;
-
-  static std::string mode_as_string (int mode);
-
-  std::istream *input_stream (void)
-  {
-    return rep ? rep->input_stream () : 0;
-  }
-
-  std::ostream *output_stream (void)
-  {
-    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:
-
-  // The actual representation of this stream.
-  octave_base_stream *rep;
-
-  bool stream_ok (bool clear = true) const
-    {
-      bool retval = true;
-
-      if (rep)
-        {
-          if (clear)
-            rep->clear ();
-        }
-      else
-        retval = false;
-
-      return retval;
-    }
-
-  void invalid_operation (const std::string& who, const char *rw)
-    {
-      if (rep)
-        rep->invalid_operation (who, rw);
-    }
-};
-
-class
-OCTINTERP_API
-octave_stream_list
-{
-protected:
-
-  octave_stream_list (void) : list (), lookup_cache (list.end ()) { }
-
-public:
-
-  ~octave_stream_list (void) { }
-
-  static bool instance_ok (void);
-
-  static int insert (octave_stream& os);
-
-  static octave_stream
-  lookup (int fid, const std::string& who = std::string ());
-
-  static octave_stream
-  lookup (const octave_value& fid, const std::string& who = std::string ());
-
-  static int remove (int fid, const std::string& who = std::string ());
-  static int remove (const octave_value& fid,
-                     const std::string& who = std::string ());
-
-  static void clear (bool flush = true);
-
-  static string_vector get_info (int fid);
-  static string_vector get_info (const octave_value& fid);
-
-  static std::string list_open_files (void);
-
-  static octave_value open_file_numbers (void);
-
-  static int get_file_number (const octave_value& fid);
-
-private:
-
-  typedef std::map<int, octave_stream> ostrl_map;
-
-  ostrl_map list;
-
-  mutable ostrl_map::const_iterator lookup_cache;
-
-  static octave_stream_list *instance;
-
-  static void cleanup_instance (void) { delete instance; instance = 0; }
-
-  int do_insert (octave_stream& os);
-
-  octave_stream do_lookup (int fid, const std::string& who = std::string ()) const;
-  octave_stream do_lookup (const octave_value& fid,
-                           const std::string& who = std::string ()) const;
-
-  int do_remove (int fid, const std::string& who = std::string ());
-  int do_remove (const octave_value& fid, const std::string& who = std::string ());
-
-  void do_clear (bool flush = true);
-
-  string_vector do_get_info (int fid) const;
-  string_vector do_get_info (const octave_value& fid) const;
-
-  std::string do_list_open_files (void) const;
-
-  octave_value do_open_file_numbers (void) const;
-
-  int do_get_file_number (const octave_value& fid) const;
-};
-
-#endif
--- a/src/oct-strstrm.cc	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
-
-Copyright (C) 1996-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "oct-strstrm.h"
-
-// Position a stream at OFFSET relative to ORIGIN.
-
-int
-octave_base_strstream::seek (long, int)
-{
-  error ("fseek: invalid operation");
-  return -1;
-}
-
-// Return current stream position.
-
-long
-octave_base_strstream::tell (void)
-{
-  error ("ftell: invalid operation");
-  return -1;
-}
-
-octave_stream
-octave_istrstream::create (const char *data, std::ios::openmode arg_md,
-                           oct_mach_info::float_format flt_fmt)
-{
-  return octave_stream (new octave_istrstream (data, arg_md, flt_fmt));
-}
-
-octave_stream
-octave_istrstream::create (const std::string& data, std::ios::openmode arg_md,
-                           oct_mach_info::float_format flt_fmt)
-{
-  return octave_stream (new octave_istrstream (data, arg_md, flt_fmt));
-}
-
-octave_stream
-octave_ostrstream::create (std::ios::openmode arg_md,
-                           oct_mach_info::float_format flt_fmt)
-{
-  return octave_stream (new octave_ostrstream (arg_md, flt_fmt));
-}
--- a/src/oct-strstrm.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,176 +0,0 @@
-/*
-
-Copyright (C) 1996-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#if !defined (octave_octave_strstream_h)
-#define octave_octave_strstream_h 1
-
-#include <string>
-#include <sstream>
-
-#include "oct-stream.h"
-
-class
-octave_base_strstream : public octave_base_stream
-{
-public:
-
-  octave_base_strstream (std::ios::openmode m = std::ios::out,
-                         oct_mach_info::float_format ff
-                           = oct_mach_info::native_float_format ())
-    : octave_base_stream (m, ff) { }
-
-  // Position a stream at OFFSET relative to ORIGIN.
-
-  int seek (long, int);
-
-  // Return current stream position.
-
-  virtual long tell (void);
-
-  // The name of the file.
-
-  std::string name (void) const { return std::string (); }
-
-  virtual std::streambuf *rdbuf (void) = 0;
-
-  virtual bool bad (void) const = 0;
-
-  virtual void clear (void) = 0;
-
-protected:
-
-  ~octave_base_strstream (void) { }
-
-private:
-
-  // No copying!
-
-  octave_base_strstream (const octave_base_strstream&);
-
-  octave_base_strstream& operator = (const octave_base_strstream&);
-};
-
-class
-octave_istrstream : public octave_base_strstream
-{
-public:
-
-  octave_istrstream (const char *data,
-                     std::ios::openmode arg_md = std::ios::out,
-                     oct_mach_info::float_format ff
-                       = oct_mach_info::native_float_format ())
-    : octave_base_strstream (arg_md, ff), is (data) { }
-
-  octave_istrstream (const std::string& data,
-                     std::ios::openmode arg_md = std::ios::out,
-                     oct_mach_info::float_format ff
-                       = oct_mach_info::native_float_format ())
-    : octave_base_strstream (arg_md, ff), is (data.c_str ()) { }
-
-  static octave_stream
-  create (const char *data, std::ios::openmode arg_md = std::ios::out,
-          oct_mach_info::float_format ff
-            = oct_mach_info::native_float_format ());
-
-  static octave_stream
-  create (const std::string& data, std::ios::openmode arg_md = std::ios::out,
-          oct_mach_info::float_format ff
-            = oct_mach_info::native_float_format ());
-
-  // Return non-zero if EOF has been reached on this stream.
-
-  bool eof (void) const { return is.eof (); }
-
-  std::istream *input_stream (void) { return &is; }
-
-  std::ostream *output_stream (void) { return 0; }
-
-  long tell (void) { return is.tellg (); }
-
-  std::streambuf *rdbuf (void) { return is ? is.rdbuf () : 0; }
-
-  bool bad (void) const { return is.bad (); }
-
-  void clear (void) { is.clear (); }
-
-protected:
-
-  ~octave_istrstream (void) { }
-
-private:
-
-  std::istringstream is;
-
-  // No copying!
-
-  octave_istrstream (const octave_istrstream&);
-
-  octave_istrstream& operator = (const octave_istrstream&);
-};
-
-class
-octave_ostrstream : public octave_base_strstream
-{
-public:
-
-  octave_ostrstream (std::ios::openmode arg_md = std::ios::out,
-                     oct_mach_info::float_format ff
-                       = oct_mach_info::native_float_format ())
-    : octave_base_strstream (arg_md, ff), os () { }
-
-  static octave_stream
-  create (std::ios::openmode arg_md = std::ios::out,
-          oct_mach_info::float_format ff
-            = oct_mach_info::native_float_format ());
-
-  // Return non-zero if EOF has been reached on this stream.
-
-  bool eof (void) const { return os.eof (); }
-
-  std::istream *input_stream (void) { return 0; }
-
-  std::ostream *output_stream (void) { return &os; }
-
-  std::string str (void) { return os.str (); }
-
-  std::streambuf *rdbuf (void) { return os ? os.rdbuf () : 0; }
-
-  bool bad (void) const { return os.bad (); }
-
-  void clear (void) { os.clear (); }
-
-protected:
-
-  ~octave_ostrstream (void) { }
-
-private:
-
-  std::ostringstream os;
-
-  // No copying!
-
-  octave_ostrstream (const octave_ostrstream&);
-
-  octave_ostrstream& operator = (const octave_ostrstream&);
-};
-
-#endif
--- a/src/oct.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
-
-Copyright (C) 1996-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#if !defined (octave_oct_h)
-#define octave_oct_h 1
-
-// Things that are often included to create .oct files.
-
-// config.h needs to be first because it includes #defines that can */
-// affect other header files.
-
-#include "config.h"
-
-#include "Matrix.h"
-
-#include "oct-locbuf.h"
-#include "defun-dld.h"
-#include "error.h"
-#include "gripes.h"
-#include "help.h"
-#include "oct-obj.h"
-#include "pager.h"
-#include "utils.h"
-#include "variables.h"
-
-#endif
--- a/src/octave.gperf	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,122 +0,0 @@
-%{
-/*
-
-Copyright (C) 1995-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at
-your option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-NOTE: gperf 2.7.2 will silently generate bad code if there are blank
-lines following the "%{" marker above.  This comment block seems to be
-handled correctly.
-
-*/
-enum octave_kw_id
-{
-  break_kw,
-  case_kw,
-  catch_kw,
-  classdef_kw,
-  continue_kw,
-  do_kw,
-  else_kw,
-  elseif_kw,
-  end_kw,
-  end_try_catch_kw,
-  end_unwind_protect_kw,
-  endclassdef_kw,
-  endenumeration_kw,
-  endevents_kw,
-  endfor_kw,
-  endfunction_kw,
-  endif_kw,
-  endmethods_kw,
-  endparfor_kw,
-  endproperties_kw,
-  endswitch_kw,
-  endwhile_kw,
-  enumeration_kw,
-  events_kw,
-  for_kw,
-  function_kw,
-  get_kw,
-  global_kw,
-  if_kw,
-  magic_file_kw,
-  magic_line_kw,
-  methods_kw,
-  otherwise_kw,
-  parfor_kw,
-  persistent_kw,
-  properties_kw,
-  return_kw,
-  set_kw,
-  static_kw,
-  switch_kw,
-  try_kw,
-  until_kw,
-  unwind_protect_kw,
-  unwind_protect_cleanup_kw,
-  while_kw
-};
-%}
-struct octave_kw { const char *name; int tok; octave_kw_id kw_id; };
-%%
-break, BREAK, break_kw
-case, CASE, case_kw
-catch, CATCH, catch_kw
-classdef, CLASSDEF, classdef_kw
-continue, CONTINUE, continue_kw
-do, DO, do_kw
-else, ELSE, else_kw
-elseif, ELSEIF, elseif_kw
-end, END, end_kw
-end_try_catch, END, end_try_catch_kw
-end_unwind_protect, END, end_unwind_protect_kw
-endclassdef, END, endclassdef_kw 
-endenumeration, END, endenumeration_kw
-endevents, END, endevents_kw
-endfor, END, endfor_kw
-endfunction, END, endfunction_kw
-endif, END, endif_kw
-endmethods, END, endmethods_kw
-endparfor, END, endparfor_kw
-endproperties, END, endproperties_kw
-endswitch, END, endswitch_kw
-endwhile, END, endwhile_kw
-enumeration, ENUMERATION, enumeration_kw
-events, EVENTS, events_kw
-for, FOR, for_kw
-function, FCN, function_kw
-get, GET, get_kw
-global, GLOBAL, global_kw
-if, IF, if_kw
-methods, METHODS, methods_kw
-otherwise, OTHERWISE, otherwise_kw
-parfor, PARFOR, parfor_kw
-persistent, PERSISTENT, persistent_kw
-properties, PROPERTIES, properties_kw
-return, FUNC_RET, return_kw
-set, SET, set_kw
-static, PERSISTENT, static_kw
-switch, SWITCH, switch_kw
-try, TRY, try_kw
-until, UNTIL, until_kw
-unwind_protect, UNWIND, unwind_protect_kw
-unwind_protect_cleanup, CLEANUP, unwind_protect_cleanup_kw
-while, WHILE, while_kw
-__FILE__, DQ_STRING, magic_file_kw
-__LINE__, NUM, magic_line_kw
--- a/src/operators/module.mk	Fri Aug 03 10:14:57 2012 -0500
+++ b/src/operators/module.mk	Fri Aug 03 13:18:21 2012 -0700
@@ -129,8 +129,16 @@
   operators/op-ui64-ui64.cc \
   operators/op-ui8-ui8.cc
 
-octinclude_HEADERS += \
+## These look like included header files to Autotools build process
+OPERATOR_INCLUDES = \
   operators/op-dm-template.cc \
   operators/op-dms-template.cc \
   operators/op-int.h \
-  operators/op-pm-template.cc
+  operators/op-pm-template.cc \
+  operators/ops.h
+
+## Special rules for sources which must be built before rest of compilation.
+operators/ops.cc: $(OPERATORS_SRC) mkops
+	$(srcdir)/mkops $(OPERATORS_SRC) > $@-t
+	mv $@-t $@
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/operators/ops.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,397 @@
+/*
+
+Copyright (C) 1996-2012 John W. Eaton
+Copyright (C) 2009 VZLU Prague, a.s.
+
+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/>.
+
+*/
+
+#if !defined (octave_ops_h)
+#define octave_ops_h 1
+
+#include "Array-util.h"
+
+// Concatenation macros that enforce argument prescan
+#define CONCAT2X(x,y) x ## y
+#define CONCAT2(x,y) CONCAT2X(x,y)
+
+#define CONCAT3X(x,y,z) x ## y ## z
+#define CONCAT3(x,y,z) CONCAT3X(x,y,z)
+
+extern void install_ops (void);
+
+#define INSTALL_UNOP(op, t, f) \
+  octave_value_typeinfo::register_unary_op \
+    (octave_value::op, t::static_type_id (), CONCAT2(oct_unop_, f));
+
+#define INSTALL_NCUNOP(op, t, f) \
+  octave_value_typeinfo::register_non_const_unary_op \
+    (octave_value::op, t::static_type_id (), CONCAT2(oct_unop_, f));
+
+#define INSTALL_BINOP(op, t1, t2, f) \
+  octave_value_typeinfo::register_binary_op \
+    (octave_value::op, t1::static_type_id (), t2::static_type_id (), \
+     CONCAT2(oct_binop_, f));
+
+#define INSTALL_CATOP(t1, t2, f) \
+  octave_value_typeinfo::register_cat_op \
+    (t1::static_type_id (), t2::static_type_id (), CONCAT2(oct_catop_, f));
+
+#define INSTALL_ASSIGNOP(op, t1, t2, f) \
+  octave_value_typeinfo::register_assign_op \
+    (octave_value::op, t1::static_type_id (), t2::static_type_id (), \
+     CONCAT2(oct_assignop_, f));
+
+#define INSTALL_ASSIGNANYOP(op, t1, f) \
+  octave_value_typeinfo::register_assignany_op \
+    (octave_value::op, t1::static_type_id (), CONCAT2(oct_assignop_, f));
+
+#define INSTALL_ASSIGNCONV(t1, t2, tr) \
+  octave_value_typeinfo::register_pref_assign_conv \
+    (t1::static_type_id (), t2::static_type_id (), tr::static_type_id ());
+
+#define INSTALL_CONVOP(t1, t2, f) \
+  octave_value_typeinfo::register_type_conv_op \
+    (t1::static_type_id (), t2::static_type_id (), CONCAT2(oct_conv_, f));
+
+#define INSTALL_WIDENOP(t1, t2, f) \
+  octave_value_typeinfo::register_widening_op \
+    (t1::static_type_id (), t2::static_type_id (), CONCAT2(oct_conv_, f));
+
+#define CAST_UNOP_ARG(t) \
+  t v = dynamic_cast<t> (a)
+
+#define CAST_BINOP_ARGS(t1, t2) \
+  t1 v1 = dynamic_cast<t1> (a1);                \
+  t2 v2 = dynamic_cast<t2> (a2)
+
+#define CAST_CONV_ARG(t) \
+  t v = dynamic_cast<t> (a)
+
+#define ASSIGNOPDECL(name) \
+  static octave_value \
+  CONCAT2(oct_assignop_, name) (octave_base_value& a1, \
+                         const octave_value_list& idx, \
+                         const octave_base_value& a2)
+
+#define NULLASSIGNOPDECL(name) \
+  static octave_value \
+  CONCAT2(oct_assignop_, name) (octave_base_value& a, \
+                         const octave_value_list& idx, \
+                         const octave_base_value&)
+
+#define ASSIGNANYOPDECL(name) \
+  static octave_value \
+  CONCAT2(oct_assignop_, name) (octave_base_value& a1, \
+                         const octave_value_list& idx, \
+                         const octave_value& a2)
+
+#define DEFASSIGNOP(name, t1, t2) \
+  ASSIGNOPDECL (name)
+
+#define DEFASSIGNOP_FN(name, t1, t2, f) \
+  ASSIGNOPDECL (name) \
+  { \
+    CAST_BINOP_ARGS (CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
+ \
+    v1.f (idx, v2.CONCAT2(t1, _value) ()); \
+    return octave_value (); \
+  }
+
+#define DEFNULLASSIGNOP_FN(name, t, f) \
+  NULLASSIGNOPDECL (name) \
+  { \
+    CAST_UNOP_ARG (CONCAT2(octave_, t)&); \
+ \
+    v.f (idx); \
+    return octave_value (); \
+  }
+
+#define DEFNDASSIGNOP_FN(name, t1, t2, e, f) \
+  ASSIGNOPDECL (name) \
+  { \
+    CAST_BINOP_ARGS (CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
+ \
+    v1.f (idx, v2.CONCAT2(e, _value) ()); \
+    return octave_value (); \
+  }
+
+// FIXME: the following currently don't handle index.
+#define DEFNDASSIGNOP_OP(name, t1, t2, f, op) \
+  ASSIGNOPDECL (name) \
+  { \
+    CAST_BINOP_ARGS (CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
+ \
+    assert (idx.empty ()); \
+    v1.matrix_ref () op v2.CONCAT2(f, _value) (); \
+ \
+    return octave_value (); \
+  }
+
+#define DEFNDASSIGNOP_FNOP(name, t1, t2, f, fnop) \
+  ASSIGNOPDECL (name) \
+  { \
+    CAST_BINOP_ARGS (CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
+ \
+    assert (idx.empty ()); \
+    fnop (v1.matrix_ref (), v2.CONCAT2(f, _value) ()); \
+ \
+    return octave_value (); \
+  }
+
+#define DEFASSIGNANYOP_FN(name, t1, f) \
+  ASSIGNANYOPDECL (name) \
+  { \
+    CONCAT2(octave_, t1)& v1 = dynamic_cast<CONCAT2(octave_, t1)&> (a1); \
+ \
+    v1.f (idx, a2); \
+    return octave_value (); \
+  }
+
+#define CONVDECL(name) \
+  static octave_base_value * \
+  CONCAT2(oct_conv_, name) (const octave_base_value& a)
+
+#define CONVDECLX(name) \
+  static octave_base_value * \
+  CONCAT2(oct_conv_, name) (const octave_base_value&)
+
+#define DEFCONV(name, a_dummy, b_dummy) \
+  CONVDECL (name)
+
+#define DEFCONVFNX(name, tfrom, ovtto, tto, e) \
+  CONVDECL (name) \
+  { \
+    CAST_CONV_ARG (const CONCAT2(octave_, tfrom)&); \
+ \
+    return new CONCAT2(octave_, ovtto) (CONCAT2(tto, NDArray) (v.CONCAT2(e, array_value) ())); \
+  }
+
+#define DEFCONVFNX2(name, tfrom, ovtto, e) \
+  CONVDECL (name) \
+  { \
+    CAST_CONV_ARG (const CONCAT2(octave_, tfrom)&); \
+ \
+    return new CONCAT2(octave_, ovtto) (v.CONCAT2(e, array_value) ()); \
+  }
+
+#define DEFDBLCONVFN(name, ovtfrom, e) \
+  CONVDECL (name) \
+  { \
+    CAST_CONV_ARG (const CONCAT2(octave_, ovtfrom)&); \
+ \
+    return new octave_matrix (NDArray (v.CONCAT2(e, _value) ())); \
+  }
+
+#define DEFFLTCONVFN(name, ovtfrom, e) \
+  CONVDECL (name) \
+  { \
+    CAST_CONV_ARG (const CONCAT2(octave_, ovtfrom)&); \
+ \
+    return new octave_float_matrix (FloatNDArray (v.CONCAT2(e, _value) ())); \
+  }
+
+#define DEFSTRINTCONVFN(name, tto) \
+  DEFCONVFNX(name, char_matrix_str, CONCAT2(tto, _matrix), tto, char_)
+
+#define DEFSTRDBLCONVFN(name, tfrom) \
+  DEFCONVFNX(name, tfrom, matrix, , char_)
+
+#define DEFSTRFLTCONVFN(name, tfrom) \
+  DEFCONVFNX(name, tfrom, float_matrix, Float, char_)
+
+#define DEFCONVFN(name, tfrom, tto) \
+  DEFCONVFNX2 (name, tfrom, CONCAT2(tto, _matrix), CONCAT2(tto, _))
+
+#define DEFCONVFN2(name, tfrom, sm, tto) \
+  DEFCONVFNX2 (name, CONCAT3(tfrom, _, sm), CONCAT2(tto, _matrix), CONCAT2(tto, _))
+
+#define UNOPDECL(name, a) \
+  static octave_value \
+  CONCAT2(oct_unop_, name) (const octave_base_value& a)
+
+#define DEFUNOPX(name, t) \
+  UNOPDECL (name, , )
+
+#define DEFUNOP(name, t) \
+  UNOPDECL (name, a)
+
+#define DEFUNOP_OP(name, t, op) \
+  UNOPDECL (name, a) \
+  { \
+    CAST_UNOP_ARG (const CONCAT2(octave_, t)&); \
+    return octave_value (op v.CONCAT2(t, _value) ()); \
+  }
+
+#define DEFNDUNOP_OP(name, t, e, op) \
+  UNOPDECL (name, a) \
+  { \
+    CAST_UNOP_ARG (const CONCAT2(octave_, t)&); \
+    return octave_value (op v.CONCAT2(e, _value) ()); \
+  }
+
+// FIXME -- in some cases, the constructor isn't necessary.
+
+#define DEFUNOP_FN(name, t, f) \
+  UNOPDECL (name, a) \
+  { \
+    CAST_UNOP_ARG (const CONCAT2(octave_, t)&); \
+    return octave_value (f (v.CONCAT2(t, _value) ())); \
+  }
+
+#define DEFNDUNOP_FN(name, t, e, f) \
+  UNOPDECL (name, a) \
+  { \
+    CAST_UNOP_ARG (const CONCAT2(octave_, t)&); \
+    return octave_value (f (v.CONCAT2(e, _value) ())); \
+  }
+
+#define DEFNCUNOP_METHOD(name, t, method) \
+  static void \
+  CONCAT2(oct_unop_, name) (octave_base_value& a) \
+  { \
+    CAST_UNOP_ARG (CONCAT2(octave_, t)&); \
+    v.method (); \
+  }
+
+#define BINOPDECL(name, a1, a2) \
+  static octave_value \
+  CONCAT2(oct_binop_, name) (const octave_base_value& a1, const octave_base_value& a2)
+
+#define DEFBINOPX(name, t1, t2) \
+  BINOPDECL (name, , )
+
+#define DEFBINOP(name, t1, t2) \
+  BINOPDECL (name, a1, a2)
+
+#define DEFBINOP_OP(name, t1, t2, op) \
+  BINOPDECL (name, a1, a2) \
+  { \
+    CAST_BINOP_ARGS (const CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
+    return octave_value \
+      (v1.CONCAT2(t1, _value) () op v2.CONCAT2(t2, _value) ()); \
+  }
+
+#define DEFCMPLXCMPOP_OP(name, t1, t2, op) \
+  BINOPDECL (name, a1, a2) \
+  { \
+    CAST_BINOP_ARGS (const CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
+    gripe_warn_complex_cmp (); \
+    return octave_value \
+      (v1.CONCAT2(t1, _value) () op v2.CONCAT2(t2, _value) ()); \
+  }
+
+#define DEFSCALARBOOLOP_OP(name, t1, t2, op) \
+  BINOPDECL (name, a1, a2) \
+  { \
+    CAST_BINOP_ARGS (const CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
+    if (xisnan (v1.CONCAT2(t1, _value) ()) || xisnan (v2.CONCAT2(t2, _value) ())) \
+      { \
+        gripe_nan_to_logical_conversion (); \
+        return octave_value (); \
+      } \
+    else \
+      return octave_value \
+        (v1.CONCAT2(t1, _value) () op v2.CONCAT2(t2, _value) ()); \
+  }
+
+#define DEFNDBINOP_OP(name, t1, t2, e1, e2, op) \
+  BINOPDECL (name, a1, a2) \
+  { \
+    CAST_BINOP_ARGS (const CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
+    return octave_value \
+      (v1.CONCAT2(e1, _value) () op v2.CONCAT2(e2, _value) ()); \
+  }
+
+// FIXME -- in some cases, the constructor isn't necessary.
+
+#define DEFBINOP_FN(name, t1, t2, f) \
+  BINOPDECL (name, a1, a2) \
+  { \
+    CAST_BINOP_ARGS (const CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
+    return octave_value (f (v1.CONCAT2(t1, _value) (), v2.CONCAT2(t2, _value) ())); \
+  }
+
+#define DEFNDBINOP_FN(name, t1, t2, e1, e2, f) \
+  BINOPDECL (name, a1, a2) \
+  { \
+    CAST_BINOP_ARGS (const CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
+    return octave_value (f (v1.CONCAT2(e1, _value) (), v2.CONCAT2(e2, _value) ())); \
+  }
+
+#define DEFNDCMPLXCMPOP_FN(name, t1, t2, e1, e2, f) \
+  BINOPDECL (name, a1, a2) \
+  { \
+    CAST_BINOP_ARGS (const CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
+    return octave_value (f (v1.CONCAT2(e1, _value) (), v2.CONCAT2(e2, _value) ())); \
+  }
+
+#define CATOPDECL(name, a1, a2) \
+  static octave_value \
+  CONCAT2(oct_catop_, name) (octave_base_value& a1, const octave_base_value& a2, \
+                      const Array<octave_idx_type>& ra_idx)
+
+#define DEFCATOPX(name, t1, t2) \
+  CATOPDECL (name, , )
+
+#define DEFCATOP(name, t1, t2)  \
+  CATOPDECL (name, a1, a2)
+
+// FIXME -- in some cases, the constructor isn't necessary.
+
+#define DEFCATOP_FN(name, t1, t2, f) \
+  CATOPDECL (name, a1, a2) \
+  { \
+    CAST_BINOP_ARGS (CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
+    return octave_value (v1.CONCAT2(t1, _value) () . f (v2.CONCAT2(t2, _value) (), ra_idx)); \
+  }
+
+#define DEFNDCATOP_FN(name, t1, t2, e1, e2, f) \
+  CATOPDECL (name, a1, a2) \
+  { \
+    CAST_BINOP_ARGS (CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
+    return octave_value (v1.CONCAT2(e1, _value) () . f (v2.CONCAT2(e2, _value) (), ra_idx)); \
+  }
+
+#define DEFNDCHARCATOP_FN(name, t1, t2, f) \
+  CATOPDECL (name, a1, a2) \
+  { \
+    CAST_BINOP_ARGS (CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
+ \
+    return octave_value (v1.char_array_value () . f (v2.char_array_value (), ra_idx), \
+                         ((a1.is_sq_string () || a2.is_sq_string ()) \
+                          ? '\'' : '"')); \
+  }
+
+// For compatibility, the second arg is always converted to the type
+// of the first.  Hmm.
+
+#define DEFNDCATOP_FN2(name, t1, t2, tc1, tc2, e1, e2, f) \
+  CATOPDECL (name, a1, a2) \
+  { \
+    CAST_BINOP_ARGS (CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
+    return octave_value (tc1 (v1.CONCAT2(e1, _value) ()) . f (tc2 (v2.CONCAT2(e2, _value) ()), ra_idx)); \
+  }
+
+#define CATOP_NONCONFORMANT(msg) \
+  gripe_nonconformant (msg, \
+                       a1.rows (), a1.columns (), \
+                       a2.rows (), a2.columns ()); \
+  return octave_value ()
+
+#endif
--- a/src/ops.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,397 +0,0 @@
-/*
-
-Copyright (C) 1996-2012 John W. Eaton
-Copyright (C) 2009 VZLU Prague, a.s.
-
-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/>.
-
-*/
-
-#if !defined (octave_ops_h)
-#define octave_ops_h 1
-
-#include "Array-util.h"
-
-// Concatenation macros that enforce argument prescan
-#define CONCAT2X(x,y) x ## y
-#define CONCAT2(x,y) CONCAT2X(x,y)
-
-#define CONCAT3X(x,y,z) x ## y ## z
-#define CONCAT3(x,y,z) CONCAT3X(x,y,z)
-
-extern void install_ops (void);
-
-#define INSTALL_UNOP(op, t, f) \
-  octave_value_typeinfo::register_unary_op \
-    (octave_value::op, t::static_type_id (), CONCAT2(oct_unop_, f));
-
-#define INSTALL_NCUNOP(op, t, f) \
-  octave_value_typeinfo::register_non_const_unary_op \
-    (octave_value::op, t::static_type_id (), CONCAT2(oct_unop_, f));
-
-#define INSTALL_BINOP(op, t1, t2, f) \
-  octave_value_typeinfo::register_binary_op \
-    (octave_value::op, t1::static_type_id (), t2::static_type_id (), \
-     CONCAT2(oct_binop_, f));
-
-#define INSTALL_CATOP(t1, t2, f) \
-  octave_value_typeinfo::register_cat_op \
-    (t1::static_type_id (), t2::static_type_id (), CONCAT2(oct_catop_, f));
-
-#define INSTALL_ASSIGNOP(op, t1, t2, f) \
-  octave_value_typeinfo::register_assign_op \
-    (octave_value::op, t1::static_type_id (), t2::static_type_id (), \
-     CONCAT2(oct_assignop_, f));
-
-#define INSTALL_ASSIGNANYOP(op, t1, f) \
-  octave_value_typeinfo::register_assignany_op \
-    (octave_value::op, t1::static_type_id (), CONCAT2(oct_assignop_, f));
-
-#define INSTALL_ASSIGNCONV(t1, t2, tr) \
-  octave_value_typeinfo::register_pref_assign_conv \
-    (t1::static_type_id (), t2::static_type_id (), tr::static_type_id ());
-
-#define INSTALL_CONVOP(t1, t2, f) \
-  octave_value_typeinfo::register_type_conv_op \
-    (t1::static_type_id (), t2::static_type_id (), CONCAT2(oct_conv_, f));
-
-#define INSTALL_WIDENOP(t1, t2, f) \
-  octave_value_typeinfo::register_widening_op \
-    (t1::static_type_id (), t2::static_type_id (), CONCAT2(oct_conv_, f));
-
-#define CAST_UNOP_ARG(t) \
-  t v = dynamic_cast<t> (a)
-
-#define CAST_BINOP_ARGS(t1, t2) \
-  t1 v1 = dynamic_cast<t1> (a1);                \
-  t2 v2 = dynamic_cast<t2> (a2)
-
-#define CAST_CONV_ARG(t) \
-  t v = dynamic_cast<t> (a)
-
-#define ASSIGNOPDECL(name) \
-  static octave_value \
-  CONCAT2(oct_assignop_, name) (octave_base_value& a1, \
-                         const octave_value_list& idx, \
-                         const octave_base_value& a2)
-
-#define NULLASSIGNOPDECL(name) \
-  static octave_value \
-  CONCAT2(oct_assignop_, name) (octave_base_value& a, \
-                         const octave_value_list& idx, \
-                         const octave_base_value&)
-
-#define ASSIGNANYOPDECL(name) \
-  static octave_value \
-  CONCAT2(oct_assignop_, name) (octave_base_value& a1, \
-                         const octave_value_list& idx, \
-                         const octave_value& a2)
-
-#define DEFASSIGNOP(name, t1, t2) \
-  ASSIGNOPDECL (name)
-
-#define DEFASSIGNOP_FN(name, t1, t2, f) \
-  ASSIGNOPDECL (name) \
-  { \
-    CAST_BINOP_ARGS (CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
- \
-    v1.f (idx, v2.CONCAT2(t1, _value) ()); \
-    return octave_value (); \
-  }
-
-#define DEFNULLASSIGNOP_FN(name, t, f) \
-  NULLASSIGNOPDECL (name) \
-  { \
-    CAST_UNOP_ARG (CONCAT2(octave_, t)&); \
- \
-    v.f (idx); \
-    return octave_value (); \
-  }
-
-#define DEFNDASSIGNOP_FN(name, t1, t2, e, f) \
-  ASSIGNOPDECL (name) \
-  { \
-    CAST_BINOP_ARGS (CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
- \
-    v1.f (idx, v2.CONCAT2(e, _value) ()); \
-    return octave_value (); \
-  }
-
-// FIXME: the following currently don't handle index.
-#define DEFNDASSIGNOP_OP(name, t1, t2, f, op) \
-  ASSIGNOPDECL (name) \
-  { \
-    CAST_BINOP_ARGS (CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
- \
-    assert (idx.empty ()); \
-    v1.matrix_ref () op v2.CONCAT2(f, _value) (); \
- \
-    return octave_value (); \
-  }
-
-#define DEFNDASSIGNOP_FNOP(name, t1, t2, f, fnop) \
-  ASSIGNOPDECL (name) \
-  { \
-    CAST_BINOP_ARGS (CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
- \
-    assert (idx.empty ()); \
-    fnop (v1.matrix_ref (), v2.CONCAT2(f, _value) ()); \
- \
-    return octave_value (); \
-  }
-
-#define DEFASSIGNANYOP_FN(name, t1, f) \
-  ASSIGNANYOPDECL (name) \
-  { \
-    CONCAT2(octave_, t1)& v1 = dynamic_cast<CONCAT2(octave_, t1)&> (a1); \
- \
-    v1.f (idx, a2); \
-    return octave_value (); \
-  }
-
-#define CONVDECL(name) \
-  static octave_base_value * \
-  CONCAT2(oct_conv_, name) (const octave_base_value& a)
-
-#define CONVDECLX(name) \
-  static octave_base_value * \
-  CONCAT2(oct_conv_, name) (const octave_base_value&)
-
-#define DEFCONV(name, a_dummy, b_dummy) \
-  CONVDECL (name)
-
-#define DEFCONVFNX(name, tfrom, ovtto, tto, e) \
-  CONVDECL (name) \
-  { \
-    CAST_CONV_ARG (const CONCAT2(octave_, tfrom)&); \
- \
-    return new CONCAT2(octave_, ovtto) (CONCAT2(tto, NDArray) (v.CONCAT2(e, array_value) ())); \
-  }
-
-#define DEFCONVFNX2(name, tfrom, ovtto, e) \
-  CONVDECL (name) \
-  { \
-    CAST_CONV_ARG (const CONCAT2(octave_, tfrom)&); \
- \
-    return new CONCAT2(octave_, ovtto) (v.CONCAT2(e, array_value) ()); \
-  }
-
-#define DEFDBLCONVFN(name, ovtfrom, e) \
-  CONVDECL (name) \
-  { \
-    CAST_CONV_ARG (const CONCAT2(octave_, ovtfrom)&); \
- \
-    return new octave_matrix (NDArray (v.CONCAT2(e, _value) ())); \
-  }
-
-#define DEFFLTCONVFN(name, ovtfrom, e) \
-  CONVDECL (name) \
-  { \
-    CAST_CONV_ARG (const CONCAT2(octave_, ovtfrom)&); \
- \
-    return new octave_float_matrix (FloatNDArray (v.CONCAT2(e, _value) ())); \
-  }
-
-#define DEFSTRINTCONVFN(name, tto) \
-  DEFCONVFNX(name, char_matrix_str, CONCAT2(tto, _matrix), tto, char_)
-
-#define DEFSTRDBLCONVFN(name, tfrom) \
-  DEFCONVFNX(name, tfrom, matrix, , char_)
-
-#define DEFSTRFLTCONVFN(name, tfrom) \
-  DEFCONVFNX(name, tfrom, float_matrix, Float, char_)
-
-#define DEFCONVFN(name, tfrom, tto) \
-  DEFCONVFNX2 (name, tfrom, CONCAT2(tto, _matrix), CONCAT2(tto, _))
-
-#define DEFCONVFN2(name, tfrom, sm, tto) \
-  DEFCONVFNX2 (name, CONCAT3(tfrom, _, sm), CONCAT2(tto, _matrix), CONCAT2(tto, _))
-
-#define UNOPDECL(name, a) \
-  static octave_value \
-  CONCAT2(oct_unop_, name) (const octave_base_value& a)
-
-#define DEFUNOPX(name, t) \
-  UNOPDECL (name, , )
-
-#define DEFUNOP(name, t) \
-  UNOPDECL (name, a)
-
-#define DEFUNOP_OP(name, t, op) \
-  UNOPDECL (name, a) \
-  { \
-    CAST_UNOP_ARG (const CONCAT2(octave_, t)&); \
-    return octave_value (op v.CONCAT2(t, _value) ()); \
-  }
-
-#define DEFNDUNOP_OP(name, t, e, op) \
-  UNOPDECL (name, a) \
-  { \
-    CAST_UNOP_ARG (const CONCAT2(octave_, t)&); \
-    return octave_value (op v.CONCAT2(e, _value) ()); \
-  }
-
-// FIXME -- in some cases, the constructor isn't necessary.
-
-#define DEFUNOP_FN(name, t, f) \
-  UNOPDECL (name, a) \
-  { \
-    CAST_UNOP_ARG (const CONCAT2(octave_, t)&); \
-    return octave_value (f (v.CONCAT2(t, _value) ())); \
-  }
-
-#define DEFNDUNOP_FN(name, t, e, f) \
-  UNOPDECL (name, a) \
-  { \
-    CAST_UNOP_ARG (const CONCAT2(octave_, t)&); \
-    return octave_value (f (v.CONCAT2(e, _value) ())); \
-  }
-
-#define DEFNCUNOP_METHOD(name, t, method) \
-  static void \
-  CONCAT2(oct_unop_, name) (octave_base_value& a) \
-  { \
-    CAST_UNOP_ARG (CONCAT2(octave_, t)&); \
-    v.method (); \
-  }
-
-#define BINOPDECL(name, a1, a2) \
-  static octave_value \
-  CONCAT2(oct_binop_, name) (const octave_base_value& a1, const octave_base_value& a2)
-
-#define DEFBINOPX(name, t1, t2) \
-  BINOPDECL (name, , )
-
-#define DEFBINOP(name, t1, t2) \
-  BINOPDECL (name, a1, a2)
-
-#define DEFBINOP_OP(name, t1, t2, op) \
-  BINOPDECL (name, a1, a2) \
-  { \
-    CAST_BINOP_ARGS (const CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
-    return octave_value \
-      (v1.CONCAT2(t1, _value) () op v2.CONCAT2(t2, _value) ()); \
-  }
-
-#define DEFCMPLXCMPOP_OP(name, t1, t2, op) \
-  BINOPDECL (name, a1, a2) \
-  { \
-    CAST_BINOP_ARGS (const CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
-    gripe_warn_complex_cmp (); \
-    return octave_value \
-      (v1.CONCAT2(t1, _value) () op v2.CONCAT2(t2, _value) ()); \
-  }
-
-#define DEFSCALARBOOLOP_OP(name, t1, t2, op) \
-  BINOPDECL (name, a1, a2) \
-  { \
-    CAST_BINOP_ARGS (const CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
-    if (xisnan (v1.CONCAT2(t1, _value) ()) || xisnan (v2.CONCAT2(t2, _value) ())) \
-      { \
-        gripe_nan_to_logical_conversion (); \
-        return octave_value (); \
-      } \
-    else \
-      return octave_value \
-        (v1.CONCAT2(t1, _value) () op v2.CONCAT2(t2, _value) ()); \
-  }
-
-#define DEFNDBINOP_OP(name, t1, t2, e1, e2, op) \
-  BINOPDECL (name, a1, a2) \
-  { \
-    CAST_BINOP_ARGS (const CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
-    return octave_value \
-      (v1.CONCAT2(e1, _value) () op v2.CONCAT2(e2, _value) ()); \
-  }
-
-// FIXME -- in some cases, the constructor isn't necessary.
-
-#define DEFBINOP_FN(name, t1, t2, f) \
-  BINOPDECL (name, a1, a2) \
-  { \
-    CAST_BINOP_ARGS (const CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
-    return octave_value (f (v1.CONCAT2(t1, _value) (), v2.CONCAT2(t2, _value) ())); \
-  }
-
-#define DEFNDBINOP_FN(name, t1, t2, e1, e2, f) \
-  BINOPDECL (name, a1, a2) \
-  { \
-    CAST_BINOP_ARGS (const CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
-    return octave_value (f (v1.CONCAT2(e1, _value) (), v2.CONCAT2(e2, _value) ())); \
-  }
-
-#define DEFNDCMPLXCMPOP_FN(name, t1, t2, e1, e2, f) \
-  BINOPDECL (name, a1, a2) \
-  { \
-    CAST_BINOP_ARGS (const CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
-    return octave_value (f (v1.CONCAT2(e1, _value) (), v2.CONCAT2(e2, _value) ())); \
-  }
-
-#define CATOPDECL(name, a1, a2) \
-  static octave_value \
-  CONCAT2(oct_catop_, name) (octave_base_value& a1, const octave_base_value& a2, \
-                      const Array<octave_idx_type>& ra_idx)
-
-#define DEFCATOPX(name, t1, t2) \
-  CATOPDECL (name, , )
-
-#define DEFCATOP(name, t1, t2)  \
-  CATOPDECL (name, a1, a2)
-
-// FIXME -- in some cases, the constructor isn't necessary.
-
-#define DEFCATOP_FN(name, t1, t2, f) \
-  CATOPDECL (name, a1, a2) \
-  { \
-    CAST_BINOP_ARGS (CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
-    return octave_value (v1.CONCAT2(t1, _value) () . f (v2.CONCAT2(t2, _value) (), ra_idx)); \
-  }
-
-#define DEFNDCATOP_FN(name, t1, t2, e1, e2, f) \
-  CATOPDECL (name, a1, a2) \
-  { \
-    CAST_BINOP_ARGS (CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
-    return octave_value (v1.CONCAT2(e1, _value) () . f (v2.CONCAT2(e2, _value) (), ra_idx)); \
-  }
-
-#define DEFNDCHARCATOP_FN(name, t1, t2, f) \
-  CATOPDECL (name, a1, a2) \
-  { \
-    CAST_BINOP_ARGS (CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
- \
-    return octave_value (v1.char_array_value () . f (v2.char_array_value (), ra_idx), \
-                         ((a1.is_sq_string () || a2.is_sq_string ()) \
-                          ? '\'' : '"')); \
-  }
-
-// For compatibility, the second arg is always converted to the type
-// of the first.  Hmm.
-
-#define DEFNDCATOP_FN2(name, t1, t2, tc1, tc2, e1, e2, f) \
-  CATOPDECL (name, a1, a2) \
-  { \
-    CAST_BINOP_ARGS (CONCAT2(octave_, t1)&, const CONCAT2(octave_, t2)&); \
-    return octave_value (tc1 (v1.CONCAT2(e1, _value) ()) . f (tc2 (v2.CONCAT2(e2, _value) ()), ra_idx)); \
-  }
-
-#define CATOP_NONCONFORMANT(msg) \
-  gripe_nonconformant (msg, \
-                       a1.rows (), a1.columns (), \
-                       a2.rows (), a2.columns ()); \
-  return octave_value ()
-
-#endif
--- a/src/parse-tree/module.mk	Fri Aug 03 10:14:57 2012 -0500
+++ b/src/parse-tree/module.mk	Fri Aug 03 13:18:21 2012 -0700
@@ -1,5 +1,6 @@
 EXTRA_DIST += \
-  parse-tree/module.mk
+  parse-tree/module.mk \
+  parse-tree/octave.gperf
 
 PARSER_INCLUDES = \
   parse-tree/lex.h \
@@ -42,6 +43,7 @@
   parse-tree/pt-unop.h \
   parse-tree/pt-walk.h \
   parse-tree/pt.h \
+  parse-tree/token.h \
 	$(PARSER_INCLUDES)
 
 PARSE_TREE_SRC = \
@@ -71,5 +73,18 @@
   parse-tree/pt-stmt.cc \
   parse-tree/pt-unop.cc \
   parse-tree/pt.cc \
+  parse-tree/token.cc \
 	$(PARSER_SRC)
 
+## Special rules for sources which must be built before rest of compilation.
+
+## Don't use a pipeline to process gperf output since if gperf
+## is missing but sed is not, the exit status of the pipeline
+## will still be success and we will end up creating an empty
+## oct-gperf.h file.
+parse-tree/oct-gperf.h: parse-tree/octave.gperf
+	$(GPERF) -t -C -D -G -L C++ -Z octave_kw_hash $< > $@-t1
+	$(SED) 's,lookup\[,gperf_lookup[,' < $@-t1 > $@-t
+	mv $@-t $@
+	rm -f $@-t1
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/parse-tree/octave.gperf	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,122 @@
+%{
+/*
+
+Copyright (C) 1995-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at
+your option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+NOTE: gperf 2.7.2 will silently generate bad code if there are blank
+lines following the "%{" marker above.  This comment block seems to be
+handled correctly.
+
+*/
+enum octave_kw_id
+{
+  break_kw,
+  case_kw,
+  catch_kw,
+  classdef_kw,
+  continue_kw,
+  do_kw,
+  else_kw,
+  elseif_kw,
+  end_kw,
+  end_try_catch_kw,
+  end_unwind_protect_kw,
+  endclassdef_kw,
+  endenumeration_kw,
+  endevents_kw,
+  endfor_kw,
+  endfunction_kw,
+  endif_kw,
+  endmethods_kw,
+  endparfor_kw,
+  endproperties_kw,
+  endswitch_kw,
+  endwhile_kw,
+  enumeration_kw,
+  events_kw,
+  for_kw,
+  function_kw,
+  get_kw,
+  global_kw,
+  if_kw,
+  magic_file_kw,
+  magic_line_kw,
+  methods_kw,
+  otherwise_kw,
+  parfor_kw,
+  persistent_kw,
+  properties_kw,
+  return_kw,
+  set_kw,
+  static_kw,
+  switch_kw,
+  try_kw,
+  until_kw,
+  unwind_protect_kw,
+  unwind_protect_cleanup_kw,
+  while_kw
+};
+%}
+struct octave_kw { const char *name; int tok; octave_kw_id kw_id; };
+%%
+break, BREAK, break_kw
+case, CASE, case_kw
+catch, CATCH, catch_kw
+classdef, CLASSDEF, classdef_kw
+continue, CONTINUE, continue_kw
+do, DO, do_kw
+else, ELSE, else_kw
+elseif, ELSEIF, elseif_kw
+end, END, end_kw
+end_try_catch, END, end_try_catch_kw
+end_unwind_protect, END, end_unwind_protect_kw
+endclassdef, END, endclassdef_kw 
+endenumeration, END, endenumeration_kw
+endevents, END, endevents_kw
+endfor, END, endfor_kw
+endfunction, END, endfunction_kw
+endif, END, endif_kw
+endmethods, END, endmethods_kw
+endparfor, END, endparfor_kw
+endproperties, END, endproperties_kw
+endswitch, END, endswitch_kw
+endwhile, END, endwhile_kw
+enumeration, ENUMERATION, enumeration_kw
+events, EVENTS, events_kw
+for, FOR, for_kw
+function, FCN, function_kw
+get, GET, get_kw
+global, GLOBAL, global_kw
+if, IF, if_kw
+methods, METHODS, methods_kw
+otherwise, OTHERWISE, otherwise_kw
+parfor, PARFOR, parfor_kw
+persistent, PERSISTENT, persistent_kw
+properties, PROPERTIES, properties_kw
+return, FUNC_RET, return_kw
+set, SET, set_kw
+static, PERSISTENT, static_kw
+switch, SWITCH, switch_kw
+try, TRY, try_kw
+until, UNTIL, until_kw
+unwind_protect, UNWIND, unwind_protect_kw
+unwind_protect_cleanup, CLEANUP, unwind_protect_cleanup_kw
+while, WHILE, while_kw
+__FILE__, DQ_STRING, magic_file_kw
+__LINE__, NUM, magic_line_kw
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/parse-tree/token.cc	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,170 @@
+/*
+
+Copyright (C) 1993-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <cassert>
+
+#include "error.h"
+#include "oct-obj.h"
+#include "symtab.h"
+#include "token.h"
+#include "utils.h"
+
+token::token (int l, int c)
+{
+  line_num = l;
+  column_num = c;
+  type_tag = generic_token;
+}
+
+token::token (const std::string& s, int l, int c)
+{
+  line_num = l;
+  column_num = c;
+  type_tag = string_token;
+  str = new std::string (s);
+}
+
+token::token (double d, const std::string& s, int l, int c)
+{
+  line_num = l;
+  column_num = c;
+  type_tag = double_token;
+  num = d;
+  orig_text = s;
+}
+
+token::token (end_tok_type t, int l, int c)
+{
+  line_num = l;
+  column_num = c;
+  type_tag = ettype_token;
+  et = t;
+}
+
+token::token (symbol_table::symbol_record *s, int l, int c)
+{
+  line_num = l;
+  column_num = c;
+  type_tag = sym_rec_token;
+  sr = s;
+}
+
+token::token (symbol_table::symbol_record *cls,
+              symbol_table::symbol_record *pkg, int l, int c)
+{
+  line_num = l;
+  column_num = c;
+  type_tag = meta_rec_token;
+  mc.cr = cls;
+  mc.pr = pkg;
+}
+
+token::token (symbol_table::symbol_record *mth,
+              symbol_table::symbol_record *cls,
+              symbol_table::symbol_record *pkg, int l, int c)
+{
+  line_num = l;
+  column_num = c;
+  type_tag = scls_rec_token;
+  sc.mr = mth;
+  sc.cr = cls;
+  sc.pr = pkg;
+}
+
+token::~token (void)
+{
+  if (type_tag == string_token)
+    delete str;
+}
+
+std::string
+token::text (void)
+{
+  assert (type_tag == string_token);
+  return *str;
+}
+
+double
+token::number (void)
+{
+  assert (type_tag == double_token);
+  return num;
+}
+
+token::end_tok_type
+token::ettype (void)
+{
+  assert (type_tag == ettype_token);
+  return et;
+}
+
+symbol_table::symbol_record *
+token::sym_rec (void)
+{
+  assert (type_tag == sym_rec_token);
+  return sr;
+}
+
+symbol_table::symbol_record *
+token::method_rec (void)
+{
+  assert (type_tag == scls_rec_token);
+  return sc.mr;
+}
+
+symbol_table::symbol_record *
+token::class_rec (void)
+{
+  assert (type_tag == scls_rec_token);
+  return sc.cr;
+}
+
+symbol_table::symbol_record *
+token::package_rec (void)
+{
+  assert (type_tag == scls_rec_token);
+  return sc.pr;
+}
+
+symbol_table::symbol_record *
+token::meta_class_rec (void)
+{
+  assert (type_tag == meta_rec_token);
+  return mc.cr;
+}
+
+symbol_table::symbol_record *
+token::meta_package_rec (void)
+{
+  assert (type_tag == meta_rec_token);
+  return mc.pr;
+}
+
+std::string
+token::text_rep (void)
+{
+  return orig_text;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/parse-tree/token.h	Fri Aug 03 13:18:21 2012 -0700
@@ -0,0 +1,125 @@
+/*
+
+Copyright (C) 1993-2012 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if !defined (octave_token_h)
+#define octave_token_h 1
+
+#include <string>
+
+class
+token
+{
+public:
+
+  enum token_type
+    {
+      generic_token,
+      string_token,
+      double_token,
+      ettype_token,
+      sym_rec_token,
+      scls_rec_token,
+      meta_rec_token
+    };
+
+  enum end_tok_type
+    {
+      simple_end,
+      classdef_end,
+      enumeration_end,
+      events_end,
+      for_end,
+      function_end,
+      if_end,
+      methods_end,
+      parfor_end,
+      properties_end,
+      switch_end,
+      while_end,
+      try_catch_end,
+      unwind_protect_end
+    };
+
+  token (int l = -1, int c = -1);
+  token (const std::string& s, int l = -1, int c = -1);
+  token (double d, const std::string& s = std::string (),
+         int l = -1, int c = -1);
+  token (end_tok_type t, int l = -1, int c = -1);
+  token (symbol_table::symbol_record *s, int l = -1, int c = -1);
+  token (symbol_table::symbol_record *cls,
+         symbol_table::symbol_record *pkg, int l = -1, int c = -1);
+  token (symbol_table::symbol_record *mth,
+         symbol_table::symbol_record *cls,
+         symbol_table::symbol_record *pkg, int l = -1, int c = -1);
+
+  ~token (void);
+
+  int line (void) { return line_num; }
+  int column (void) { return column_num; }
+
+  std::string text (void);
+  double number (void);
+  end_tok_type ettype (void);
+  symbol_table::symbol_record *sym_rec (void);
+
+  symbol_table::symbol_record *method_rec (void);
+  symbol_table::symbol_record *class_rec (void);
+  symbol_table::symbol_record *package_rec (void);
+
+  symbol_table::symbol_record *meta_class_rec (void);
+  symbol_table::symbol_record *meta_package_rec (void);
+
+  std::string text_rep (void);
+
+private:
+
+  // No copying!
+
+  token (const token& tok);
+
+  token& operator = (const token& tok);
+
+  int line_num;
+  int column_num;
+  token_type type_tag;
+  union
+    {
+      std::string *str;
+      double num;
+      end_tok_type et;
+      symbol_table::symbol_record *sr;
+      struct
+        {
+          symbol_table::symbol_record *mr;
+          symbol_table::symbol_record *cr;
+          symbol_table::symbol_record *pr;
+        } sc;
+      struct
+        {
+          symbol_table::symbol_record *cr;
+          symbol_table::symbol_record *pr;
+        } mc;
+    };
+  std::string orig_text;
+};
+
+#endif
--- a/src/procstream.cc	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-/*
-
-Copyright (C) 1993-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <iostream>
-
-#include "procstream.h"
-
-procstreambase::procstreambase (const std::string& command, int mode)
-{
-  pb_init ();
-
-  if (! pb.open (command.c_str (), mode))
-    std::ios::setstate (std::ios::badbit);
-}
-
-procstreambase::procstreambase (const char *command, int mode)
-{
-  pb_init ();
-
-  if (! pb.open (command, mode))
-    std::ios::setstate (std::ios::badbit);
-}
-
-void
-procstreambase::open (const char *command, int mode)
-{
-  clear ();
-
-  if (! pb.open (command, mode))
-    std::ios::setstate (std::ios::badbit);
-}
-
-int
-procstreambase::close (void)
-{
-  int status = 0;
-
-  if (is_open ())
-    {
-      if (! pb.close ())
-        std::ios::setstate (std::ios::failbit);
-
-      status = pb.wait_status ();
-    }
-
-  return status;
-}
--- a/src/procstream.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,161 +0,0 @@
-/*
-
-Copyright (C) 1993-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#if !defined (octave_procstream_h)
-#define octave_procstream_h 1
-
-#include <iosfwd>
-#include <string>
-
-#include <sys/types.h>
-
-#include "oct-procbuf.h"
-
-class
-OCTINTERP_API
-procstreambase : virtual public std::ios
-{
-public:
-
-  procstreambase (void) : pb () { pb_init (); }
-
-  procstreambase (const std::string& name, int mode);
-
-  procstreambase (const char *name, int mode);
-
-  ~procstreambase (void) { close (); }
-
-  void open (const std::string& name, int mode)
-    { open (name.c_str (), mode); }
-
-  void open (const char *name, int mode);
-
-  int is_open (void) const { return pb.is_open (); }
-
-  int close (void);
-
-  pid_t pid (void) const { return pb.pid (); }
-
-  int file_number (void) const { return pb.file_number (); }
-
-private:
-
-  octave_procbuf pb;
-
-  void pb_init (void) { init (&pb); }
-
-  procstreambase (const procstreambase&);
-
-  procstreambase& operator = (const procstreambase&);
-};
-
-class
-OCTINTERP_API
-iprocstream : public std::istream, public procstreambase
-// iprocstream : public procstreambase, public std::istream
-{
-public:
-
-  iprocstream (void) : std::istream (0), procstreambase () { }
-
-  iprocstream (const std::string& name, int mode = std::ios::in)
-    : std::istream (0), procstreambase (name, mode) { }
-
-  iprocstream (const char *name, int mode = std::ios::in)
-    : std::istream (0), procstreambase (name, mode) { }
-
-  ~iprocstream (void) { }
-
-  void open (const std::string& name, int mode = std::ios::in)
-    { procstreambase::open (name, mode); }
-
-  void open (const char *name, int mode = std::ios::in)
-    { procstreambase::open (name, mode); }
-
-private:
-
-  iprocstream (const iprocstream&);
-
-  iprocstream& operator = (const iprocstream&);
-};
-
-class
-OCTINTERP_API
-oprocstream : public std::ostream, public procstreambase
-// oprocstream : public procstreambase, public std::ostream
-{
-public:
-
-  oprocstream (void) : std::ostream (0), procstreambase () { }
-
-  oprocstream (const std::string& name, int mode = std::ios::out)
-    : std::ostream (0), procstreambase (name, mode) { }
-
-  oprocstream (const char *name, int mode = std::ios::out)
-    : std::ostream (0), procstreambase (name, mode) { }
-
-  ~oprocstream (void) { }
-
-  void open (const std::string& name, int mode = std::ios::out)
-    { procstreambase::open (name, mode); }
-
-  void open (const char *name, int mode = std::ios::out)
-    { procstreambase::open (name, mode); }
-
-private:
-
-  oprocstream (const oprocstream&);
-
-  oprocstream& operator = (const oprocstream&);
-};
-
-class
-OCTINTERP_API
-procstream : public std::iostream, public procstreambase
-// procstream : public procstreambase, public std::iostream
-{
-public:
-
-  procstream (void) : std::iostream (0), procstreambase () { }
-
-  procstream (const std::string& name, int mode)
-    : std::iostream (0), procstreambase (name, mode) { }
-
-  procstream (const char *name, int mode)
-    : std::iostream (0), procstreambase (name, mode) { }
-
-  ~procstream (void) { }
-
-  void open (const std::string& name, int mode)
-    { procstreambase::open (name, mode); }
-
-  void open (const char *name, int mode)
-    { procstreambase::open (name, mode); }
-
-private:
-
-  procstream (const procstream&);
-
-  procstream& operator = (const procstream&);
-};
-
-#endif
--- a/src/pt-jit.cc	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1930 +0,0 @@
-/*
-
-Copyright (C) 2012 Max Brister <max@2bass.com>
-
-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/>.
-
-*/
-
-#define __STDC_LIMIT_MACROS
-#define __STDC_CONSTANT_MACROS
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifdef HAVE_LLVM
-
-#include "pt-jit.h"
-
-#include <llvm/Analysis/CallGraph.h>
-#include <llvm/Analysis/Passes.h>
-#include <llvm/Analysis/Verifier.h>
-#include <llvm/LLVMContext.h>
-#include <llvm/ExecutionEngine/ExecutionEngine.h>
-#include <llvm/ExecutionEngine/JIT.h>
-#include <llvm/Module.h>
-#include <llvm/PassManager.h>
-#include <llvm/Support/IRBuilder.h>
-#include <llvm/Support/raw_os_ostream.h>
-#include <llvm/Support/TargetSelect.h>
-#include <llvm/Target/TargetData.h>
-#include <llvm/Transforms/IPO.h>
-#include <llvm/Transforms/Scalar.h>
-
-#ifdef OCTAVE_JIT_DEBUG
-#include <llvm/Bitcode/ReaderWriter.h>
-#endif
-
-#include "symtab.h"
-#include "pt-all.h"
-
-static llvm::IRBuilder<> builder (llvm::getGlobalContext ());
-
-static llvm::LLVMContext& context = llvm::getGlobalContext ();
-
-// -------------------- jit_convert --------------------
-jit_convert::jit_convert (llvm::Module *module, tree &tee,
-                          jit_type *for_bounds)
-  : iterator_count (0), for_bounds_count (0), short_count (0), breaking (false)
-{
-  jit_instruction::reset_ids ();
-
-  entry_block = create<jit_block> ("body");
-  final_block = create<jit_block> ("final");
-  append (entry_block);
-  entry_block->mark_alive ();
-  block = entry_block;
-
-  if (for_bounds)
-    create_variable (next_for_bounds (false), for_bounds);
-
-  visit (tee);
-
-  // FIXME: Remove if we no longer only compile loops
-  assert (! breaking);
-  assert (breaks.empty ());
-  assert (continues.empty ());
-
-  block->append (create<jit_branch> (final_block));
-  append (final_block);
-
-  for (vmap_t::iterator iter = vmap.begin (); iter != vmap.end (); ++iter)
-    {
-      jit_variable *var = iter->second;
-      const std::string& name = var->name ();
-      if (name.size () && name[0] != '#')
-        final_block->append (create<jit_store_argument> (var));
-    }
-
-  construct_ssa ();
-
-  // initialize the worklist to instructions derived from constants
-  for (std::list<jit_value *>::iterator iter = constants.begin ();
-       iter != constants.end (); ++iter)
-    append_users (*iter);
-
-  // the entry block terminator may be a regular branch statement
-  if (entry_block->terminator ())
-    push_worklist (entry_block->terminator ());
-
-  // FIXME: Describe algorithm here
-  while (worklist.size ())
-    {
-      jit_instruction *next = worklist.front ();
-      worklist.pop_front ();
-      next->stash_in_worklist (false);
-
-      if (next->infer ())
-        {
-          // terminators need to be handles specially
-          if (jit_terminator *term = dynamic_cast<jit_terminator *> (next))
-            append_users_term (term);
-          else
-            append_users (next);
-        }
-    }
-
-  remove_dead ();
-  merge_blocks ();
-  final_block->label ();
-  place_releases ();
-  simplify_phi ();
-
-#ifdef OCTAVE_JIT_DEBUG
-  final_block->label ();
-  std::cout << "-------------------- Compiling tree --------------------\n";
-  std::cout << tee.str_print_code () << std::endl;
-  print_blocks ("octave jit ir");
-#endif
-
-  // for now just init arguments from entry, later we will have to do something
-  // more interesting
-  for (jit_block::iterator iter = entry_block->begin ();
-       iter != entry_block->end (); ++iter)
-    if (jit_extract_argument *extract
-        = dynamic_cast<jit_extract_argument *> (*iter))
-      arguments.push_back (std::make_pair (extract->name (), true));
-
-  convert_llvm to_llvm (*this);
-  function = to_llvm.convert (module, arguments, blocks, constants);
-
-#ifdef OCTAVE_JIT_DEBUG
-  std::cout << "-------------------- llvm ir --------------------";
-  llvm::raw_os_ostream llvm_cout (std::cout);
-  function->print (llvm_cout);
-  std::cout << std::endl;
-  llvm::verifyFunction (*function);
-#endif
-}
-
-jit_convert::~jit_convert (void)
-{
-  for (std::list<jit_value *>::iterator iter = all_values.begin ();
-       iter != all_values.end (); ++iter)
-    delete *iter;
-}
-
-void
-jit_convert::visit_anon_fcn_handle (tree_anon_fcn_handle&)
-{
-  throw jit_fail_exception ();
-}
-
-void
-jit_convert::visit_argument_list (tree_argument_list&)
-{
-  throw jit_fail_exception ();
-}
-
-void
-jit_convert::visit_binary_expression (tree_binary_expression& be)
-{
-  if (be.op_type () >= octave_value::num_binary_ops)
-    {
-      tree_boolean_expression *boole;
-      boole = dynamic_cast<tree_boolean_expression *> (&be);
-      assert (boole);
-      bool is_and = boole->op_type () == tree_boolean_expression::bool_and;
-
-      std::string short_name = next_shortcircut_result ();
-      jit_variable *short_result = create<jit_variable> (short_name);
-      vmap[short_name] = short_result;
-
-      jit_block *done = create<jit_block> (block->name ());
-      tree_expression *lhs = be.lhs ();
-      jit_value *lhsv = visit (lhs);
-      lhsv = create_checked (&jit_typeinfo::logically_true, lhsv);
-
-      jit_block *short_early = create<jit_block> ("short_early");
-      append (short_early);
-
-      jit_block *short_cont = create<jit_block> ("short_cont");
-
-      if (is_and)
-        block->append (create<jit_cond_branch> (lhsv, short_cont, short_early));
-      else
-        block->append (create<jit_cond_branch> (lhsv, short_early, short_cont));
-
-      block = short_early;
-
-      jit_value *early_result = create<jit_const_bool> (! is_and);
-      block->append (create<jit_assign> (short_result, early_result));
-      block->append (create<jit_branch> (done));
-
-      append (short_cont);
-      block = short_cont;
-
-      tree_expression *rhs = be.rhs ();
-      jit_value *rhsv = visit (rhs);
-      rhsv = create_checked (&jit_typeinfo::logically_true, rhsv);
-      block->append (create<jit_assign> (short_result, rhsv));
-      block->append (create<jit_branch> (done));
-
-      append (done);
-      block = done;
-      result = short_result;
-    }
-  else
-    {
-      tree_expression *lhs = be.lhs ();
-      jit_value *lhsv = visit (lhs);
-
-      tree_expression *rhs = be.rhs ();
-      jit_value *rhsv = visit (rhs);
-
-      const jit_operation& fn = jit_typeinfo::binary_op (be.op_type ());
-      result = create_checked (fn, lhsv, rhsv);
-    }
-}
-
-void
-jit_convert::visit_break_command (tree_break_command&)
-{
-  breaks.push_back (block);
-  breaking = true;
-}
-
-void
-jit_convert::visit_colon_expression (tree_colon_expression& expr)
-{
-  // in the futher we need to add support for classes and deal with rvalues
-  jit_value *base = visit (expr.base ());
-  jit_value *limit = visit (expr.limit ());
-  jit_value *increment;
-  tree_expression *tinc = expr.increment ();
-
-  if (tinc)
-    increment = visit (tinc);
-  else
-    increment = create<jit_const_scalar> (1);
-
-  result = block->append (create<jit_call> (jit_typeinfo::make_range, base,
-                                            limit, increment));
-}
-
-void
-jit_convert::visit_continue_command (tree_continue_command&)
-{
-  continues.push_back (block);
-  breaking = true;
-}
-
-void
-jit_convert::visit_global_command (tree_global_command&)
-{
-  throw jit_fail_exception ();
-}
-
-void
-jit_convert::visit_persistent_command (tree_persistent_command&)
-{
-  throw jit_fail_exception ();
-}
-
-void
-jit_convert::visit_decl_elt (tree_decl_elt&)
-{
-  throw jit_fail_exception ();
-}
-
-void
-jit_convert::visit_decl_init_list (tree_decl_init_list&)
-{
-  throw jit_fail_exception ();
-}
-
-void
-jit_convert::visit_simple_for_command (tree_simple_for_command& cmd)
-{
-  // Note we do an initial check to see if the loop will run atleast once.
-  // This allows us to get better type inference bounds on variables defined
-  // and used only inside the for loop (e.g. the index variable)
-
-  // If we are a nested for loop we need to store the previous breaks
-  assert (! breaking);
-  unwind_protect prot;
-  prot.protect_var (breaks);
-  prot.protect_var (continues);
-  prot.protect_var (breaking);
-  breaks.clear ();
-  continues.clear ();
-
-  // we need a variable for our iterator, because it is used in multiple blocks
-  std::string iter_name = next_iterator ();
-  jit_variable *iterator = create<jit_variable> (iter_name);
-  create<jit_variable> (iter_name);
-  vmap[iter_name] = iterator;
-
-  jit_block *body = create<jit_block> ("for_body");
-  append (body);
-
-  jit_block *tail = create<jit_block> ("for_tail");
-
-  // do control expression, iter init, and condition check in prev_block (block)
-  // if we are the top level for loop, the bounds is an input argument.
-  jit_value *control = find_variable (next_for_bounds ());
-  if (! control)
-    control = visit (cmd.control_expr ());
-  jit_call *init_iter = create<jit_call> (jit_typeinfo::for_init, control);
-  block->append (init_iter);
-  block->append (create<jit_assign> (iterator, init_iter));
-
-  jit_value *check = block->append (create<jit_call> (jit_typeinfo::for_check,
-                                                      control, iterator));
-  block->append (create<jit_cond_branch> (check, body, tail));
-  block = body;
-
-  // compute the syntactical iterator
-  jit_call *idx_rhs = create<jit_call> (jit_typeinfo::for_index, control,
-                                        iterator);
-  block->append (idx_rhs);
-  do_assign (cmd.left_hand_side (), idx_rhs);
-
-  // do loop
-  tree_statement_list *pt_body = cmd.body ();
-  pt_body->accept (*this);
-
-  if (breaking && continues.empty ())
-    {
-      // WTF are you doing user? Every branch was a continue, why did you have
-      // a loop??? Users are silly people...
-      finish_breaks (tail, breaks);
-      append (tail);
-      block = tail;
-      return;
-    }
-
-  // check our condition, continues jump to this block
-  jit_block *check_block = create<jit_block> ("for_check");
-  append (check_block);
-
-  if (! breaking)
-    block->append (create<jit_branch> (check_block));
-  finish_breaks (check_block, continues);
-
-  block = check_block;
-  const jit_operation& add_fn = jit_typeinfo::binary_op (octave_value::op_add);
-  jit_value *one = create<jit_const_index> (1);
-  jit_call *iter_inc = create<jit_call> (add_fn, iterator, one);
-  block->append (iter_inc);
-  block->append (create<jit_assign> (iterator, iter_inc));
-  check = block->append (create<jit_call> (jit_typeinfo::for_check, control,
-                                           iterator));
-  block->append (create<jit_cond_branch> (check, body, tail));
-
-  // breaks will go to our tail
-  append (tail);
-  finish_breaks (tail, breaks);
-  block = tail;
-}
-
-void
-jit_convert::visit_complex_for_command (tree_complex_for_command&)
-{
-  throw jit_fail_exception ();
-}
-
-void
-jit_convert::visit_octave_user_script (octave_user_script&)
-{
-  throw jit_fail_exception ();
-}
-
-void
-jit_convert::visit_octave_user_function (octave_user_function&)
-{
-  throw jit_fail_exception ();
-}
-
-void
-jit_convert::visit_octave_user_function_header (octave_user_function&)
-{
-  throw jit_fail_exception ();
-}
-
-void
-jit_convert::visit_octave_user_function_trailer (octave_user_function&)
-{
-  throw jit_fail_exception ();
-}
-
-void
-jit_convert::visit_function_def (tree_function_def&)
-{
-  throw jit_fail_exception ();
-}
-
-void
-jit_convert::visit_identifier (tree_identifier& ti)
-{
-  if (ti.has_magic_end ())
-    {
-      if (!end_context.size ())
-        throw jit_fail_exception ("Illegal end");
-      result = block->append (create<jit_magic_end> (end_context));
-    }
-  else
-    result = get_variable (ti.name ());
-}
-
-void
-jit_convert::visit_if_clause (tree_if_clause&)
-{
-  throw jit_fail_exception ();
-}
-
-void
-jit_convert::visit_if_command (tree_if_command& cmd)
-{
-  tree_if_command_list *lst = cmd.cmd_list ();
-  assert (lst); // jwe: Can this be null?
-  lst->accept (*this);
-}
-
-void
-jit_convert::visit_if_command_list (tree_if_command_list& lst)
-{
-  tree_if_clause *last = lst.back ();
-  size_t last_else = static_cast<size_t> (last->is_else_clause ());
-
-  // entry_blocks represents the block you need to enter in order to execute
-  // the condition check for the ith clause. For the else, it is simple the
-  // else body. If there is no else body, then it is padded with the tail
-  std::vector<jit_block *> entry_blocks (lst.size () + 1 - last_else);
-  std::vector<jit_block *> branch_blocks (lst.size (), 0); // final blocks
-  entry_blocks[0] = block;
-
-  // we need to construct blocks first, because they have jumps to eachother
-  tree_if_command_list::iterator iter = lst.begin ();
-  ++iter;
-  for (size_t i = 1; iter != lst.end (); ++iter, ++i)
-    {
-      tree_if_clause *tic = *iter;
-      if (tic->is_else_clause ())
-        entry_blocks[i] = create<jit_block> ("else");
-      else
-        entry_blocks[i] = create<jit_block> ("ifelse_cond");
-    }
-
-  jit_block *tail = create<jit_block> ("if_tail");
-  if (! last_else)
-    entry_blocks[entry_blocks.size () - 1] = tail;
-
-  size_t num_incomming = 0; // number of incomming blocks to our tail
-  iter = lst.begin ();
-  for (size_t i = 0; iter != lst.end (); ++iter, ++i)
-    {
-      tree_if_clause *tic = *iter;
-      block = entry_blocks[i];
-      assert (block);
-
-      if (i) // the first block is prev_block, so it has already been added
-        append (entry_blocks[i]);
-
-      if (! tic->is_else_clause ())
-        {
-          tree_expression *expr = tic->condition ();
-          jit_value *cond = visit (expr);
-          jit_call *check = create_checked (&jit_typeinfo::logically_true,
-                                            cond);
-          jit_block *body = create<jit_block> (i == 0 ? "if_body"
-                                               : "ifelse_body");
-          append (body);
-
-          jit_instruction *br = create<jit_cond_branch> (check, body,
-                                                        entry_blocks[i + 1]);
-          block->append (br);
-          block = body;
-        }
-
-      tree_statement_list *stmt_lst = tic->commands ();
-      assert (stmt_lst); // jwe: Can this be null?
-      stmt_lst->accept (*this);
-
-      if (breaking)
-        breaking = false;
-      else
-        {
-          ++num_incomming;
-          block->append (create<jit_branch> (tail));
-        }
-    }
-
-  if (num_incomming || ! last_else)
-    {
-      append (tail);
-      block = tail;
-    }
-  else
-    // every branch broke, so we don't have a tail
-    breaking = true;
-}
-
-void
-jit_convert::visit_index_expression (tree_index_expression& exp)
-{
-  result = resolve (jit_typeinfo::paren_subsref (), exp);
-}
-
-void
-jit_convert::visit_matrix (tree_matrix&)
-{
-  throw jit_fail_exception ();
-}
-
-void
-jit_convert::visit_cell (tree_cell&)
-{
-  throw jit_fail_exception ();
-}
-
-void
-jit_convert::visit_multi_assignment (tree_multi_assignment&)
-{
-  throw jit_fail_exception ();
-}
-
-void
-jit_convert::visit_no_op_command (tree_no_op_command&)
-{
-  throw jit_fail_exception ();
-}
-
-void
-jit_convert::visit_constant (tree_constant& tc)
-{
-  octave_value v = tc.rvalue1 ();
-  if (v.is_real_scalar () && v.is_double_type ())
-    {
-      double dv = v.double_value ();
-      result = create<jit_const_scalar> (dv);
-    }
-  else if (v.is_range ())
-    {
-      Range rv = v.range_value ();
-      result = create<jit_const_range> (rv);
-    }
-  else if (v.is_complex_scalar ())
-    {
-      Complex cv = v.complex_value ();
-      result = create<jit_const_complex> (cv);
-    }
-  else
-    throw jit_fail_exception ("Unknown constant");
-}
-
-void
-jit_convert::visit_fcn_handle (tree_fcn_handle&)
-{
-  throw jit_fail_exception ();
-}
-
-void
-jit_convert::visit_parameter_list (tree_parameter_list&)
-{
-  throw jit_fail_exception ();
-}
-
-void
-jit_convert::visit_postfix_expression (tree_postfix_expression&)
-{
-  throw jit_fail_exception ();
-}
-
-void
-jit_convert::visit_prefix_expression (tree_prefix_expression&)
-{
-  throw jit_fail_exception ();
-}
-
-void
-jit_convert::visit_return_command (tree_return_command&)
-{
-  throw jit_fail_exception ();
-}
-
-void
-jit_convert::visit_return_list (tree_return_list&)
-{
-  throw jit_fail_exception ();
-}
-
-void
-jit_convert::visit_simple_assignment (tree_simple_assignment& tsa)
-{
-  if (tsa.op_type () != octave_value::op_asn_eq)
-    throw jit_fail_exception ("Unsupported assign");
-
-  // resolve rhs
-  tree_expression *rhs = tsa.right_hand_side ();
-  jit_value *rhsv = visit (rhs);
-
-  result = do_assign (tsa.left_hand_side (), rhsv);
-}
-
-void
-jit_convert::visit_statement (tree_statement& stmt)
-{
-  tree_command *cmd = stmt.command ();
-  tree_expression *expr = stmt.expression ();
-
-  if (cmd)
-    visit (cmd);
-  else
-    {
-      // stolen from tree_evaluator::visit_statement
-      bool do_bind_ans = false;
-
-      if (expr->is_identifier ())
-        {
-          tree_identifier *id = dynamic_cast<tree_identifier *> (expr);
-
-          do_bind_ans = (! id->is_variable ());
-        }
-      else
-        do_bind_ans = (! expr->is_assignment_expression ());
-
-      jit_value *expr_result = visit (expr);
-
-      if (do_bind_ans)
-        do_assign ("ans", expr_result, expr->print_result ());
-      else if (expr->is_identifier () && expr->print_result ())
-        {
-          // FIXME: ugly hack, we need to come up with a way to pass
-          // nargout to visit_identifier
-          const jit_operation& fn = jit_typeinfo::print_value ();
-          jit_const_string *name = create<jit_const_string> (expr->name ());
-          block->append (create<jit_call> (fn, name, expr_result));
-        }
-    }
-}
-
-void
-jit_convert::visit_statement_list (tree_statement_list& lst)
-{
-  for (tree_statement_list::iterator iter = lst.begin (); iter != lst.end();
-       ++iter)
-    {
-      tree_statement *elt = *iter;
-      // jwe: Can this ever be null?
-      assert (elt);
-      elt->accept (*this);
-
-      if (breaking)
-        break;
-    }
-}
-
-void
-jit_convert::visit_switch_case (tree_switch_case&)
-{
-  throw jit_fail_exception ();
-}
-
-void
-jit_convert::visit_switch_case_list (tree_switch_case_list&)
-{
-  throw jit_fail_exception ();
-}
-
-void
-jit_convert::visit_switch_command (tree_switch_command&)
-{
-  throw jit_fail_exception ();
-}
-
-void
-jit_convert::visit_try_catch_command (tree_try_catch_command&)
-{
-  throw jit_fail_exception ();
-}
-
-void
-jit_convert::visit_unwind_protect_command (tree_unwind_protect_command&)
-{
-  throw jit_fail_exception ();
-}
-
-void
-jit_convert::visit_while_command (tree_while_command& wc)
-{
-  assert (! breaking);
-  unwind_protect prot;
-  prot.protect_var (breaks);
-  prot.protect_var (continues);
-  prot.protect_var (breaking);
-  breaks.clear ();
-  continues.clear ();
-
-  jit_block *cond_check = create<jit_block> ("while_cond_check");
-  block->append (create<jit_branch> (cond_check));
-  append (cond_check);
-  block = cond_check;
-
-  tree_expression *expr = wc.condition ();
-  assert (expr && "While expression can not be null");
-  jit_value *check = visit (expr);
-  check = create_checked (&jit_typeinfo::logically_true, check);
-
-  jit_block *body = create<jit_block> ("while_body");
-  append (body);
-
-  jit_block *tail = create<jit_block> ("while_tail");
-  block->append (create<jit_cond_branch> (check, body, tail));
-  block = body;
-
-  tree_statement_list *loop_body = wc.body ();
-  if (loop_body)
-    loop_body->accept (*this);
-
-  finish_breaks (tail, breaks);
-  finish_breaks (cond_check, continues);
-
-  if (! breaking)
-    block->append (create<jit_branch> (cond_check));
-
-  append (tail);
-  block = tail;
-}
-
-void
-jit_convert::visit_do_until_command (tree_do_until_command&)
-{
-  throw jit_fail_exception ();
-}
-
-void
-jit_convert::append (jit_block *ablock)
-{
-  blocks.push_back (ablock);
-  ablock->stash_location (--blocks.end ());
-}
-
-void
-jit_convert::insert_before (block_iterator iter, jit_block *ablock)
-{
-  iter = blocks.insert (iter, ablock);
-  ablock->stash_location (iter);
-}
-
-void
-jit_convert::insert_after (block_iterator iter, jit_block *ablock)
-{
-  ++iter;
-  insert_before (iter, ablock);
-}
-
-jit_variable *
-jit_convert::find_variable (const std::string& vname) const
-{
-  vmap_t::const_iterator iter;
-  iter = vmap.find (vname);
-  return iter != vmap.end () ? iter->second : 0;
-}
-
-jit_variable *
-jit_convert::get_variable (const std::string& vname)
-{
-  jit_variable *ret = find_variable (vname);
-  if (ret)
-    return ret;
-
-  octave_value val = symbol_table::find (vname);
-  jit_type *type = jit_typeinfo::type_of (val);
-  return create_variable (vname, type);
-}
-
-jit_variable *
-jit_convert::create_variable (const std::string& vname, jit_type *type)
-{
-  jit_variable *var = create<jit_variable> (vname);
-  jit_extract_argument *extract;
-  extract = create<jit_extract_argument> (type, var);
-  entry_block->prepend (extract);
-  return vmap[vname] = var;
-}
-
-std::string
-jit_convert::next_name (const char *prefix, size_t& count, bool inc)
-{
-  std::stringstream ss;
-  ss << prefix << count;
-  if (inc)
-    ++count;
-  return ss.str ();
-}
-
-jit_instruction *
-jit_convert::resolve (const jit_operation& fres, tree_index_expression& exp,
-                      jit_value *extra_arg)
-{
-  std::string type = exp.type_tags ();
-  if (! (type.size () == 1 && type[0] == '('))
-    throw jit_fail_exception ("Unsupported index operation");
-
-  std::list<tree_argument_list *> args = exp.arg_lists ();
-  if (args.size () != 1)
-    throw jit_fail_exception ("Bad number of arguments in tree_index_expression");
-
-  tree_argument_list *arg_list = args.front ();
-  if (! arg_list)
-    throw jit_fail_exception ("null argument list");
-
-  if (arg_list->size () < 1)
-    throw jit_fail_exception ("Empty arg_list");
-
-  tree_expression *tree_object = exp.expression ();
-  jit_value *object = visit (tree_object);
-
-  size_t narg = arg_list->size ();
-  tree_argument_list::iterator iter = arg_list->begin ();
-  bool have_extra = extra_arg;
-  std::vector<jit_value *> call_args (narg + 1 + have_extra);
-  call_args[0] = object;
-
-  for (size_t idx = 0; iter != arg_list->end (); ++idx, ++iter)
-    {
-      unwind_protect prot;
-      prot.add_method (&end_context,
-                       &std::vector<jit_magic_end::context>::pop_back);
-      end_context.push_back (jit_magic_end::context (object, idx, narg));
-      call_args[idx + 1] = visit (*iter);
-    }
-
-  if (extra_arg)
-    call_args[call_args.size () - 1] = extra_arg;
-
-  return create_checked (fres, call_args);
-}
-
-jit_value *
-jit_convert::do_assign (tree_expression *exp, jit_value *rhs, bool artificial)
-{
-  if (! exp)
-    throw jit_fail_exception ("NULL lhs in assign");
-
-  if (isa<tree_identifier> (exp))
-    return do_assign (exp->name (), rhs, exp->print_result (), artificial);
-  else if (tree_index_expression *idx
-           = dynamic_cast<tree_index_expression *> (exp))
-    {
-      jit_value *new_object = resolve (jit_typeinfo::paren_subsasgn (), *idx,
-                                       rhs);
-      do_assign (idx->expression (), new_object, true);
-
-      // FIXME: Will not work for values that must be release/grabed
-      return rhs;
-    }
-  else
-    throw jit_fail_exception ("Unsupported assignment");
-}
-
-jit_value *
-jit_convert::do_assign (const std::string& lhs, jit_value *rhs,
-                        bool print, bool artificial)
-{
-  jit_variable *var = get_variable (lhs);
-  jit_assign *assign = block->append (create<jit_assign> (var, rhs));
-
-  if (artificial)
-    assign->mark_artificial ();
-
-  if (print)
-    {
-      const jit_operation& print_fn = jit_typeinfo::print_value ();
-      jit_const_string *name = create<jit_const_string> (lhs);
-      block->append (create<jit_call> (print_fn, name, var));
-    }
-
-  return var;
-}
-
-jit_value *
-jit_convert::visit (tree& tee)
-{
-  result = 0;
-  tee.accept (*this);
-
-  jit_value *ret = result;
-  result = 0;
-  return ret;
-}
-
-void
-jit_convert::append_users_term (jit_terminator *term)
-{
-  for (size_t i = 0; i < term->successor_count (); ++i)
-    {
-      if (term->alive (i))
-        {
-          jit_block *succ = term->successor (i);
-          for (jit_block::iterator iter = succ->begin (); iter != succ->end ()
-                 && isa<jit_phi> (*iter); ++iter)
-            push_worklist (*iter);
-
-          jit_terminator *sterm = succ->terminator ();
-          if (sterm)
-            push_worklist (sterm);
-        }
-    }
-}
-
-void
-jit_convert::merge_blocks (void)
-{
-  std::vector<jit_block *> dead;
-  for (block_list::iterator iter = blocks.begin (); iter != blocks.end ();
-       ++iter)
-    {
-      jit_block *b = *iter;
-      jit_block *merged = b->maybe_merge ();
-
-      if (merged)
-        {
-          if (merged == final_block)
-            final_block = b;
-
-          if (merged == entry_block)
-            entry_block = b;
-
-          dead.push_back (merged);
-        }
-    }
-
-  for (size_t i = 0; i < dead.size (); ++i)
-    blocks.erase (dead[i]->location ());
-}
-
-void
-jit_convert::construct_ssa (void)
-{
-  merge_blocks ();
-  final_block->label ();
-  final_block->compute_idom (entry_block);
-  entry_block->compute_df ();
-  entry_block->create_dom_tree ();
-
-  // insert phi nodes where needed, this is done on a per variable basis
-  for (vmap_t::iterator iter = vmap.begin (); iter != vmap.end (); ++iter)
-    {
-      jit_block::df_set visited, added_phi;
-      std::list<jit_block *> ssa_worklist;
-      iter->second->use_blocks (visited);
-      ssa_worklist.insert (ssa_worklist.begin (), visited.begin (),
-                           visited.end ());
-
-      while (ssa_worklist.size ())
-        {
-          jit_block *b = ssa_worklist.front ();
-          ssa_worklist.pop_front ();
-
-          for (jit_block::df_iterator diter = b->df_begin ();
-               diter != b->df_end (); ++diter)
-            {
-              jit_block *dblock = *diter;
-              if (! added_phi.count (dblock))
-                {
-                  jit_phi *phi = create<jit_phi> (iter->second,
-                                                  dblock->use_count ());
-                  dblock->prepend (phi);
-                  added_phi.insert (dblock);
-                }
-
-              if (! visited.count (dblock))
-                {
-                  ssa_worklist.push_back (dblock);
-                  visited.insert (dblock);
-                }
-            }
-        }
-    }
-
-  do_construct_ssa (*entry_block, entry_block->visit_count ());
-}
-
-void
-jit_convert::do_construct_ssa (jit_block& ablock, size_t avisit_count)
-{
-  if (ablock.visited (avisit_count))
-    return;
-
-  // replace variables with their current SSA value
-  for (jit_block::iterator iter = ablock.begin (); iter != ablock.end (); ++iter)
-    {
-      jit_instruction *instr = *iter;
-      instr->construct_ssa ();
-      instr->push_variable ();
-    }
-
-  // finish phi nodes of successors
-  for (size_t i = 0; i < ablock.successor_count (); ++i)
-    {
-      jit_block *finish = ablock.successor (i);
-
-      for (jit_block::iterator iter = finish->begin (); iter != finish->end ()
-             && isa<jit_phi> (*iter);)
-        {
-          jit_phi *phi = static_cast<jit_phi *> (*iter);
-          jit_variable *var = phi->dest ();
-          if (var->has_top ())
-            {
-              phi->add_incomming (&ablock, var->top ());
-              ++iter;
-            }
-          else
-            {
-              // temporaries may have extranious phi nodes which can be removed
-              assert (! phi->use_count ());
-              assert (var->name ().size () && var->name ()[0] == '#');
-              iter = finish->remove (iter);
-            }
-        }
-    }
-
-  for (size_t i = 0; i < ablock.dom_successor_count (); ++i)
-    do_construct_ssa (*ablock.dom_successor (i), avisit_count);
-
-  ablock.pop_all ();
-}
-
-void
-jit_convert::remove_dead ()
-{
-  block_list::iterator biter;
-  for (biter = blocks.begin (); biter != blocks.end (); ++biter)
-    {
-      jit_block *b = *biter;
-      if (b->alive ())
-        {
-          for (jit_block::iterator iter = b->begin (); iter != b->end ()
-                 && isa<jit_phi> (*iter);)
-            {
-              jit_phi *phi = static_cast<jit_phi *> (*iter);
-              if (phi->prune ())
-                iter = b->remove (iter);
-              else
-                ++iter;
-            }
-        }
-    }
-
-  for (biter = blocks.begin (); biter != blocks.end ();)
-    {
-      jit_block *b = *biter;
-      if (b->alive ())
-        {
-          // FIXME: A special case for jit_error_check, if we generalize to
-          // we will need to change!
-          jit_terminator *term = b->terminator ();
-          if (term && term->successor_count () == 2 && ! term->alive (0))
-            {
-              jit_block *succ = term->successor (1);
-              term->remove ();
-              jit_branch *abreak = b->append (create<jit_branch> (succ));
-              abreak->infer ();
-            }
-
-          ++biter;
-        }
-      else
-        {
-          jit_terminator *term = b->terminator ();
-          if (term)
-            term->remove ();
-          biter = blocks.erase (biter);
-        }
-    }
-}
-
-void
-jit_convert::place_releases (void)
-{
-  std::set<jit_value *> temporaries;
-  for (block_list::iterator iter = blocks.begin (); iter != blocks.end ();
-       ++iter)
-    {
-      jit_block& ablock = **iter;
-      if (ablock.id () != jit_block::NO_ID)
-        {
-          release_temp (ablock, temporaries);
-          release_dead_phi (ablock);
-        }
-    }
-}
-
-void
-jit_convert::release_temp (jit_block& ablock, std::set<jit_value *>& temp)
-{
-  for (jit_block::iterator iter = ablock.begin (); iter != ablock.end ();
-       ++iter)
-    {
-      jit_instruction *instr = *iter;
-
-      // check for temporaries that require release and live across
-      // multiple blocks
-      if (instr->needs_release ())
-        {
-          jit_block *fu_block = instr->first_use_block ();
-          if (fu_block && fu_block != &ablock)
-            temp.insert (instr);
-        }
-
-      if (isa<jit_call> (instr))
-        {
-          // place releases for temporary arguments
-          for (size_t i = 0; i < instr->argument_count (); ++i)
-            {
-              jit_value *arg = instr->argument (i);
-              if (arg->needs_release ())
-                {
-                  jit_call *release = create<jit_call> (&jit_typeinfo::release,
-                                                        arg);
-                  release->infer ();
-                  ablock.insert_after (iter, release);
-                  ++iter;
-                  temp.erase (arg);
-                }
-            }
-        }
-    }
-
-  if (! temp.size () || ! isa<jit_error_check> (ablock.terminator ()))
-    return;
-
-  // FIXME: If we support try/catch or unwind_protect final_block may not be the
-  // destination
-  jit_block *split = ablock.maybe_split (*this, final_block);
-  jit_terminator *term = split->terminator ();
-  for (std::set<jit_value *>::const_iterator iter = temp.begin ();
-       iter != temp.end (); ++iter)
-    {
-      jit_value *value = *iter;
-      jit_call *release = create<jit_call> (&jit_typeinfo::release, value);
-      split->insert_before (term, release);
-      release->infer ();
-    }
-}
-
-void
-jit_convert::release_dead_phi (jit_block& ablock)
-{
-  jit_block::iterator iter = ablock.begin ();
-  while (iter != ablock.end () && isa<jit_phi> (*iter))
-    {
-      jit_phi *phi = static_cast<jit_phi *> (*iter);
-      ++iter;
-
-      jit_use *use = phi->first_use ();
-      if (phi->use_count () == 1 && isa<jit_assign> (use->user ()))
-        {
-          // instead of releasing on assign, release on all incomming branches,
-          // this can get rid of casts inside loops
-          for (size_t i = 0; i < phi->argument_count (); ++i)
-            {
-              jit_value *arg = phi->argument (i);
-              jit_block *inc = phi->incomming (i);
-              jit_block *split = inc->maybe_split (*this, ablock);
-              jit_terminator *term = split->terminator ();
-              jit_call *release = create<jit_call> (jit_typeinfo::release, arg);
-              release->infer ();
-              split->insert_before (term, release);
-            }
-
-          phi->replace_with (0);
-          phi->remove ();
-        }
-    }
-}
-
-void
-jit_convert::simplify_phi (void)
-{
-  for (block_list::iterator biter = blocks.begin (); biter != blocks.end ();
-       ++biter)
-    {
-      jit_block &ablock = **biter;
-      for (jit_block::iterator iter = ablock.begin (); iter != ablock.end ()
-             && isa<jit_phi> (*iter); ++iter)
-        simplify_phi (*static_cast<jit_phi *> (*iter));
-    }
-}
-
-void
-jit_convert::simplify_phi (jit_phi& phi)
-{
-  jit_block& pblock = *phi.parent ();
-  const jit_operation& cast_fn = jit_typeinfo::cast (phi.type ());
-  jit_variable *dest = phi.dest ();
-  for (size_t i = 0; i < phi.argument_count (); ++i)
-    {
-      jit_value *arg = phi.argument (i);
-      if (arg->type () != phi.type ())
-        {
-          jit_block *pred = phi.incomming (i);
-          jit_block *split = pred->maybe_split (*this, pblock);
-          jit_terminator *term = split->terminator ();
-          jit_instruction *cast = create<jit_call> (cast_fn, arg);
-          jit_assign *assign = create<jit_assign> (dest, cast);
-
-          split->insert_before (term, cast);
-          split->insert_before (term, assign);
-          cast->infer ();
-          assign->infer ();
-          phi.stash_argument (i, assign);
-        }
-    }
-}
-
-void
-jit_convert::finish_breaks (jit_block *dest, const block_list& lst)
-{
-  for (block_list::const_iterator iter = lst.begin (); iter != lst.end ();
-       ++iter)
-    {
-      jit_block *b = *iter;
-      b->append (create<jit_branch> (dest));
-    }
-}
-
-// -------------------- jit_convert::convert_llvm --------------------
-llvm::Function *
-jit_convert::convert_llvm::convert (llvm::Module *module,
-                                    const std::vector<std::pair< std::string, bool> >& args,
-                                    const std::list<jit_block *>& blocks,
-                                    const std::list<jit_value *>& constants)
-{
-  jit_type *any = jit_typeinfo::get_any ();
-
-  // argument is an array of octave_base_value*, or octave_base_value**
-  llvm::Type *arg_type = any->to_llvm (); // this is octave_base_value*
-  arg_type = arg_type->getPointerTo ();
-  llvm::FunctionType *ft = llvm::FunctionType::get (llvm::Type::getVoidTy (context),
-                                                    arg_type, false);
-  function = llvm::Function::Create (ft, llvm::Function::ExternalLinkage,
-                                     "foobar", module);
-
-  try
-    {
-      prelude = llvm::BasicBlock::Create (context, "prelude", function);
-      builder.SetInsertPoint (prelude);
-
-      llvm::Value *arg = function->arg_begin ();
-      for (size_t i = 0; i < args.size (); ++i)
-        {
-          llvm::Value *loaded_arg = builder.CreateConstInBoundsGEP1_32 (arg, i);
-          arguments[args[i].first] = loaded_arg;
-        }
-
-      std::list<jit_block *>::const_iterator biter;
-      for (biter = blocks.begin (); biter != blocks.end (); ++biter)
-        {
-          jit_block *jblock = *biter;
-          llvm::BasicBlock *block = llvm::BasicBlock::Create (context,
-                                                              jblock->name (),
-                                                              function);
-          jblock->stash_llvm (block);
-        }
-
-      jit_block *first = *blocks.begin ();
-      builder.CreateBr (first->to_llvm ());
-
-      // constants aren't in the IR, we visit those first
-      for (std::list<jit_value *>::const_iterator iter = constants.begin ();
-           iter != constants.end (); ++iter)
-        if (! isa<jit_instruction> (*iter))
-          visit (*iter);
-
-      // convert all instructions
-      for (biter = blocks.begin (); biter != blocks.end (); ++biter)
-        visit (*biter);
-
-      // now finish phi nodes
-      for (biter = blocks.begin (); biter != blocks.end (); ++biter)
-        {
-          jit_block& block = **biter;
-          for (jit_block::iterator piter = block.begin ();
-               piter != block.end () && isa<jit_phi> (*piter); ++piter)
-            {
-              jit_instruction *phi = *piter;
-              finish_phi (static_cast<jit_phi *> (phi));
-            }
-        }
-
-      jit_block *last = blocks.back ();
-      builder.SetInsertPoint (last->to_llvm ());
-      builder.CreateRetVoid ();
-    } catch (const jit_fail_exception& e)
-    {
-      function->eraseFromParent ();
-      throw;
-    }
-
-  return function;
-}
-
-void
-jit_convert::convert_llvm::finish_phi (jit_phi *phi)
-{
-  llvm::PHINode *llvm_phi = phi->to_llvm ();
-  for (size_t i = 0; i < phi->argument_count (); ++i)
-    {
-      llvm::BasicBlock *pred = phi->incomming_llvm (i);
-      llvm_phi->addIncoming (phi->argument_llvm (i), pred);
-    }
-}
-
-void
-jit_convert::convert_llvm::visit (jit_const_string& cs)
-{
-  cs.stash_llvm (builder.CreateGlobalStringPtr (cs.value ()));
-}
-
-void
-jit_convert::convert_llvm::visit (jit_const_bool& cb)
-{
-  cb.stash_llvm (llvm::ConstantInt::get (cb.type_llvm (), cb.value ()));
-}
-
-void
-jit_convert::convert_llvm::visit (jit_const_scalar& cs)
-{
-  cs.stash_llvm (llvm::ConstantFP::get (cs.type_llvm (), cs.value ()));
-}
-
-void
-jit_convert::convert_llvm::visit (jit_const_complex& cc)
-{
-  llvm::Type *scalar_t = jit_typeinfo::get_scalar_llvm ();
-  llvm::Constant *values[2];
-  Complex value = cc.value ();
-  values[0] = llvm::ConstantFP::get (scalar_t, value.real ());
-  values[1] = llvm::ConstantFP::get (scalar_t, value.imag ());
-  cc.stash_llvm (llvm::ConstantVector::get (values));
-}
-
-void jit_convert::convert_llvm::visit (jit_const_index& ci)
-{
-  ci.stash_llvm (llvm::ConstantInt::get (ci.type_llvm (), ci.value ()));
-}
-
-void
-jit_convert::convert_llvm::visit (jit_const_range& cr)
-{
-  llvm::StructType *stype = llvm::cast<llvm::StructType>(cr.type_llvm ());
-  llvm::Type *scalar_t = jit_typeinfo::get_scalar_llvm ();
-  llvm::Type *idx = jit_typeinfo::get_index_llvm ();
-  const jit_range& rng = cr.value ();
-
-  llvm::Constant *constants[4];
-  constants[0] = llvm::ConstantFP::get (scalar_t, rng.base);
-  constants[1] = llvm::ConstantFP::get (scalar_t, rng.limit);
-  constants[2] = llvm::ConstantFP::get (scalar_t, rng.inc);
-  constants[3] = llvm::ConstantInt::get (idx, rng.nelem);
-
-  llvm::Value *as_llvm;
-  as_llvm = llvm::ConstantStruct::get (stype,
-                                       llvm::makeArrayRef (constants, 4));
-  cr.stash_llvm (as_llvm);
-}
-
-void
-jit_convert::convert_llvm::visit (jit_block& b)
-{
-  llvm::BasicBlock *block = b.to_llvm ();
-  builder.SetInsertPoint (block);
-  for (jit_block::iterator iter = b.begin (); iter != b.end (); ++iter)
-    visit (*iter);
-}
-
-void
-jit_convert::convert_llvm::visit (jit_branch& b)
-{
-  b.stash_llvm (builder.CreateBr (b.successor_llvm ()));
-}
-
-void
-jit_convert::convert_llvm::visit (jit_cond_branch& cb)
-{
-  llvm::Value *cond = cb.cond_llvm ();
-  llvm::Value *br;
-  br = builder.CreateCondBr (cond, cb.successor_llvm (0),
-                             cb.successor_llvm (1));
-  cb.stash_llvm (br);
-}
-
-void
-jit_convert::convert_llvm::visit (jit_call& call)
-{
-  const jit_function& ol = call.overload ();
-
-  std::vector<jit_value *> args (call.arguments ().size ());
-  for (size_t i = 0; i < args.size (); ++i)
-    args[i] = call.argument (i);
-
-  llvm::Value *ret = ol.call (builder, args);
-  call.stash_llvm (ret);
-}
-
-void
-jit_convert::convert_llvm::visit (jit_extract_argument& extract)
-{
-  llvm::Value *arg = arguments[extract.name ()];
-  assert (arg);
-  arg = builder.CreateLoad (arg);
-
-  const jit_function& ol = extract.overload ();
-  extract.stash_llvm (ol.call (builder, arg));
-}
-
-void
-jit_convert::convert_llvm::visit (jit_store_argument& store)
-{
-  const jit_function& ol = store.overload ();
-  llvm::Value *arg_value = ol.call (builder, store.result ());
-  llvm::Value *arg = arguments[store.name ()];
-  store.stash_llvm (builder.CreateStore (arg_value, arg));
-}
-
-void
-jit_convert::convert_llvm::visit (jit_phi& phi)
-{
-  // we might not have converted all incoming branches, so we don't
-  // set incomming branches now
-  llvm::PHINode *node = llvm::PHINode::Create (phi.type_llvm (),
-                                               phi.argument_count ());
-  builder.Insert (node);
-  phi.stash_llvm (node);
-}
-
-void
-jit_convert::convert_llvm::visit (jit_variable&)
-{
-  throw jit_fail_exception ("ERROR: SSA construction should remove all variables");
-}
-
-void
-jit_convert::convert_llvm::visit (jit_error_check& check)
-{
-  llvm::Value *cond = jit_typeinfo::insert_error_check (builder);
-  llvm::Value *br = builder.CreateCondBr (cond, check.successor_llvm (0),
-                                          check.successor_llvm (1));
-  check.stash_llvm (br);
-}
-
-void
-jit_convert::convert_llvm::visit (jit_assign& assign)
-{
-  jit_value *new_value = assign.src ();
-  assign.stash_llvm (new_value->to_llvm ());
-
-  if (assign.artificial ())
-    return;
-
-  if (isa<jit_assign_base> (new_value))
-    {
-      const jit_function& ol =  jit_typeinfo::get_grab (new_value->type ());
-      if (ol.valid ())
-        assign.stash_llvm (ol.call (builder, new_value));
-    }
-
-  jit_value *overwrite = assign.overwrite ();
-  if (isa<jit_assign_base> (overwrite))
-    {
-      const jit_function& ol = jit_typeinfo::get_release (overwrite->type ());
-      ol.call (builder, overwrite);
-    }
-}
-
-void
-jit_convert::convert_llvm::visit (jit_argument&)
-{}
-
-void
-jit_convert::convert_llvm::visit (jit_magic_end& me)
-{
-  const jit_function& ol = me.overload ();
-  llvm::Value *ret = ol.call (builder, me.resolve_context ());
-  me.stash_llvm (ret);
-}
-
-// -------------------- tree_jit --------------------
-
-tree_jit::tree_jit (void) : module (0), engine (0)
-{
-}
-
-tree_jit::~tree_jit (void)
-{}
-
-bool
-tree_jit::execute (tree_simple_for_command& cmd, const octave_value& bounds)
-{
-  const size_t MIN_TRIP_COUNT = 1000;
-
-  size_t tc = trip_count (bounds);
-  if (! tc || ! initialize ())
-    return false;
-
-  jit_info::vmap extra_vars;
-  extra_vars["#for_bounds0"] = &bounds;
-
-  jit_info *info = cmd.get_info ();
-  if (! info || ! info->match (extra_vars))
-    {
-      if (tc < MIN_TRIP_COUNT)
-        return false;
-
-      delete info;
-      info = new jit_info (*this, cmd, bounds);
-      cmd.stash_info (info);
-    }
-
-  return info->execute (extra_vars);
-}
-
-bool
-tree_jit::execute (tree_while_command& cmd)
-{
-  if (! initialize ())
-    return false;
-
-  jit_info *info = cmd.get_info ();
-  if (! info || ! info->match ())
-    {
-      delete info;
-      info = new jit_info (*this, cmd);
-      cmd.stash_info (info);
-    }
-
-  return info->execute ();
-}
-
-bool
-tree_jit::initialize (void)
-{
-  if (engine)
-    return true;
-
-  if (! module)
-    {
-      llvm::InitializeNativeTarget ();
-      module = new llvm::Module ("octave", context);
-    }
-
-  // sometimes this fails pre main
-  engine = llvm::ExecutionEngine::createJIT (module);
-
-  if (! engine)
-    return false;
-
-  module_pass_manager = new llvm::PassManager ();
-  module_pass_manager->add (llvm::createAlwaysInlinerPass ());
-
-  pass_manager = new llvm::FunctionPassManager (module);
-  pass_manager->add (new llvm::TargetData(*engine->getTargetData ()));
-  pass_manager->add (llvm::createBasicAliasAnalysisPass ());
-  pass_manager->add (llvm::createPromoteMemoryToRegisterPass ());
-  pass_manager->add (llvm::createInstructionCombiningPass ());
-  pass_manager->add (llvm::createReassociatePass ());
-  pass_manager->add (llvm::createGVNPass ());
-  pass_manager->add (llvm::createCFGSimplificationPass ());
-  pass_manager->doInitialization ();
-
-  jit_typeinfo::initialize (module, engine);
-
-  return true;
-}
-
-size_t
-tree_jit::trip_count (const octave_value& bounds) const
-{
-  if (bounds.is_range ())
-    {
-      Range rng = bounds.range_value ();
-      return rng.nelem ();
-    }
-
-  // unsupported type
-  return 0;
-}
-
-
-void
-tree_jit::optimize (llvm::Function *fn)
-{
-  module_pass_manager->run (*module);
-  pass_manager->run (*fn);
-
-#ifdef OCTAVE_JIT_DEBUG
-  std::string error;
-  llvm::raw_fd_ostream fout ("test.bc", error,
-                             llvm::raw_fd_ostream::F_Binary);
-  llvm::WriteBitcodeToFile (module, fout);
-#endif
-}
-
-// -------------------- jit_info --------------------
-jit_info::jit_info (tree_jit& tjit, tree& tee)
-  : engine (tjit.get_engine ()), function (0), llvm_function (0)
-{
-  try
-    {
-      jit_convert conv (tjit.get_module (), tee);
-      initialize (tjit, conv);
-    }
-  catch (const jit_fail_exception& e)
-    {
-#ifdef OCTAVE_JIT_DEBUG
-      if (e.known ())
-        std::cout << "jit fail: " << e.what () << std::endl;
-#endif
-    }
-}
-
-jit_info::jit_info (tree_jit& tjit, tree& tee, const octave_value& for_bounds)
-  : engine (tjit.get_engine ()), function (0), llvm_function (0)
-{
-  try
-    {
-      jit_convert conv (tjit.get_module (), tee,
-                        jit_typeinfo::type_of (for_bounds));
-      initialize (tjit, conv);
-    }
-  catch (const jit_fail_exception& e)
-    {
-#ifdef OCTAVE_JIT_DEBUG
-      if (e.known ())
-        std::cout << "jit fail: " << e.what () << std::endl;
-#endif
-    }
-}
-
-jit_info::~jit_info (void)
-{
-  if (llvm_function)
-    llvm_function->eraseFromParent ();
-}
-
-bool
-jit_info::execute (const vmap& extra_vars) const
-{
-  if (! function)
-    return false;
-
-  std::vector<octave_base_value *> real_arguments (arguments.size ());
-  for (size_t i = 0; i < arguments.size (); ++i)
-    {
-      if (arguments[i].second)
-        {
-          octave_value current = find (extra_vars, arguments[i].first);
-          octave_base_value *obv = current.internal_rep ();
-          obv->grab ();
-          real_arguments[i] = obv;
-        }
-    }
-
-  function (&real_arguments[0]);
-
-  for (size_t i = 0; i < arguments.size (); ++i)
-    {
-      const std::string& name = arguments[i].first;
-
-      // do not store for loop bounds temporary
-      if (name.size () && name[0] != '#')
-        symbol_table::varref (arguments[i].first) = real_arguments[i];
-    }
-
-  return true;
-}
-
-bool
-jit_info::match (const vmap& extra_vars) const
-{
-  if (! function)
-    return true;
-
-  for (size_t i = 0; i < bounds.size (); ++i)
-    {
-      const std::string& arg_name = bounds[i].second;
-      octave_value value = find (extra_vars, arg_name);
-      jit_type *type = jit_typeinfo::type_of (value);
-
-      // FIXME: Check for a parent relationship
-      if (type != bounds[i].first)
-        return false;
-    }
-
-  return true;
-}
-
-void
-jit_info::initialize (tree_jit& tjit, jit_convert& conv)
-{
-  llvm_function = conv.get_function ();
-  arguments = conv.get_arguments ();
-  bounds = conv.get_bounds ();
-
-  if (llvm_function)
-    {
-      tjit.optimize (llvm_function);
-
-#ifdef OCTAVE_JIT_DEBUG
-      std::cout << "-------------------- optimized llvm ir "
-                << "--------------------\n";
-      llvm::raw_os_ostream llvm_cout (std::cout);
-      llvm_function->print (llvm_cout);
-      llvm_cout.flush ();
-      std::cout << std::endl;
-#endif
-
-      void *void_fn = engine->getPointerToFunction (llvm_function);
-      function = reinterpret_cast<jited_function> (void_fn);
-    }
-}
-
-octave_value
-jit_info::find (const vmap& extra_vars, const std::string& vname) const
-{
-  vmap::const_iterator iter = extra_vars.find (vname);
-  return iter == extra_vars.end () ? symbol_table::varval (vname)
-    : *iter->second;
-}
-
-#endif
-
-
-/*
-Test some simple cases that compile.
-
-%!test
-%! inc = 1e-5;
-%! result = 0;
-%! for ii = 0:inc:1
-%!   result = result + inc * (1/3 * ii * ii);
-%! endfor
-%! assert (abs (result - 1/9) < 1e-5);
-
-%!test
-%! inc = 1e-5;
-%! result = 0;
-%! for ii = 0:inc:1
-%!   # the ^ operator's result is complex
-%!   result = result + inc * (1/3 * ii ^ 2);
-%! endfor
-%! assert (abs (result - 1/9) < 1e-5);
-
-%!test
-%! nr = 1001;
-%! mat = zeros (1, nr);
-%! for i = 1:nr
-%!   mat(i) = i;
-%! endfor
-%! assert (mat == 1:nr);
-
-%!test
-%! nr = 1001;
-%! mat = 1:nr;
-%! mat(end) = 0; # force mat to a matrix
-%! total = 0;
-%! for i = 1:nr
-%!   total = mat(i) + total;
-%! endfor
-%! assert (sum (mat) == total);
-
-%!test
-%! nr = 1001;
-%! mat = [3 1 5];
-%! try
-%!   for i = 1:nr
-%!     if i > 500
-%!       result = mat(100);
-%!     else
-%!       result = i;
-%!     endif
-%!   endfor
-%! catch
-%! end
-%! assert (result == 500);
-
-%!function result = gen_test (n)
-%!  result = double (rand (1, n) > .01);
-%!endfunction
-
-%!function z = vectorized (A, K)
-%!  temp = ones (1, K);
-%!  z = conv (A, temp);
-%!  z = z > K-1;
-%!  z = conv (z, temp);
-%!  z = z(K:end-K+1);
-%!  z = z >= 1;
-%!endfunction
-
-%!function z = loopy (A, K)
-%!  z = A;
-%!  n = numel (A);
-%!  counter = 0;
-%!  for ii=1:n
-%!    if z(ii)
-%!      counter = counter + 1;
-%!    else
-%!      if counter > 0 && counter < K
-%!        z(ii-counter:ii-1) = 0;
-%!      endif
-%!      counter = 0;
-%!    endif
-%!  endfor
-%!
-%!  if counter > 0 && counter < K
-%!    z(end-counter+1:end) = 0;
-%!  endif
-%!endfunction
-
-%!test
-%! test_set = gen_test (10000);
-%! assert (all (vectorized (test_set, 3) == loopy (test_set, 3)));
-
-%!test
-%! niter = 1001;
-%! i = 0;
-%! while (i < niter)
-%!   i = i + 1;
-%! endwhile
-%! assert (i == niter);
-
-%!test
-%! niter = 1001;
-%! result = 0;
-%! m = [5 10];
-%! for i=1:niter
-%!   result = result + m(end);
-%! endfor
-%! assert (result == m(end) * niter);
-
-%!test
-%! ndim = 100;
-%! result = 0;
-%! m = zeros (ndim);
-%! m(:) = 1:ndim^2;
-%! i = 1;
-%! while (i <= ndim)
-%!   for j = 1:ndim
-%!     result = result + m(i, j);
-%!    endfor
-%!   i = i + 1;
-%! endwhile
-%! assert (result == sum (sum (m)));
-
-%!test
-%! ndim = 100;
-%! m = zeros (ndim);
-%! i = 1;
-%! while (i <= ndim)
-%!   for j = 1:ndim
-%!     m(i, j) = (j - 1) * ndim + i;
-%!   endfor
-%!   i = i + 1;
-%! endwhile
-%! m2 = zeros (ndim);
-%! m2(:) = 1:(ndim^2);
-%! assert (all (m == m2));
-
-%!test
-%! ndim = 2;
-%! m = zeros (ndim, ndim, ndim, ndim);
-%! result = 0;
-%! i0 = 1;
-%! while (i0 <= ndim)
-%!   for i1 = 1:ndim
-%!     for i2 = 1:ndim
-%!       for i3 = 1:ndim
-%!         m(i0, i1, i2, i3) = 1;
-%!         m(i0, i1, i2, i3, 1, 1, 1, 1, 1, 1) = 1;
-%!         result = result + m(i0, i1, i2, i3);
-%!       endfor
-%!     endfor
-%!   endfor
-%!   i0 = i0 + 1;
-%! endwhile
-%! expected = ones (ndim, ndim, ndim, ndim);
-%! assert (all (m == expected));
-%! assert (result == sum (expected (:)));
-
-%!function test_divide ()
-%! state = warning ("query", "Octave:divide-by-zero").state;
-%! unwind_protect
-%!   warning ("error", "Octave:divide-by-zero");
-%!   for i=1:1e5
-%!     a = 1;
-%!     a / 0;
-%!   endfor
-%! unwind_protect_cleanup
-%!   warning (state, "Octave:divide-by-zero");
-%! end_unwind_protect
-%!endfunction
-
-%!error <division by zero> test_divide ()
-
-%!test
-%! while 1
-%!   a = 0;
-%!   result = a / 1;
-%!   break;
-%! endwhile
-%! assert (result, 0);
-
-*/
--- a/src/pt-jit.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,491 +0,0 @@
-/*
-
-Copyright (C) 2012 Max Brister <max@2bass.com>
-
-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/>.
-
-*/
-
-#if !defined (octave_tree_jit_h)
-#define octave_tree_jit_h 1
-
-#ifdef HAVE_LLVM
-
-#include "jit-ir.h"
-
-#include "pt-walk.h"
-
-// -------------------- Current status --------------------
-// Simple binary operations (+-*/) on octave_scalar's (doubles) are optimized.
-// a = 5;
-// b = a * 5 + a;
-//
-// Indexing matrices with scalars works.
-//
-// if, elseif, else, break, continue, and for compile. Compilation is triggered
-// at the start of a simple for loop.
-//
-// The octave low level IR is a linear IR, it works by converting everything to
-// calls to jit_operations. This turns expressions like c = a + b into
-// c = call binary+ (a, b)
-// The jit_operations contain information about overloads for different types.
-// For, example, if we know a and b are scalars, then c must also be a scalar.
-//
-// Support for function calls is in progress. Currently, calls to sin with a
-// scalar argument will compile.
-//
-// TODO:
-// 1. Function calls (In progress)
-// 2. Cleanup/documentation
-// 3. ...
-// ---------------------------------------------------------
-
-// convert between IRs
-// FIXME: Class relationships are messy from here on down. They need to be
-// cleaned up.
-class
-jit_convert : public tree_walker
-{
-public:
-  typedef std::pair<jit_type *, std::string> type_bound;
-  typedef std::vector<type_bound> type_bound_vector;
-
-  jit_convert (llvm::Module *module, tree &tee, jit_type *for_bounds = 0);
-
-  ~jit_convert (void);
-
-  llvm::Function *get_function (void) const { return function; }
-
-  const std::vector<std::pair<std::string, bool> >& get_arguments(void) const
-  { return arguments; }
-
-  const type_bound_vector& get_bounds (void) const { return bounds; }
-
-  void visit_anon_fcn_handle (tree_anon_fcn_handle&);
-
-  void visit_argument_list (tree_argument_list&);
-
-  void visit_binary_expression (tree_binary_expression&);
-
-  void visit_break_command (tree_break_command&);
-
-  void visit_colon_expression (tree_colon_expression&);
-
-  void visit_continue_command (tree_continue_command&);
-
-  void visit_global_command (tree_global_command&);
-
-  void visit_persistent_command (tree_persistent_command&);
-
-  void visit_decl_elt (tree_decl_elt&);
-
-  void visit_decl_init_list (tree_decl_init_list&);
-
-  void visit_simple_for_command (tree_simple_for_command&);
-
-  void visit_complex_for_command (tree_complex_for_command&);
-
-  void visit_octave_user_script (octave_user_script&);
-
-  void visit_octave_user_function (octave_user_function&);
-
-  void visit_octave_user_function_header (octave_user_function&);
-
-  void visit_octave_user_function_trailer (octave_user_function&);
-
-  void visit_function_def (tree_function_def&);
-
-  void visit_identifier (tree_identifier&);
-
-  void visit_if_clause (tree_if_clause&);
-
-  void visit_if_command (tree_if_command&);
-
-  void visit_if_command_list (tree_if_command_list&);
-
-  void visit_index_expression (tree_index_expression&);
-
-  void visit_matrix (tree_matrix&);
-
-  void visit_cell (tree_cell&);
-
-  void visit_multi_assignment (tree_multi_assignment&);
-
-  void visit_no_op_command (tree_no_op_command&);
-
-  void visit_constant (tree_constant&);
-
-  void visit_fcn_handle (tree_fcn_handle&);
-
-  void visit_parameter_list (tree_parameter_list&);
-
-  void visit_postfix_expression (tree_postfix_expression&);
-
-  void visit_prefix_expression (tree_prefix_expression&);
-
-  void visit_return_command (tree_return_command&);
-
-  void visit_return_list (tree_return_list&);
-
-  void visit_simple_assignment (tree_simple_assignment&);
-
-  void visit_statement (tree_statement&);
-
-  void visit_statement_list (tree_statement_list&);
-
-  void visit_switch_case (tree_switch_case&);
-
-  void visit_switch_case_list (tree_switch_case_list&);
-
-  void visit_switch_command (tree_switch_command&);
-
-  void visit_try_catch_command (tree_try_catch_command&);
-
-  void visit_unwind_protect_command (tree_unwind_protect_command&);
-
-  void visit_while_command (tree_while_command&);
-
-  void visit_do_until_command (tree_do_until_command&);
-
-  // this would be easier with variadic templates
-  template <typename T>
-  T *create (void)
-  {
-    T *ret = new T();
-    track_value (ret);
-    return ret;
-  }
-
-#define DECL_ARG(n) const ARG ## n& arg ## n
-#define JIT_CREATE(N)                                           \
-  template <typename T, OCT_MAKE_DECL_LIST (typename, ARG, N)>  \
-  T *create (OCT_MAKE_LIST (DECL_ARG, N))                       \
-  {                                                             \
-    T *ret = new T (OCT_MAKE_ARG_LIST (arg, N));                \
-    track_value (ret);                                          \
-    return ret;                                                 \
-  }
-
-  JIT_CREATE (1)
-  JIT_CREATE (2)
-  JIT_CREATE (3)
-  JIT_CREATE (4)
-
-#undef JIT_CREATE
-
-#define JIT_CREATE_CHECKED(N)                                           \
-  template <OCT_MAKE_DECL_LIST (typename, ARG, N)>                      \
-  jit_call *create_checked (OCT_MAKE_LIST (DECL_ARG, N))                \
-  {                                                                     \
-    jit_call *ret = create<jit_call> (OCT_MAKE_ARG_LIST (arg, N));      \
-    return create_checked_impl (ret);                                   \
-  }
-
-  JIT_CREATE_CHECKED (1)
-  JIT_CREATE_CHECKED (2)
-  JIT_CREATE_CHECKED (3)
-  JIT_CREATE_CHECKED (4)
-
-#undef JIT_CREATE_CHECKED
-#undef DECL_ARG
-
-  typedef std::list<jit_block *> block_list;
-  typedef block_list::iterator block_iterator;
-
-  void append (jit_block *ablock);
-
-  void insert_before (block_iterator iter, jit_block *ablock);
-
-  void insert_before (jit_block *loc, jit_block *ablock)
-  {
-    insert_before (loc->location (), ablock);
-  }
-
-  void insert_after (block_iterator iter, jit_block *ablock);
-
-  void insert_after (jit_block *loc, jit_block *ablock)
-  {
-    insert_after (loc->location (), ablock);
-  }
-private:
-  std::vector<std::pair<std::string, bool> > arguments;
-  type_bound_vector bounds;
-
-  // used instead of return values from visit_* functions
-  jit_value *result;
-
-  jit_block *entry_block;
-
-  jit_block *final_block;
-
-  jit_block *block;
-
-  llvm::Function *function;
-
-  std::list<jit_block *> blocks;
-
-  std::list<jit_instruction *> worklist;
-
-  std::list<jit_value *> constants;
-
-  std::list<jit_value *> all_values;
-
-  std::vector<jit_magic_end::context> end_context;
-
-  size_t iterator_count;
-  size_t for_bounds_count;
-  size_t short_count;
-
-  typedef std::map<std::string, jit_variable *> vmap_t;
-  vmap_t vmap;
-
-  jit_call *create_checked_impl (jit_call *ret)
-  {
-    block->append (ret);
-    create_check (ret);
-    return ret;
-  }
-
-  jit_error_check *create_check (jit_call *call)
-  {
-    jit_block *normal = create<jit_block> (block->name ());
-    jit_error_check *ret
-      = block->append (create<jit_error_check> (call, normal, final_block));
-    append (normal);
-    block = normal;
-
-    return ret;
-  }
-
-  // get an existing vairable. If the variable does not exist, it will not be
-  // created
-  jit_variable *find_variable (const std::string& vname) const;
-
-  // get a variable, create it if it does not exist. The type will default to
-  // the variable's current type in the symbol table.
-  jit_variable *get_variable (const std::string& vname);
-
-  // create a variable of the given name and given type. Will also insert an
-  // extract statement
-  jit_variable *create_variable (const std::string& vname, jit_type *type);
-
-  // The name of the next for loop iterator. If inc is false, then the iterator
-  // counter will not be incremented.
-  std::string next_iterator (bool inc = true)
-  { return next_name ("#iter", iterator_count, inc); }
-
-  std::string next_for_bounds (bool inc = true)
-  { return next_name ("#for_bounds", for_bounds_count, inc); }
-
-  std::string next_shortcircut_result (bool inc = true)
-  { return next_name ("#shortcircut_result", short_count, inc); }
-
-  std::string next_name (const char *prefix, size_t& count, bool inc);
-
-  jit_instruction *resolve (const jit_operation& fres,
-                            tree_index_expression& exp,
-                            jit_value *extra_arg = 0);
-
-  jit_value *do_assign (tree_expression *exp, jit_value *rhs,
-                        bool artificial = false);
-
-  jit_value *do_assign (const std::string& lhs, jit_value *rhs, bool print,
-                        bool artificial = false);
-
-  jit_value *visit (tree *tee) { return visit (*tee); }
-
-  jit_value *visit (tree& tee);
-
-  void push_worklist (jit_instruction *instr)
-  {
-    if (! instr->in_worklist ())
-      {
-        instr->stash_in_worklist (true);
-        worklist.push_back (instr);
-      }
-  }
-
-  void append_users (jit_value *v)
-  {
-    for (jit_use *use = v->first_use (); use; use = use->next ())
-      push_worklist (use->user ());
-  }
-
-  void append_users_term (jit_terminator *term);
-
-  void track_value (jit_value *value)
-  {
-    if (value->type ())
-      constants.push_back (value);
-    all_values.push_back (value);
-  }
-
-  void merge_blocks (void);
-
-  void construct_ssa (void);
-
-  void do_construct_ssa (jit_block& block, size_t avisit_count);
-
-  void remove_dead ();
-
-  void place_releases (void);
-
-  void release_temp (jit_block& ablock, std::set<jit_value *>& temp);
-
-  void release_dead_phi (jit_block& ablock);
-
-  void simplify_phi (void);
-
-  void simplify_phi (jit_phi& phi);
-
-  void print_blocks (const std::string& header)
-  {
-    std::cout << "-------------------- " << header << " --------------------\n";
-    for (std::list<jit_block *>::iterator iter = blocks.begin ();
-         iter != blocks.end (); ++iter)
-      {
-        assert (*iter);
-        (*iter)->print (std::cout, 0);
-      }
-    std::cout << std::endl;
-  }
-
-  void print_dom (void)
-  {
-    std::cout << "-------------------- dom info --------------------\n";
-    for (std::list<jit_block *>::iterator iter = blocks.begin ();
-         iter != blocks.end (); ++iter)
-      {
-        assert (*iter);
-        (*iter)->print_dom (std::cout);
-      }
-    std::cout << std::endl;
-  }
-
-  bool breaking; // true if we are breaking OR continuing
-  block_list breaks;
-  block_list continues;
-
-  void finish_breaks (jit_block *dest, const block_list& lst);
-
-  // this case is much simpler, just convert from the jit ir to llvm
-  class
-  convert_llvm : public jit_ir_walker
-  {
-  public:
-    convert_llvm (jit_convert& jc) : jthis (jc) {}
-
-    llvm::Function *convert (llvm::Module *module,
-                             const std::vector<std::pair<std::string, bool> >& args,
-                             const std::list<jit_block *>& blocks,
-                             const std::list<jit_value *>& constants);
-
-#define JIT_METH(clname)                        \
-    virtual void visit (jit_ ## clname&);
-
-    JIT_VISIT_IR_CLASSES;
-
-#undef JIT_METH
-  private:
-    // name -> llvm argument
-    std::map<std::string, llvm::Value *> arguments;
-
-    void finish_phi (jit_phi *phi);
-
-    void visit (jit_value *jvalue)
-    {
-      return visit (*jvalue);
-    }
-
-    void visit (jit_value &jvalue)
-    {
-      jvalue.accept (*this);
-    }
-  private:
-    jit_convert &jthis;
-    llvm::Function *function;
-    llvm::BasicBlock *prelude;
-  };
-};
-
-class jit_info;
-
-class
-tree_jit
-{
-public:
-  tree_jit (void);
-
-  ~tree_jit (void);
-
-  bool execute (tree_simple_for_command& cmd, const octave_value& bounds);
-
-  bool execute (tree_while_command& cmd);
-
-  llvm::ExecutionEngine *get_engine (void) const { return engine; }
-
-  llvm::Module *get_module (void) const { return module; }
-
-  void optimize (llvm::Function *fn);
- private:
-  bool initialize (void);
-
-  size_t trip_count (const octave_value& bounds) const;
-
-  // FIXME: Temorary hack to test
-  typedef std::map<tree *, jit_info *> compiled_map;
-  llvm::Module *module;
-  llvm::PassManager *module_pass_manager;
-  llvm::FunctionPassManager *pass_manager;
-  llvm::ExecutionEngine *engine;
-};
-
-class
-jit_info
-{
-public:
-  // we use a pointer here so we don't have to include ov.h
-  typedef std::map<std::string, const octave_value *> vmap;
-
-  jit_info (tree_jit& tjit, tree& tee);
-
-  jit_info (tree_jit& tjit, tree& tee, const octave_value& for_bounds);
-
-  ~jit_info (void);
-
-  bool execute (const vmap& extra_vars = vmap ()) const;
-
-  bool match (const vmap& extra_vars = vmap ()) const;
-private:
-  typedef jit_convert::type_bound type_bound;
-  typedef jit_convert::type_bound_vector type_bound_vector;
-  typedef void (*jited_function)(octave_base_value**);
-
-  void initialize (tree_jit& tjit, jit_convert& conv);
-
-  octave_value find (const vmap& extra_vars, const std::string& vname) const;
-
-  llvm::ExecutionEngine *engine;
-  jited_function function;
-  llvm::Function *llvm_function;
-
-  std::vector<std::pair<std::string, bool> > arguments;
-  type_bound_vector bounds;
-};
-
-#endif
-#endif
--- a/src/siglist.c	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,232 +0,0 @@
-/*
-
-Copyright (C) 2000-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <signal.h>
-
-#include "siglist.h"
-
-/* The following is all borrowed from Emacs.  */
-
-#if ! (defined HAVE_STRSIGNAL || HAVE_DECL_SYS_SIGLIST)
-
-static char *my_sys_siglist[NSIG];
-
-#ifdef sys_siglist
-#undef sys_siglist
-#endif
-#define sys_siglist my_sys_siglist
-
-#endif
-
-void
-init_signals (void)
-{
-#if ! (defined HAVE_STRSIGNAL || HAVE_DECL_SYS_SIGLIST)
-
-  static int initialized = 0;
-
-  if (! initialized)
-    {
-      initialized = 1;
-
-# ifdef SIGABRT
-      sys_siglist[SIGABRT] = "Aborted";
-# endif
-# ifdef SIGAIO
-      sys_siglist[SIGAIO] = "LAN I/O interrupt";
-# endif
-# ifdef SIGALRM
-      sys_siglist[SIGALRM] = "Alarm clock";
-# endif
-# ifdef SIGBUS
-      sys_siglist[SIGBUS] = "Bus error";
-# endif
-# ifdef SIGCLD
-      sys_siglist[SIGCLD] = "Child status changed";
-# endif
-# ifdef SIGCHLD
-      sys_siglist[SIGCHLD] = "Child status changed";
-# endif
-# ifdef SIGCONT
-      sys_siglist[SIGCONT] = "Continued";
-# endif
-# ifdef SIGDANGER
-      sys_siglist[SIGDANGER] = "Swap space dangerously low";
-# endif
-# ifdef SIGDGNOTIFY
-      sys_siglist[SIGDGNOTIFY] = "Notification message in queue";
-# endif
-# ifdef SIGEMT
-      sys_siglist[SIGEMT] = "Emulation trap";
-# endif
-# ifdef SIGFPE
-      sys_siglist[SIGFPE] = "Arithmetic exception";
-# endif
-# ifdef SIGFREEZE
-      sys_siglist[SIGFREEZE] = "SIGFREEZE";
-# endif
-# ifdef SIGGRANT
-      sys_siglist[SIGGRANT] = "Monitor mode granted";
-# endif
-# ifdef SIGHUP
-      sys_siglist[SIGHUP] = "Hangup";
-# endif
-# ifdef SIGILL
-      sys_siglist[SIGILL] = "Illegal instruction";
-# endif
-# ifdef SIGINT
-      sys_siglist[SIGINT] = "Interrupt";
-# endif
-# ifdef SIGIO
-      sys_siglist[SIGIO] = "I/O possible";
-# endif
-# ifdef SIGIOINT
-      sys_siglist[SIGIOINT] = "I/O intervention required";
-# endif
-# ifdef SIGIOT
-      sys_siglist[SIGIOT] = "IOT trap";
-# endif
-# ifdef SIGKILL
-      sys_siglist[SIGKILL] = "Killed";
-# endif
-# ifdef SIGLOST
-      sys_siglist[SIGLOST] = "Resource lost";
-# endif
-# ifdef SIGLWP
-      sys_siglist[SIGLWP] = "SIGLWP";
-# endif
-# ifdef SIGMSG
-      sys_siglist[SIGMSG] = "Monitor mode data available";
-# endif
-# ifdef SIGPHONE
-      sys_siglist[SIGWIND] = "SIGPHONE";
-# endif
-# ifdef SIGPIPE
-      sys_siglist[SIGPIPE] = "Broken pipe";
-# endif
-# ifdef SIGPOLL
-      sys_siglist[SIGPOLL] = "Pollable event occurred";
-# endif
-# ifdef SIGPROF
-      sys_siglist[SIGPROF] = "Profiling timer expired";
-# endif
-# ifdef SIGPTY
-      sys_siglist[SIGPTY] = "PTY I/O interrupt";
-# endif
-# ifdef SIGPWR
-      sys_siglist[SIGPWR] = "Power-fail restart";
-# endif
-# ifdef SIGQUIT
-      sys_siglist[SIGQUIT] = "Quit";
-# endif
-# ifdef SIGRETRACT
-      sys_siglist[SIGRETRACT] = "Need to relinguish monitor mode";
-# endif
-# ifdef SIGSAK
-      sys_siglist[SIGSAK] = "Secure attention";
-# endif
-# ifdef SIGSEGV
-      sys_siglist[SIGSEGV] = "Segmentation violation";
-# endif
-# ifdef SIGSOUND
-      sys_siglist[SIGSOUND] = "Sound completed";
-# endif
-# ifdef SIGSTOP
-      sys_siglist[SIGSTOP] = "Stopped (signal)";
-# endif
-# ifdef SIGSTP
-      sys_siglist[SIGSTP] = "Stopped (user)";
-# endif
-# ifdef SIGSYS
-      sys_siglist[SIGSYS] = "Bad argument to system call";
-# endif
-# ifdef SIGTERM
-      sys_siglist[SIGTERM] = "Terminated";
-# endif
-# ifdef SIGTHAW
-      sys_siglist[SIGTHAW] = "SIGTHAW";
-# endif
-# ifdef SIGTRAP
-      sys_siglist[SIGTRAP] = "Trace/breakpoint trap";
-# endif
-# ifdef SIGTSTP
-      sys_siglist[SIGTSTP] = "Stopped (user)";
-# endif
-# ifdef SIGTTIN
-      sys_siglist[SIGTTIN] = "Stopped (tty input)";
-# endif
-# ifdef SIGTTOU
-      sys_siglist[SIGTTOU] = "Stopped (tty output)";
-# endif
-# ifdef SIGURG
-      sys_siglist[SIGURG] = "Urgent I/O condition";
-# endif
-# ifdef SIGUSR1
-      sys_siglist[SIGUSR1] = "User defined signal 1";
-# endif
-# ifdef SIGUSR2
-      sys_siglist[SIGUSR2] = "User defined signal 2";
-# endif
-# ifdef SIGVTALRM
-      sys_siglist[SIGVTALRM] = "Virtual timer expired";
-# endif
-# ifdef SIGWAITING
-      sys_siglist[SIGWAITING] = "Process's LWPs are blocked";
-# endif
-# ifdef SIGWINCH
-      sys_siglist[SIGWINCH] = "Window size changed";
-# endif
-# ifdef SIGWIND
-      sys_siglist[SIGWIND] = "SIGWIND";
-# endif
-# ifdef SIGXCPU
-      sys_siglist[SIGXCPU] = "CPU time limit exceeded";
-# endif
-# ifdef SIGXFSZ
-      sys_siglist[SIGXFSZ] = "File size limit exceeded";
-# endif
-    }
-
-#endif
-}
-
-#if ! defined (HAVE_STRSIGNAL)
-
-char *
-strsignal (int code)
-{
-  char *signame = "";
-
-  if (0 <= code && code < NSIG)
-    {
-      /* Cast to suppress warning if the table has const char *.  */
-      signame = (char *) sys_siglist[code];
-    }
-
-  return signame;
-}
-
-#endif
--- a/src/siglist.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/*
-
-Copyright (C) 2000-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#if !defined (octave_siglist_h)
-#define octave_siglist_h 1
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-/* This is borrowed from Emacs.  */
-
-#if ! defined (HAVE_DECL_SYS_SIGLIST)
-extern char *sys_siglist[];
-#endif
-
-extern void init_signals (void);
-
-#if ! defined (HAVE_STRSIGNAL)
-extern char *strsignal (int);
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
--- a/src/sparse-xdiv.cc	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,633 +0,0 @@
-/*
-
-Copyright (C) 2004-2012 David Bateman
-Copyright (C) 1998-2004 Andy Adler
-
-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/>.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <cassert>
-
-#include "Array-util.h"
-#include "oct-cmplx.h"
-#include "quit.h"
-#include "error.h"
-#include "lo-ieee.h"
-
-#include "dSparse.h"
-#include "dDiagMatrix.h"
-#include "CSparse.h"
-#include "CDiagMatrix.h"
-#include "oct-spparms.h"
-#include "sparse-xdiv.h"
-
-static void
-solve_singularity_warning (double rcond)
-{
-  warning ("matrix singular to machine precision, rcond = %g", rcond);
-  warning ("attempting to find minimum norm solution");
-}
-
-template <class T1, class T2>
-bool
-mx_leftdiv_conform (const T1& a, const T2& b)
-{
-  octave_idx_type a_nr = a.rows ();
-  octave_idx_type b_nr = b.rows ();
-
-  if (a_nr != b_nr)
-    {
-      octave_idx_type a_nc = a.cols ();
-      octave_idx_type b_nc = b.cols ();
-
-      gripe_nonconformant ("operator \\", a_nr, a_nc, b_nr, b_nc);
-      return false;
-    }
-
-  return true;
-}
-
-#define INSTANTIATE_MX_LEFTDIV_CONFORM(T1, T2) \
-  template bool mx_leftdiv_conform (const T1&, const T2&)
-
-INSTANTIATE_MX_LEFTDIV_CONFORM (SparseMatrix, SparseMatrix);
-INSTANTIATE_MX_LEFTDIV_CONFORM (SparseMatrix, SparseComplexMatrix);
-INSTANTIATE_MX_LEFTDIV_CONFORM (SparseComplexMatrix, SparseMatrix);
-INSTANTIATE_MX_LEFTDIV_CONFORM (SparseComplexMatrix, SparseComplexMatrix);
-INSTANTIATE_MX_LEFTDIV_CONFORM (SparseMatrix, Matrix);
-INSTANTIATE_MX_LEFTDIV_CONFORM (SparseMatrix, ComplexMatrix);
-INSTANTIATE_MX_LEFTDIV_CONFORM (SparseComplexMatrix, Matrix);
-INSTANTIATE_MX_LEFTDIV_CONFORM (SparseComplexMatrix, ComplexMatrix);
-INSTANTIATE_MX_LEFTDIV_CONFORM (DiagMatrix, SparseMatrix);
-INSTANTIATE_MX_LEFTDIV_CONFORM (DiagMatrix, SparseComplexMatrix);
-INSTANTIATE_MX_LEFTDIV_CONFORM (ComplexDiagMatrix, SparseMatrix);
-INSTANTIATE_MX_LEFTDIV_CONFORM (ComplexDiagMatrix, SparseComplexMatrix);
-
-template <class T1, class T2>
-bool
-mx_div_conform (const T1& a, const T2& b)
-{
-  octave_idx_type a_nc = a.cols ();
-  octave_idx_type b_nc = b.cols ();
-
-  if (a_nc != b_nc)
-    {
-      octave_idx_type a_nr = a.rows ();
-      octave_idx_type b_nr = b.rows ();
-
-      gripe_nonconformant ("operator /", a_nr, a_nc, b_nr, b_nc);
-      return false;
-    }
-
-  return true;
-}
-
-#define INSTANTIATE_MX_DIV_CONFORM(T1, T2) \
-  template bool mx_div_conform (const T1&, const T2&)
-
-INSTANTIATE_MX_DIV_CONFORM (SparseMatrix, SparseMatrix);
-INSTANTIATE_MX_DIV_CONFORM (SparseMatrix, SparseComplexMatrix);
-INSTANTIATE_MX_DIV_CONFORM (SparseComplexMatrix, SparseMatrix);
-INSTANTIATE_MX_DIV_CONFORM (SparseComplexMatrix, SparseComplexMatrix);
-INSTANTIATE_MX_DIV_CONFORM (Matrix, SparseMatrix);
-INSTANTIATE_MX_DIV_CONFORM (Matrix, SparseComplexMatrix);
-INSTANTIATE_MX_DIV_CONFORM (ComplexMatrix, SparseMatrix);
-INSTANTIATE_MX_DIV_CONFORM (ComplexMatrix, SparseComplexMatrix);
-INSTANTIATE_MX_DIV_CONFORM (SparseMatrix, DiagMatrix);
-INSTANTIATE_MX_DIV_CONFORM (SparseMatrix, ComplexDiagMatrix);
-INSTANTIATE_MX_DIV_CONFORM (SparseComplexMatrix, DiagMatrix);
-INSTANTIATE_MX_DIV_CONFORM (SparseComplexMatrix, ComplexDiagMatrix);
-
-// Right division functions.  X / Y = X * inv (Y) = (inv (Y') * X')'
-//
-//                  Y / X:   m   cm   sm  scm
-//                   +--   +---+----+----+----+
-//   sparse matrix         | 1 |  3 |  5 |  7 |
-//                         +---+----+----+----+
-//   sparse complex_matrix | 2 |  4 |  6 |  8 |
-//                         +---+----+----+----+
-//   diagonal matrix                |  9 | 11 |
-//                                  +----+----+
-//   complex diag. matrix           | 10 | 12 |
-//                                  +----+----+
-
-// -*- 1 -*-
-Matrix
-xdiv (const Matrix& a, const SparseMatrix& b, MatrixType &typ)
-{
-  if (! mx_div_conform (a, b))
-    return Matrix ();
-
-  Matrix atmp = a.transpose ();
-  SparseMatrix btmp = b.transpose ();
-  MatrixType btyp = typ.transpose ();
-
-  octave_idx_type info;
-  double rcond = 0.0;
-  Matrix result = btmp.solve (btyp, atmp, info, rcond,
-                              solve_singularity_warning);
-
-  typ = btyp.transpose ();
-  return result.transpose ();
-}
-
-// -*- 2 -*-
-ComplexMatrix
-xdiv (const Matrix& a, const SparseComplexMatrix& b, MatrixType &typ)
-{
-  if (! mx_div_conform (a, b))
-    return ComplexMatrix ();
-
-  Matrix atmp = a.transpose ();
-  SparseComplexMatrix btmp = b.hermitian ();
-  MatrixType btyp = typ.transpose ();
-
-  octave_idx_type info;
-  double rcond = 0.0;
-  ComplexMatrix result
-    = btmp.solve (btyp, atmp, info, rcond, solve_singularity_warning);
-
-  typ = btyp.transpose ();
-  return result.hermitian ();
-}
-
-// -*- 3 -*-
-ComplexMatrix
-xdiv (const ComplexMatrix& a, const SparseMatrix& b, MatrixType &typ)
-{
-  if (! mx_div_conform (a, b))
-    return ComplexMatrix ();
-
-  ComplexMatrix atmp = a.hermitian ();
-  SparseMatrix btmp = b.transpose ();
-  MatrixType btyp = typ.transpose ();
-
-  octave_idx_type info;
-  double rcond = 0.0;
-  ComplexMatrix result
-    = btmp.solve (btyp, atmp, info, rcond, solve_singularity_warning);
-
-  typ = btyp.transpose ();
-  return result.hermitian ();
-}
-
-// -*- 4 -*-
-ComplexMatrix
-xdiv (const ComplexMatrix& a, const SparseComplexMatrix& b, MatrixType &typ)
-{
-  if (! mx_div_conform (a, b))
-    return ComplexMatrix ();
-
-  ComplexMatrix atmp = a.hermitian ();
-  SparseComplexMatrix btmp = b.hermitian ();
-  MatrixType btyp = typ.transpose ();
-
-  octave_idx_type info;
-  double rcond = 0.0;
-  ComplexMatrix result
-    = btmp.solve (btyp, atmp, info, rcond, solve_singularity_warning);
-
-  typ = btyp.transpose ();
-  return result.hermitian ();
-}
-
-// -*- 5 -*-
-SparseMatrix
-xdiv (const SparseMatrix& a, const SparseMatrix& b, MatrixType &typ)
-{
-  if (! mx_div_conform (a, b))
-    return SparseMatrix ();
-
-  SparseMatrix atmp = a.transpose ();
-  SparseMatrix btmp = b.transpose ();
-  MatrixType btyp = typ.transpose ();
-
-  octave_idx_type info;
-  double rcond = 0.0;
-  SparseMatrix result = btmp.solve (btyp, atmp, info, rcond,
-                                    solve_singularity_warning);
-
-  typ = btyp.transpose ();
-  return result.transpose ();
-}
-
-// -*- 6 -*-
-SparseComplexMatrix
-xdiv (const SparseMatrix& a, const SparseComplexMatrix& b, MatrixType &typ)
-{
-  if (! mx_div_conform (a, b))
-    return SparseComplexMatrix ();
-
-  SparseMatrix atmp = a.transpose ();
-  SparseComplexMatrix btmp = b.hermitian ();
-  MatrixType btyp = typ.transpose ();
-
-  octave_idx_type info;
-  double rcond = 0.0;
-  SparseComplexMatrix result
-    = btmp.solve (btyp, atmp, info, rcond, solve_singularity_warning);
-
-  typ = btyp.transpose ();
-  return result.hermitian ();
-}
-
-// -*- 7 -*-
-SparseComplexMatrix
-xdiv (const SparseComplexMatrix& a, const SparseMatrix& b, MatrixType &typ)
-{
-  if (! mx_div_conform (a, b))
-    return SparseComplexMatrix ();
-
-  SparseComplexMatrix atmp = a.hermitian ();
-  SparseMatrix btmp = b.transpose ();
-  MatrixType btyp = typ.transpose ();
-
-  octave_idx_type info;
-  double rcond = 0.0;
-  SparseComplexMatrix result
-    = btmp.solve (btyp, atmp, info, rcond, solve_singularity_warning);
-
-  typ = btyp.transpose ();
-  return result.hermitian ();
-}
-
-// -*- 8 -*-
-SparseComplexMatrix
-xdiv (const SparseComplexMatrix& a, const SparseComplexMatrix& b, MatrixType &typ)
-{
-  if (! mx_div_conform (a, b))
-    return SparseComplexMatrix ();
-
-  SparseComplexMatrix atmp = a.hermitian ();
-  SparseComplexMatrix btmp = b.hermitian ();
-  MatrixType btyp = typ.transpose ();
-
-  octave_idx_type info;
-  double rcond = 0.0;
-  SparseComplexMatrix result
-    = btmp.solve (btyp, atmp, info, rcond, solve_singularity_warning);
-
-  typ = btyp.transpose ();
-  return result.hermitian ();
-}
-
-template <typename RT, typename SM, typename DM>
-RT do_rightdiv_sm_dm (const SM& a, const DM& d)
-{
-  const octave_idx_type d_nr = d.rows ();
-
-  const octave_idx_type a_nr = a.rows ();
-  const octave_idx_type a_nc = a.cols ();
-
-  using std::min;
-  const octave_idx_type nc = min (d_nr, a_nc);
-
-  if ( ! mx_div_conform (a, d))
-    return RT ();
-
-  const octave_idx_type nz = a.nnz ();
-  RT r (a_nr, nc, nz);
-
-  typedef typename DM::element_type DM_elt_type;
-  const DM_elt_type zero = DM_elt_type ();
-
-  octave_idx_type k_result = 0;
-  for (octave_idx_type j = 0; j < nc; ++j)
-    {
-      octave_quit ();
-      const DM_elt_type s = d.dgelem (j);
-      const octave_idx_type colend = a.cidx (j+1);
-      r.xcidx (j) = k_result;
-      if (s != zero)
-        for (octave_idx_type k = a.cidx (j); k < colend; ++k)
-          {
-            r.xdata (k_result) = a.data (k) / s;
-            r.xridx (k_result) = a.ridx (k);
-            ++k_result;
-          }
-    }
-  r.xcidx (nc) = k_result;
-
-  r.maybe_compress (true);
-  return r;
-}
-
-// -*- 9 -*-
-SparseMatrix
-xdiv (const SparseMatrix& a, const DiagMatrix& b, MatrixType &)
-{
-  return do_rightdiv_sm_dm<SparseMatrix> (a, b);
-}
-
-// -*- 10 -*-
-SparseComplexMatrix
-xdiv (const SparseMatrix& a, const ComplexDiagMatrix& b, MatrixType &)
-{
-  return do_rightdiv_sm_dm<SparseComplexMatrix> (a, b);
-}
-
-// -*- 11 -*-
-SparseComplexMatrix
-xdiv (const SparseComplexMatrix& a, const DiagMatrix& b, MatrixType &)
-{
-  return do_rightdiv_sm_dm<SparseComplexMatrix> (a, b);
-}
-
-// -*- 12 -*-
-SparseComplexMatrix
-xdiv (const SparseComplexMatrix& a, const ComplexDiagMatrix& b, MatrixType &)
-{
-  return do_rightdiv_sm_dm<SparseComplexMatrix> (a, b);
-}
-
-// Funny element by element division operations.
-//
-//       op2 \ op1:   s   cs
-//            +--   +---+----+
-//   matrix         | 1 |  3 |
-//                  +---+----+
-//   complex_matrix | 2 |  4 |
-//                  +---+----+
-
-Matrix
-x_el_div (double a, const SparseMatrix& b)
-{
-  octave_idx_type nr = b.rows ();
-  octave_idx_type nc = b.cols ();
-
-  Matrix result;
-  if (a == 0.)
-    result = Matrix (nr, nc, octave_NaN);
-  else if (a > 0.)
-    result = Matrix (nr, nc, octave_Inf);
-  else
-    result = Matrix (nr, nc, -octave_Inf);
-
-
-  for (octave_idx_type j = 0; j < nc; j++)
-    for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++)
-      {
-        octave_quit ();
-        result.elem (b.ridx (i), j) = a / b.data (i);
-      }
-
-  return result;
-}
-
-ComplexMatrix
-x_el_div (double a, const SparseComplexMatrix& b)
-{
-  octave_idx_type nr = b.rows ();
-  octave_idx_type nc = b.cols ();
-
-  ComplexMatrix  result (nr, nc, Complex (octave_NaN, octave_NaN));
-
-  for (octave_idx_type j = 0; j < nc; j++)
-    for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++)
-      {
-        octave_quit ();
-        result.elem (b.ridx (i), j) = a / b.data (i);
-      }
-
-  return result;
-}
-
-ComplexMatrix
-x_el_div (const Complex a, const SparseMatrix& b)
-{
-  octave_idx_type nr = b.rows ();
-  octave_idx_type nc = b.cols ();
-
-  ComplexMatrix result (nr, nc, (a / 0.0));
-
-  for (octave_idx_type j = 0; j < nc; j++)
-    for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++)
-      {
-        octave_quit ();
-        result.elem (b.ridx (i), j) = a / b.data (i);
-      }
-
-  return result;
-}
-
-ComplexMatrix
-x_el_div (const Complex a, const SparseComplexMatrix& b)
-{
-  octave_idx_type nr = b.rows ();
-  octave_idx_type nc = b.cols ();
-
-  ComplexMatrix result (nr, nc, (a / 0.0));
-
-  for (octave_idx_type j = 0; j < nc; j++)
-    for (octave_idx_type i = b.cidx (j); i < b.cidx (j+1); i++)
-      {
-        octave_quit ();
-        result.elem (b.ridx (i), j) = a / b.data (i);
-      }
-
-  return result;
-}
-
-// Left division functions.  X \ Y = inv (X) * Y
-//
-//               Y  \  X :   sm  scm  dm  dcm
-//                   +--   +---+----+
-//   matrix                | 1 |  5 |
-//                         +---+----+
-//   complex_matrix        | 2 |  6 |
-//                         +---+----+----+----+
-//   sparse matrix         | 3 |  7 |  9 | 11 |
-//                         +---+----+----+----+
-//   sparse complex_matrix | 4 |  8 | 10 | 12 |
-//                         +---+----+----+----+
-
-// -*- 1 -*-
-Matrix
-xleftdiv (const SparseMatrix& a, const Matrix& b, MatrixType &typ)
-{
-  if (! mx_leftdiv_conform (a, b))
-    return Matrix ();
-
-  octave_idx_type info;
-  double rcond = 0.0;
-  return a.solve (typ, b, info, rcond, solve_singularity_warning);
-}
-
-// -*- 2 -*-
-ComplexMatrix
-xleftdiv (const SparseMatrix& a, const ComplexMatrix& b, MatrixType &typ)
-{
-  if (! mx_leftdiv_conform (a, b))
-    return ComplexMatrix ();
-
-  octave_idx_type info;
-  double rcond = 0.0;
-  return a.solve (typ, b, info, rcond, solve_singularity_warning);
-}
-
-// -*- 3 -*-
-SparseMatrix
-xleftdiv (const SparseMatrix& a, const SparseMatrix& b, MatrixType &typ)
-{
-  if (! mx_leftdiv_conform (a, b))
-    return SparseMatrix ();
-
-  octave_idx_type info;
-  double rcond = 0.0;
-  return a.solve (typ, b, info, rcond, solve_singularity_warning);
-}
-
-// -*- 4 -*-
-SparseComplexMatrix
-xleftdiv (const SparseMatrix& a, const SparseComplexMatrix& b, MatrixType &typ)
-{
-  if (! mx_leftdiv_conform (a, b))
-    return SparseComplexMatrix ();
-
-  octave_idx_type info;
-  double rcond = 0.0;
-  return a.solve (typ, b, info, rcond, solve_singularity_warning);
-}
-
-// -*- 5 -*-
-ComplexMatrix
-xleftdiv (const SparseComplexMatrix& a, const Matrix& b, MatrixType &typ)
-{
-  if (! mx_leftdiv_conform (a, b))
-    return ComplexMatrix ();
-
-  octave_idx_type info;
-  double rcond = 0.0;
-  return a.solve (typ, b, info, rcond, solve_singularity_warning);
-}
-
-// -*- 6 -*-
-ComplexMatrix
-xleftdiv (const SparseComplexMatrix& a, const ComplexMatrix& b, MatrixType &typ)
-{
-  if (! mx_leftdiv_conform (a, b))
-    return ComplexMatrix ();
-
-  octave_idx_type info;
-  double rcond = 0.0;
-  return a.solve (typ, b, info, rcond, solve_singularity_warning);
-}
-
-// -*- 7 -*-
-SparseComplexMatrix
-xleftdiv (const SparseComplexMatrix& a, const SparseMatrix& b, MatrixType &typ)
-{
-  if (! mx_leftdiv_conform (a, b))
-    return SparseComplexMatrix ();
-
-  octave_idx_type info;
-  double rcond = 0.0;
-  return a.solve (typ, b, info, rcond, solve_singularity_warning);
-}
-
-// -*- 8 -*-
-SparseComplexMatrix
-xleftdiv (const SparseComplexMatrix& a, const SparseComplexMatrix& b,
-          MatrixType &typ)
-{
-  if (! mx_leftdiv_conform (a, b))
-    return SparseComplexMatrix ();
-
-  octave_idx_type info;
-  double rcond = 0.0;
-  return a.solve (typ, b, info, rcond, solve_singularity_warning);
-}
-
-template <typename RT, typename DM, typename SM>
-RT do_leftdiv_dm_sm (const DM& d, const SM& a)
-{
-  const octave_idx_type a_nr = a.rows ();
-  const octave_idx_type a_nc = a.cols ();
-
-  const octave_idx_type d_nc = d.cols ();
-
-  using std::min;
-  const octave_idx_type nr = min (d_nc, a_nr);
-
-  if ( ! mx_leftdiv_conform (d, a))
-    return RT ();
-
-  const octave_idx_type nz = a.nnz ();
-  RT r (nr, a_nc, nz);
-
-  typedef typename DM::element_type DM_elt_type;
-  const DM_elt_type zero = DM_elt_type ();
-
-  octave_idx_type k_result = 0;
-  for (octave_idx_type j = 0; j < a_nc; ++j)
-    {
-      octave_quit ();
-      const octave_idx_type colend = a.cidx (j+1);
-      r.xcidx (j) = k_result;
-      for (octave_idx_type k = a.cidx (j); k < colend; ++k)
-        {
-          const octave_idx_type i = a.ridx (k);
-          if (i < nr)
-            {
-              const DM_elt_type s = d.dgelem (i);
-              if (s != zero)
-                {
-                  r.xdata (k_result) = a.data (k) / s;
-                  r.xridx (k_result) = i;
-                  ++k_result;
-                }
-            }
-        }
-    }
-  r.xcidx (a_nc) = k_result;
-
-  r.maybe_compress (true);
-  return r;
-}
-
-// -*- 9 -*-
-SparseMatrix
-xleftdiv (const DiagMatrix& d, const SparseMatrix& a,  MatrixType&)
-{
-  return do_leftdiv_dm_sm<SparseMatrix> (d, a);
-}
-
-// -*- 10 -*-
-SparseComplexMatrix
-xleftdiv (const DiagMatrix& d, const SparseComplexMatrix& a,  MatrixType&)
-{
-  return do_leftdiv_dm_sm<SparseComplexMatrix> (d, a);
-}
-
-// -*- 11 -*-
-SparseComplexMatrix
-xleftdiv (const ComplexDiagMatrix& d, const SparseMatrix& a,  MatrixType&)
-{
-  return do_leftdiv_dm_sm<SparseComplexMatrix> (d, a);
-}
-
-// -*- 12 -*-
-SparseComplexMatrix
-xleftdiv (const ComplexDiagMatrix& d, const SparseComplexMatrix& a,  MatrixType&)
-{
-  return do_leftdiv_dm_sm<SparseComplexMatrix> (d, a);
-}
--- a/src/sparse-xdiv.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-/*
-
-Copyright (C) 2004-2012 David Bateman
-Copyright (C) 1998-2004 Andy Adler
-
-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/>.
-
-*/
-
-#if !defined (octave_sparse_xdiv_h)
-#define octave_sparse_xdiv_h 1
-
-#include "oct-cmplx.h"
-#include "MatrixType.h"
-
-class DiagMatrix;
-class ComplexDiagMatrix;
-class SparseMatrix;
-class SparseComplexMatrix;
-
-extern Matrix xdiv (const Matrix& a, const SparseMatrix& b, MatrixType &typ);
-extern ComplexMatrix xdiv (const Matrix& a, const SparseComplexMatrix& b,
-                           MatrixType &typ);
-extern ComplexMatrix xdiv (const ComplexMatrix& a, const SparseMatrix& b,
-                           MatrixType &typ);
-extern ComplexMatrix xdiv (const ComplexMatrix& a,
-                           const SparseComplexMatrix& b, MatrixType &typ);
-
-extern SparseMatrix xdiv (const SparseMatrix& a, const SparseMatrix& b,
-                          MatrixType &typ);
-extern SparseComplexMatrix xdiv (const SparseMatrix& a,
-                                 const SparseComplexMatrix& b, MatrixType &typ);
-extern SparseComplexMatrix xdiv (const SparseComplexMatrix& a,
-                                 const SparseMatrix& b, MatrixType &typ);
-extern SparseComplexMatrix xdiv (const SparseComplexMatrix& a,
-                                 const SparseComplexMatrix& b, MatrixType &typ);
-
-extern SparseMatrix xdiv (const SparseMatrix& a,
-                          const DiagMatrix& b, MatrixType &typ);
-extern SparseComplexMatrix xdiv (const SparseMatrix& a,
-                                 const ComplexDiagMatrix& b, MatrixType &typ);
-extern SparseComplexMatrix xdiv (const SparseComplexMatrix& a,
-                                 const DiagMatrix& b, MatrixType &typ);
-extern SparseComplexMatrix xdiv (const SparseComplexMatrix& a,
-                                 const ComplexDiagMatrix& b, MatrixType &typ);
-
-extern Matrix x_el_div (double a, const SparseMatrix& b);
-extern ComplexMatrix x_el_div (double a, const SparseComplexMatrix& b);
-extern ComplexMatrix x_el_div (const Complex a, const SparseMatrix& b);
-extern ComplexMatrix x_el_div (const Complex a,
-                               const SparseComplexMatrix& b);
-
-extern Matrix xleftdiv (const SparseMatrix& a, const Matrix& b,
-                        MatrixType& typ);
-extern ComplexMatrix xleftdiv (const SparseMatrix& a, const ComplexMatrix& b,
-                               MatrixType &typ);
-extern ComplexMatrix xleftdiv (const SparseComplexMatrix& a, const Matrix& b,
-                               MatrixType &typ);
-extern ComplexMatrix xleftdiv (const SparseComplexMatrix& a,
-                               const ComplexMatrix& b, MatrixType &typ);
-
-extern SparseMatrix xleftdiv (const SparseMatrix& a, const SparseMatrix& b,
-                              MatrixType &typ);
-extern SparseComplexMatrix xleftdiv (const SparseMatrix& a,
-                                     const SparseComplexMatrix& b, MatrixType &typ);
-extern SparseComplexMatrix xleftdiv (const SparseComplexMatrix& a,
-                                     const SparseMatrix& b, MatrixType &typ);
-extern SparseComplexMatrix xleftdiv (const SparseComplexMatrix& a,
-                                     const SparseComplexMatrix& b, MatrixType &typ);
-
-extern SparseMatrix xleftdiv (const DiagMatrix&, const SparseMatrix&, MatrixType&);
-extern SparseComplexMatrix xleftdiv (const ComplexDiagMatrix&, const SparseMatrix&,
-                                     MatrixType&);
-extern SparseComplexMatrix xleftdiv (const DiagMatrix&, const SparseComplexMatrix&,
-                                     MatrixType&);
-extern SparseComplexMatrix xleftdiv (const ComplexDiagMatrix&, const SparseComplexMatrix&,
-                                     MatrixType&);
-
-#endif
--- a/src/sparse-xpow.cc	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,730 +0,0 @@
-/*
-
-Copyright (C) 2004-2012 David Bateman
-Copyright (C) 1998-2004 Andy Adler
-
-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/>.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <cassert>
-#include <climits>
-
-#include "Array-util.h"
-#include "oct-cmplx.h"
-#include "quit.h"
-
-#include "error.h"
-#include "oct-obj.h"
-#include "utils.h"
-
-#include "dSparse.h"
-#include "CSparse.h"
-#include "ov-re-sparse.h"
-#include "ov-cx-sparse.h"
-#include "sparse-xpow.h"
-
-static inline int
-xisint (double x)
-{
-  return (D_NINT (x) == x
-          && ((x >= 0 && x < INT_MAX)
-              || (x <= 0 && x > INT_MIN)));
-}
-
-
-// Safer pow functions. Only two make sense for sparse matrices, the
-// others should all promote to full matrices.
-
-octave_value
-xpow (const SparseMatrix& a, double b)
-{
-  octave_value retval;
-
-  octave_idx_type nr = a.rows ();
-  octave_idx_type nc = a.cols ();
-
-  if (nr == 0 || nc == 0 || nr != nc)
-    error ("for A^b, A must be a square matrix");
-  else
-    {
-      if (static_cast<int> (b) == b)
-        {
-          int btmp = static_cast<int> (b);
-          if (btmp == 0)
-            {
-              SparseMatrix tmp = SparseMatrix (nr, nr, nr);
-              for (octave_idx_type i = 0; i < nr; i++)
-                {
-                  tmp.data (i) = 1.0;
-                  tmp.ridx (i) = i;
-                }
-              for (octave_idx_type i = 0; i < nr + 1; i++)
-                tmp.cidx (i) = i;
-
-              retval = tmp;
-            }
-          else
-            {
-              SparseMatrix atmp;
-              if (btmp < 0)
-                {
-                  btmp = -btmp;
-
-                  octave_idx_type info;
-                  double rcond = 0.0;
-                  MatrixType mattyp (a);
-
-                  atmp = a.inverse (mattyp, info, rcond, 1);
-
-                  if (info == -1)
-                    warning ("inverse: matrix singular to machine\
- precision, rcond = %g", rcond);
-                }
-              else
-                atmp = a;
-
-              SparseMatrix result (atmp);
-
-              btmp--;
-
-              while (btmp > 0)
-                {
-                  if (btmp & 1)
-                    result = result * atmp;
-
-                  btmp >>= 1;
-
-                  if (btmp > 0)
-                    atmp = atmp * atmp;
-                }
-
-              retval = result;
-            }
-        }
-      else
-        error ("use full(a) ^ full(b)");
-    }
-
-  return retval;
-}
-
-octave_value
-xpow (const SparseComplexMatrix& a, double b)
-{
-  octave_value retval;
-
-  octave_idx_type nr = a.rows ();
-  octave_idx_type nc = a.cols ();
-
-  if (nr == 0 || nc == 0 || nr != nc)
-    error ("for A^b, A must be a square matrix");
-  else
-    {
-      if (static_cast<int> (b) == b)
-        {
-          int btmp = static_cast<int> (b);
-          if (btmp == 0)
-            {
-              SparseMatrix tmp = SparseMatrix (nr, nr, nr);
-              for (octave_idx_type i = 0; i < nr; i++)
-                {
-                  tmp.data (i) = 1.0;
-                  tmp.ridx (i) = i;
-                }
-              for (octave_idx_type i = 0; i < nr + 1; i++)
-                tmp.cidx (i) = i;
-
-              retval = tmp;
-            }
-          else
-            {
-              SparseComplexMatrix atmp;
-              if (btmp < 0)
-                {
-                  btmp = -btmp;
-
-                  octave_idx_type info;
-                  double rcond = 0.0;
-                  MatrixType mattyp (a);
-
-                  atmp = a.inverse (mattyp, info, rcond, 1);
-
-                  if (info == -1)
-                    warning ("inverse: matrix singular to machine\
- precision, rcond = %g", rcond);
-                }
-              else
-                atmp = a;
-
-              SparseComplexMatrix result (atmp);
-
-              btmp--;
-
-              while (btmp > 0)
-                {
-                  if (btmp & 1)
-                    result = result * atmp;
-
-                  btmp >>= 1;
-
-                  if (btmp > 0)
-                    atmp = atmp * atmp;
-                }
-
-              retval = result;
-            }
-        }
-      else
-        error ("use full(a) ^ full(b)");
-    }
-
-  return retval;
-}
-
-// Safer pow functions that work elementwise for matrices.
-//
-//       op2 \ op1:   s   m   cs   cm
-//            +--   +---+---+----+----+
-//   scalar   |     | * | 3 |  * |  9 |
-//                  +---+---+----+----+
-//   matrix         | 1 | 4 |  7 | 10 |
-//                  +---+---+----+----+
-//   complex_scalar | * | 5 |  * | 11 |
-//                  +---+---+----+----+
-//   complex_matrix | 2 | 6 |  8 | 12 |
-//                  +---+---+----+----+
-//
-//   * -> not needed.
-
-// FIXME -- these functions need to be fixed so that things
-// like
-//
-//   a = -1; b = [ 0, 0.5, 1 ]; r = a .^ b
-//
-// and
-//
-//   a = -1; b = [ 0, 0.5, 1 ]; for i = 1:3, r(i) = a .^ b(i), end
-//
-// produce identical results.  Also, it would be nice if -1^0.5
-// produced a pure imaginary result instead of a complex number with a
-// small real part.  But perhaps that's really a problem with the math
-// library...
-
-// -*- 1 -*-
-octave_value
-elem_xpow (double a, const SparseMatrix& b)
-{
-  octave_value retval;
-
-  octave_idx_type nr = b.rows ();
-  octave_idx_type nc = b.cols ();
-
-  double d1, d2;
-
-  if (a < 0.0 && ! b.all_integers (d1, d2))
-    {
-      Complex atmp (a);
-      ComplexMatrix result (nr, nc);
-
-      for (octave_idx_type j = 0; j < nc; j++)
-        {
-          for (octave_idx_type i = 0; i < nr; i++)
-            {
-              octave_quit ();
-              result(i, j) = std::pow (atmp, b(i,j));
-            }
-        }
-
-      retval = result;
-    }
-  else
-    {
-      Matrix result (nr, nc);
-
-      for (octave_idx_type j = 0; j < nc; j++)
-        {
-          for (octave_idx_type i = 0; i < nr; i++)
-            {
-              octave_quit ();
-              result(i, j) = std::pow (a, b(i,j));
-            }
-        }
-
-      retval = result;
-    }
-
-  return retval;
-}
-
-// -*- 2 -*-
-octave_value
-elem_xpow (double a, const SparseComplexMatrix& b)
-{
-  octave_idx_type nr = b.rows ();
-  octave_idx_type nc = b.cols ();
-
-  Complex atmp (a);
-  ComplexMatrix result (nr, nc);
-
-  for (octave_idx_type j = 0; j < nc; j++)
-    {
-      for (octave_idx_type i = 0; i < nr; i++)
-        {
-          octave_quit ();
-          result(i, j) = std::pow (atmp, b(i,j));
-        }
-    }
-
-  return result;
-}
-
-// -*- 3 -*-
-octave_value
-elem_xpow (const SparseMatrix& a, double b)
-{
-  // FIXME What should a .^ 0 give?? Matlab gives a
-  // sparse matrix with same structure as a, which is strictly
-  // incorrect. Keep compatiability.
-
-  octave_value retval;
-
-  octave_idx_type nz = a.nnz ();
-
-  if (b <= 0.0)
-    {
-      octave_idx_type nr = a.rows ();
-      octave_idx_type nc = a.cols ();
-
-      if (static_cast<int> (b) != b && a.any_element_is_negative ())
-        {
-          ComplexMatrix result (nr, nc, Complex (std::pow (0.0, b)));
-
-          // FIXME -- avoid apparent GNU libm bug by
-          // converting A and B to complex instead of just A.
-          Complex btmp (b);
-
-          for (octave_idx_type j = 0; j < nc; j++)
-            for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)
-              {
-                octave_quit ();
-
-                Complex atmp (a.data (i));
-
-                result(a.ridx (i), j) = std::pow (atmp, btmp);
-              }
-
-          retval = octave_value (result);
-        }
-      else
-        {
-          Matrix result (nr, nc, (std::pow (0.0, b)));
-
-          for (octave_idx_type j = 0; j < nc; j++)
-            for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)
-              {
-                octave_quit ();
-                result(a.ridx (i), j) = std::pow (a.data (i), b);
-              }
-
-          retval = octave_value (result);
-        }
-    }
-  else if (static_cast<int> (b) != b && a.any_element_is_negative ())
-    {
-      SparseComplexMatrix result (a);
-
-      for (octave_idx_type i = 0; i < nz; i++)
-        {
-          octave_quit ();
-
-          // FIXME -- avoid apparent GNU libm bug by
-          // converting A and B to complex instead of just A.
-
-          Complex atmp (a.data (i));
-          Complex btmp (b);
-
-          result.data (i) = std::pow (atmp, btmp);
-        }
-
-      result.maybe_compress (true);
-
-      retval = result;
-    }
-  else
-    {
-      SparseMatrix result (a);
-
-      for (octave_idx_type i = 0; i < nz; i++)
-        {
-          octave_quit ();
-          result.data (i) = std::pow (a.data (i), b);
-        }
-
-      result.maybe_compress (true);
-
-      retval = result;
-    }
-
-  return retval;
-}
-
-// -*- 4 -*-
-octave_value
-elem_xpow (const SparseMatrix& a, const SparseMatrix& b)
-{
-  octave_value retval;
-
-  octave_idx_type nr = a.rows ();
-  octave_idx_type nc = a.cols ();
-
-  octave_idx_type b_nr = b.rows ();
-  octave_idx_type b_nc = b.cols ();
-
-  if (nr != b_nr || nc != b_nc)
-    {
-      gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc);
-      return octave_value ();
-    }
-
-  int convert_to_complex = 0;
-  for (octave_idx_type j = 0; j < nc; j++)
-    for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)
-      {
-        if (a.data(i) < 0.0)
-          {
-            double btmp = b (a.ridx (i), j);
-            if (static_cast<int> (btmp) != btmp)
-              {
-                convert_to_complex = 1;
-                goto done;
-              }
-          }
-      }
-
-done:
-
-  // This is a dumb operator for sparse matrices anyway, and there is
-  // no sensible way to handle the 0.^0 versus the 0.^x cases. Therefore
-  // allocate a full matrix filled for the 0.^0 case and shrink it later
-  // as needed
-
-  if (convert_to_complex)
-    {
-      SparseComplexMatrix complex_result (nr, nc, Complex (1.0, 0.0));
-
-      for (octave_idx_type j = 0; j < nc; j++)
-        {
-          for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)
-            {
-              octave_quit ();
-              complex_result.xelem (a.ridx (i), j) =
-                std::pow (Complex (a.data (i)), Complex (b(a.ridx (i), j)));
-            }
-        }
-      complex_result.maybe_compress (true);
-      retval = complex_result;
-    }
-  else
-    {
-      SparseMatrix result (nr, nc, 1.0);
-
-      for (octave_idx_type j = 0; j < nc; j++)
-        {
-          for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)
-            {
-              octave_quit ();
-              result.xelem (a.ridx (i), j) = std::pow (a.data (i),
-                                                       b(a.ridx (i), j));
-            }
-        }
-      result.maybe_compress (true);
-      retval = result;
-    }
-
-  return retval;
-}
-
-// -*- 5 -*-
-octave_value
-elem_xpow (const SparseMatrix& a, const Complex& b)
-{
-  octave_value retval;
-
-  if (b == 0.0)
-    // Can this case ever happen, due to automatic retyping with maybe_mutate?
-    retval = octave_value (NDArray (a.dims (), 1));
-  else
-    {
-      octave_idx_type nz = a.nnz ();
-      SparseComplexMatrix result (a);
-
-      for (octave_idx_type i = 0; i < nz; i++)
-        {
-          octave_quit ();
-          result.data (i) = std::pow (Complex (a.data (i)), b);
-        }
-
-      result.maybe_compress (true);
-
-      retval = result;
-    }
-
-  return retval;
-}
-
-// -*- 6 -*-
-octave_value
-elem_xpow (const SparseMatrix& a, const SparseComplexMatrix& b)
-{
-  octave_idx_type nr = a.rows ();
-  octave_idx_type nc = a.cols ();
-
-  octave_idx_type b_nr = b.rows ();
-  octave_idx_type b_nc = b.cols ();
-
-  if (nr != b_nr || nc != b_nc)
-    {
-      gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc);
-      return octave_value ();
-    }
-
-  SparseComplexMatrix result (nr, nc, Complex (1.0, 0.0));
-  for (octave_idx_type j = 0; j < nc; j++)
-    {
-      for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)
-        {
-          octave_quit ();
-          result.xelem (a.ridx(i), j) = std::pow (a.data (i), b(a.ridx (i), j));
-        }
-    }
-
-  result.maybe_compress (true);
-
-  return result;
-}
-
-// -*- 7 -*-
-octave_value
-elem_xpow (const Complex& a, const SparseMatrix& b)
-{
-  octave_idx_type nr = b.rows ();
-  octave_idx_type nc = b.cols ();
-
-  ComplexMatrix result (nr, nc);
-
-  for (octave_idx_type j = 0; j < nc; j++)
-    {
-      for (octave_idx_type i = 0; i < nr; i++)
-        {
-          octave_quit ();
-          double btmp = b (i, j);
-          if (xisint (btmp))
-            result (i, j) = std::pow (a, static_cast<int> (btmp));
-          else
-            result (i, j) = std::pow (a, btmp);
-        }
-    }
-
-  return result;
-}
-
-// -*- 8 -*-
-octave_value
-elem_xpow (const Complex& a, const SparseComplexMatrix& b)
-{
-  octave_idx_type nr = b.rows ();
-  octave_idx_type nc = b.cols ();
-
-  ComplexMatrix result (nr, nc);
-  for (octave_idx_type j = 0; j < nc; j++)
-    for (octave_idx_type i = 0; i < nr; i++)
-      {
-        octave_quit ();
-        result (i, j) = std::pow (a, b (i, j));
-      }
-
-  return result;
-}
-
-// -*- 9 -*-
-octave_value
-elem_xpow (const SparseComplexMatrix& a, double b)
-{
-  octave_value retval;
-
-  if (b <= 0)
-    {
-      octave_idx_type nr = a.rows ();
-      octave_idx_type nc = a.cols ();
-
-      ComplexMatrix result (nr, nc, Complex (std::pow (0.0, b)));
-
-      if (xisint (b))
-        {
-          for (octave_idx_type j = 0; j < nc; j++)
-            for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)
-              {
-                octave_quit ();
-                result (a.ridx (i), j) =
-                  std::pow (a.data (i), static_cast<int> (b));
-              }
-        }
-      else
-        {
-          for (octave_idx_type j = 0; j < nc; j++)
-            for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)
-              {
-                octave_quit ();
-                result (a.ridx (i), j) = std::pow (a.data (i), b);
-              }
-        }
-
-      retval = result;
-    }
-  else
-    {
-      octave_idx_type nz = a.nnz ();
-
-      SparseComplexMatrix result (a);
-
-      if (xisint (b))
-        {
-          for (octave_idx_type i = 0; i < nz; i++)
-            {
-              octave_quit ();
-              result.data (i) = std::pow (a.data (i), static_cast<int> (b));
-            }
-        }
-      else
-        {
-          for (octave_idx_type i = 0; i < nz; i++)
-            {
-              octave_quit ();
-              result.data (i) = std::pow (a.data (i), b);
-            }
-        }
-
-      result.maybe_compress (true);
-
-      retval = result;
-    }
-
-  return retval;
-}
-
-// -*- 10 -*-
-octave_value
-elem_xpow (const SparseComplexMatrix& a, const SparseMatrix& b)
-{
-  octave_idx_type nr = a.rows ();
-  octave_idx_type nc = a.cols ();
-
-  octave_idx_type b_nr = b.rows ();
-  octave_idx_type b_nc = b.cols ();
-
-  if (nr != b_nr || nc != b_nc)
-    {
-      gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc);
-      return octave_value ();
-    }
-
-  SparseComplexMatrix result (nr, nc, Complex (1.0, 0.0));
-  for (octave_idx_type j = 0; j < nc; j++)
-    {
-      for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)
-        {
-          octave_quit ();
-          double btmp = b(a.ridx (i), j);
-          Complex tmp;
-
-          if (xisint (btmp))
-            result.xelem (a.ridx (i), j) = std::pow (a.data (i),
-                                              static_cast<int> (btmp));
-          else
-            result.xelem (a.ridx (i), j) = std::pow (a.data (i), btmp);
-        }
-    }
-
-  result.maybe_compress (true);
-
-  return result;
-}
-
-// -*- 11 -*-
-octave_value
-elem_xpow (const SparseComplexMatrix& a, const Complex& b)
-{
-  octave_value retval;
-
-  if (b == 0.0)
-    // Can this case ever happen, due to automatic retyping with maybe_mutate?
-    retval = octave_value (NDArray (a.dims (), 1));
-  else
-    {
-
-      octave_idx_type nz = a.nnz ();
-
-      SparseComplexMatrix result (a);
-
-      for (octave_idx_type i = 0; i < nz; i++)
-        {
-          octave_quit ();
-          result.data (i) = std::pow (a.data (i), b);
-        }
-
-      result.maybe_compress (true);
-
-      retval = result;
-    }
-
-  return retval;
-}
-
-// -*- 12 -*-
-octave_value
-elem_xpow (const SparseComplexMatrix& a, const SparseComplexMatrix& b)
-{
-  octave_idx_type nr = a.rows ();
-  octave_idx_type nc = a.cols ();
-
-  octave_idx_type b_nr = b.rows ();
-  octave_idx_type b_nc = b.cols ();
-
-  if (nr != b_nr || nc != b_nc)
-    {
-      gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc);
-      return octave_value ();
-    }
-
-  SparseComplexMatrix result (nr, nc, Complex (1.0, 0.0));
-  for (octave_idx_type j = 0; j < nc; j++)
-    {
-      for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)
-        {
-          octave_quit ();
-          result.xelem (a.ridx (i), j) = std::pow (a.data (i), b(a.ridx (i), j));
-        }
-    }
-  result.maybe_compress (true);
-
-  return result;
-}
--- a/src/sparse-xpow.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,57 +0,0 @@
-/*
-
-Copyright (C) 2004-2012 David Bateman
-Copyright (C) 1998-2004 Andy Adler
-
-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/>.
-
-*/
-
-#if !defined (octave_sparse_xpow_h)
-#define octave_sparse_xpow_h 1
-
-#include "oct-cmplx.h"
-
-class SparseMatrix;
-class SparseComplexMatrix;
-class octave_value;
-
-extern octave_value xpow (const SparseMatrix& a, double b);
-extern octave_value xpow (const SparseComplexMatrix& a, double b);
-
-extern octave_value elem_xpow (double a, const SparseMatrix& b);
-extern octave_value elem_xpow (double a, const SparseComplexMatrix& b);
-
-extern octave_value elem_xpow (const SparseMatrix& a, double b);
-extern octave_value elem_xpow (const SparseMatrix& a, const SparseMatrix& b);
-extern octave_value elem_xpow (const SparseMatrix& a, const Complex& b);
-extern octave_value elem_xpow (const SparseMatrix& a,
-                               const SparseComplexMatrix& b);
-
-extern octave_value elem_xpow (const Complex& a, const SparseMatrix& b);
-extern octave_value elem_xpow (const Complex& a,
-                               const SparseComplexMatrix& b);
-
-extern octave_value elem_xpow (const SparseComplexMatrix& a, double b);
-extern octave_value elem_xpow (const SparseComplexMatrix& a,
-                               const SparseMatrix& b);
-extern octave_value elem_xpow (const SparseComplexMatrix& a,
-                               const Complex& b);
-extern octave_value elem_xpow (const SparseComplexMatrix& a,
-                               const SparseComplexMatrix& b);
-
-#endif
--- a/src/token.cc	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,170 +0,0 @@
-/*
-
-Copyright (C) 1993-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <cassert>
-
-#include "error.h"
-#include "oct-obj.h"
-#include "symtab.h"
-#include "token.h"
-#include "utils.h"
-
-token::token (int l, int c)
-{
-  line_num = l;
-  column_num = c;
-  type_tag = generic_token;
-}
-
-token::token (const std::string& s, int l, int c)
-{
-  line_num = l;
-  column_num = c;
-  type_tag = string_token;
-  str = new std::string (s);
-}
-
-token::token (double d, const std::string& s, int l, int c)
-{
-  line_num = l;
-  column_num = c;
-  type_tag = double_token;
-  num = d;
-  orig_text = s;
-}
-
-token::token (end_tok_type t, int l, int c)
-{
-  line_num = l;
-  column_num = c;
-  type_tag = ettype_token;
-  et = t;
-}
-
-token::token (symbol_table::symbol_record *s, int l, int c)
-{
-  line_num = l;
-  column_num = c;
-  type_tag = sym_rec_token;
-  sr = s;
-}
-
-token::token (symbol_table::symbol_record *cls,
-              symbol_table::symbol_record *pkg, int l, int c)
-{
-  line_num = l;
-  column_num = c;
-  type_tag = meta_rec_token;
-  mc.cr = cls;
-  mc.pr = pkg;
-}
-
-token::token (symbol_table::symbol_record *mth,
-              symbol_table::symbol_record *cls,
-              symbol_table::symbol_record *pkg, int l, int c)
-{
-  line_num = l;
-  column_num = c;
-  type_tag = scls_rec_token;
-  sc.mr = mth;
-  sc.cr = cls;
-  sc.pr = pkg;
-}
-
-token::~token (void)
-{
-  if (type_tag == string_token)
-    delete str;
-}
-
-std::string
-token::text (void)
-{
-  assert (type_tag == string_token);
-  return *str;
-}
-
-double
-token::number (void)
-{
-  assert (type_tag == double_token);
-  return num;
-}
-
-token::end_tok_type
-token::ettype (void)
-{
-  assert (type_tag == ettype_token);
-  return et;
-}
-
-symbol_table::symbol_record *
-token::sym_rec (void)
-{
-  assert (type_tag == sym_rec_token);
-  return sr;
-}
-
-symbol_table::symbol_record *
-token::method_rec (void)
-{
-  assert (type_tag == scls_rec_token);
-  return sc.mr;
-}
-
-symbol_table::symbol_record *
-token::class_rec (void)
-{
-  assert (type_tag == scls_rec_token);
-  return sc.cr;
-}
-
-symbol_table::symbol_record *
-token::package_rec (void)
-{
-  assert (type_tag == scls_rec_token);
-  return sc.pr;
-}
-
-symbol_table::symbol_record *
-token::meta_class_rec (void)
-{
-  assert (type_tag == meta_rec_token);
-  return mc.cr;
-}
-
-symbol_table::symbol_record *
-token::meta_package_rec (void)
-{
-  assert (type_tag == meta_rec_token);
-  return mc.pr;
-}
-
-std::string
-token::text_rep (void)
-{
-  return orig_text;
-}
--- a/src/token.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,125 +0,0 @@
-/*
-
-Copyright (C) 1993-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#if !defined (octave_token_h)
-#define octave_token_h 1
-
-#include <string>
-
-class
-token
-{
-public:
-
-  enum token_type
-    {
-      generic_token,
-      string_token,
-      double_token,
-      ettype_token,
-      sym_rec_token,
-      scls_rec_token,
-      meta_rec_token
-    };
-
-  enum end_tok_type
-    {
-      simple_end,
-      classdef_end,
-      enumeration_end,
-      events_end,
-      for_end,
-      function_end,
-      if_end,
-      methods_end,
-      parfor_end,
-      properties_end,
-      switch_end,
-      while_end,
-      try_catch_end,
-      unwind_protect_end
-    };
-
-  token (int l = -1, int c = -1);
-  token (const std::string& s, int l = -1, int c = -1);
-  token (double d, const std::string& s = std::string (),
-         int l = -1, int c = -1);
-  token (end_tok_type t, int l = -1, int c = -1);
-  token (symbol_table::symbol_record *s, int l = -1, int c = -1);
-  token (symbol_table::symbol_record *cls,
-         symbol_table::symbol_record *pkg, int l = -1, int c = -1);
-  token (symbol_table::symbol_record *mth,
-         symbol_table::symbol_record *cls,
-         symbol_table::symbol_record *pkg, int l = -1, int c = -1);
-
-  ~token (void);
-
-  int line (void) { return line_num; }
-  int column (void) { return column_num; }
-
-  std::string text (void);
-  double number (void);
-  end_tok_type ettype (void);
-  symbol_table::symbol_record *sym_rec (void);
-
-  symbol_table::symbol_record *method_rec (void);
-  symbol_table::symbol_record *class_rec (void);
-  symbol_table::symbol_record *package_rec (void);
-
-  symbol_table::symbol_record *meta_class_rec (void);
-  symbol_table::symbol_record *meta_package_rec (void);
-
-  std::string text_rep (void);
-
-private:
-
-  // No copying!
-
-  token (const token& tok);
-
-  token& operator = (const token& tok);
-
-  int line_num;
-  int column_num;
-  token_type type_tag;
-  union
-    {
-      std::string *str;
-      double num;
-      end_tok_type et;
-      symbol_table::symbol_record *sr;
-      struct
-        {
-          symbol_table::symbol_record *mr;
-          symbol_table::symbol_record *cr;
-          symbol_table::symbol_record *pr;
-        } sc;
-      struct
-        {
-          symbol_table::symbol_record *cr;
-          symbol_table::symbol_record *pr;
-        } mc;
-    };
-  std::string orig_text;
-};
-
-#endif
--- a/src/txt-eng-ft.cc	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,669 +0,0 @@
-/*
-
-Copyright (C) 2009-2012 Michael Goffioul
-
-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/>.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#if defined (HAVE_FREETYPE)
-
-#if defined (HAVE_FONTCONFIG)
-#include <fontconfig/fontconfig.h>
-#endif
-
-#include <iostream>
-
-#include "singleton-cleanup.h"
-
-#include "error.h"
-#include "pr-output.h"
-#include "txt-eng-ft.h"
-
-// FIXME -- maybe issue at most one warning per glyph/font/size/weight
-// combination.
-
-static void
-gripe_missing_glyph (char c)
-{
-  warning_with_id ("Octave:missing-glyph",
-                   "ft_render: skipping missing glyph for character `%c'",
-                   c);
-}
-
-static void
-gripe_glyph_render (char c)
-{
-  warning_with_id ("Octave:glyph-render",
-                   "ft_render: unable to render glyph for character `%c'",
-                   c);
-}
-
-#ifdef _MSC_VER
-// This is just a trick to avoid multiply symbols definition.
-// PermMatrix.h contains a dllexport'ed Array<octave_idx_type>
-// that will make MSVC not to generate new instantiation and
-// use the imported one.
-#include "PermMatrix.h"
-#endif
-
-class
-ft_manager
-{
-public:
-  static bool instance_ok (void)
-    {
-      bool retval = true;
-
-      if (! instance)
-        {
-          instance = new ft_manager ();
-
-          if (instance)
-            singleton_cleanup_list::add (cleanup_instance);
-        }
-
-      if (! instance)
-        {
-          ::error ("unable to create ft_manager!");
-
-          retval = false;
-        }
-
-      return retval;
-    }
-
-  static void cleanup_instance (void) { delete instance; instance = 0; }
-
-  static FT_Face get_font (const std::string& name, const std::string& weight,
-                           const std::string& angle, double size)
-    { return (instance_ok ()
-              ? instance->do_get_font (name, weight, angle, size)
-              : 0); }
-
-private:
-
-  static ft_manager *instance;
-
-private:
-
-  // No copying!
-
-  ft_manager (const ft_manager&);
-
-  ft_manager& operator = (const ft_manager&);
-
-  ft_manager (void)
-    : library (), freetype_initialized (false), fontconfig_initialized (false)
-    {
-      if (FT_Init_FreeType (&library))
-        ::error ("unable to initialize freetype library");
-      else
-        freetype_initialized = true;
-
-#if defined (HAVE_FONTCONFIG)
-      if (! FcInit ())
-        ::error ("unable to initialize fontconfig library");
-      else
-        fontconfig_initialized = true;
-#endif
-    }
-
-  ~ft_manager (void)
-    {
-      if (freetype_initialized)
-        FT_Done_FreeType (library);
-
-#if defined (HAVE_FONTCONFIG)
-      // FIXME -- Skip the call to FcFini because it can trigger the
-      // assertion
-      //
-      //   octave: fccache.c:507: FcCacheFini: Assertion `fcCacheChains[i] == ((void *)0)' failed.
-      //
-      // if (fontconfig_initialized)
-      //   FcFini ();
-#endif
-    }
-
-
-  FT_Face do_get_font (const std::string& name, const std::string& weight,
-                       const std::string& angle, double size)
-    {
-      FT_Face retval = 0;
-
-      std::string file;
-
-#if defined (HAVE_FONTCONFIG)
-      if (fontconfig_initialized)
-        {
-          int fc_weight, fc_angle;
-
-          if (weight == "bold")
-            fc_weight = FC_WEIGHT_BOLD;
-          else if (weight == "light")
-            fc_weight = FC_WEIGHT_LIGHT;
-          else if (weight == "demi")
-            fc_weight = FC_WEIGHT_DEMIBOLD;
-          else
-            fc_weight = FC_WEIGHT_NORMAL;
-
-          if (angle == "italic")
-            fc_angle = FC_SLANT_ITALIC;
-          else if (angle == "oblique")
-            fc_angle = FC_SLANT_OBLIQUE;
-          else
-            fc_angle = FC_SLANT_ROMAN;
-
-          FcPattern *pat = FcPatternCreate ();
-
-          FcPatternAddString (pat, FC_FAMILY,
-                              (reinterpret_cast<const FcChar8*>
-                               (name == "*" ? "sans" : name.c_str ())));
-
-          FcPatternAddInteger (pat, FC_WEIGHT, fc_weight);
-          FcPatternAddInteger (pat, FC_SLANT, fc_angle);
-          FcPatternAddDouble (pat, FC_PIXEL_SIZE, size);
-
-          if (FcConfigSubstitute (0, pat, FcMatchPattern))
-            {
-              FcResult res;
-              FcPattern *match;
-
-              FcDefaultSubstitute (pat);
-              match = FcFontMatch (0, pat, &res);
-
-              // FIXME -- originally, this test also required that
-              // res != FcResultNoMatch.  Is that really needed?
-              if (match)
-                {
-                  unsigned char *tmp;
-
-                  FcPatternGetString (match, FC_FILE, 0, &tmp);
-                  file = reinterpret_cast<char*> (tmp);
-                }
-              else
-                ::warning ("could not match any font: %s-%s-%s-%g",
-                         name.c_str (), weight.c_str (), angle.c_str (),
-                         size);
-
-              if (match)
-                FcPatternDestroy (match);
-            }
-
-          FcPatternDestroy (pat);
-        }
-#endif
-
-      if (file.empty ())
-        {
-#ifdef __WIN32__
-          file = "C:/WINDOWS/Fonts/verdana.ttf";
-#else
-          // FIXME: find a "standard" font for UNIX platforms
-#endif
-        }
-
-      if (! file.empty () && FT_New_Face (library, file.c_str (), 0, &retval))
-        ::warning ("ft_manager: unable to load font: %s", file.c_str ());
-
-      return retval;
-    }
-
-private:
-  FT_Library library;
-  bool freetype_initialized;
-  bool fontconfig_initialized;
-};
-
-ft_manager* ft_manager::instance = 0;
-
-// ---------------------------------------------------------------------------
-
-ft_render::ft_render (void)
-    : text_processor (), face (0), bbox (1, 4, 0.0),
-      xoffset (0), yoffset (0), multiline_halign (0),
-      multiline_align_xoffsets (), mode (MODE_BBOX),
-      red (0), green (0), blue (0)
-{
-}
-
-ft_render::~ft_render (void)
-{
-  if (face)
-    FT_Done_Face (face);
-}
-
-void
-ft_render::set_font (const std::string& name, const std::string& weight,
-                     const std::string& angle, double size)
-{
-  if (face)
-    FT_Done_Face (face);
-
-  // FIXME: take "fontunits" into account
-  face = ft_manager::get_font (name, weight, angle, size);
-
-  if (face)
-    {
-      if (FT_Set_Char_Size (face, 0, size*64, 0, 0))
-        ::warning ("ft_render: unable to set font size to %d", size);
-    }
-  else
-    ::warning ("ft_render: unable to load appropriate font");
-}
-
-void
-ft_render::set_mode (int m)
-{
-  mode = m;
-
-  switch (mode)
-    {
-    case MODE_BBOX:
-      xoffset = yoffset = 0;
-      bbox = Matrix (1, 4, 0.0);
-      break;
-    case MODE_RENDER:
-      if (bbox.numel () != 4)
-        {
-          ::warning ("ft_render: invalid bounding box, cannot render");
-
-          xoffset = yoffset = 0;
-          pixels = uint8NDArray ();
-        }
-      else
-        {
-          pixels = uint8NDArray (dim_vector (4, bbox(2), bbox(3)),
-                                 static_cast<uint8_t> (0));
-          xoffset = 0;
-          yoffset = -bbox(1)-1;
-        }
-      break;
-    default:
-      ::error ("ft_render: invalid mode `%d'", mode);
-      break;
-    }
-}
-
-void
-ft_render::visit (text_element_string& e)
-{
-  if (face)
-    {
-      int line_index = 0;
-      FT_UInt box_line_width = 0;
-      std::string str = e.string_value ();
-      FT_UInt glyph_index, previous = 0;
-
-      if (mode == MODE_BBOX)
-        multiline_align_xoffsets.clear ();
-      else if (mode == MODE_RENDER)
-        xoffset += multiline_align_xoffsets[line_index];
-
-      for (size_t i = 0; i < str.length (); i++)
-        {
-          glyph_index = FT_Get_Char_Index (face, str[i]);
-
-          if (str[i] != '\n'
-              && (! glyph_index
-              || FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT)))
-            gripe_missing_glyph (str[i]);
-          else
-            {
-              switch (mode)
-                {
-                case MODE_RENDER:
-                  if (str[i] == '\n')
-                    {
-                    glyph_index = FT_Get_Char_Index (face, ' ');
-                    if (!glyph_index || FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT))
-                      {
-                        gripe_missing_glyph (' ');
-                      }
-                    else
-                      {
-                        line_index++;
-                        xoffset = multiline_align_xoffsets[line_index];
-                        yoffset -= (face->size->metrics.height >> 6);
-                      }
-                    }
-                  else if (FT_Render_Glyph (face->glyph, FT_RENDER_MODE_NORMAL))
-                    {
-                      gripe_glyph_render (str[i]);
-                    }
-                  else
-                    {
-                      FT_Bitmap& bitmap = face->glyph->bitmap;
-                      int x0, y0;
-
-                      if (previous)
-                        {
-                          FT_Vector delta;
-
-                          FT_Get_Kerning (face, previous, glyph_index, FT_KERNING_DEFAULT, &delta);
-                          xoffset += (delta.x >> 6);
-                        }
-
-                      x0 = xoffset+face->glyph->bitmap_left;
-                      y0 = yoffset+face->glyph->bitmap_top;
-
-                      // 'w' seems to have a negative -1
-                      // face->glyph->bitmap_left, this is so we don't
-                      // index out of bound, and assumes we we allocated
-                      // the right amount of horizontal space in the bbox.
-                      if (x0 < 0)
-                        x0 = 0;
-
-                      for (int r = 0; r < bitmap.rows; r++)
-                        for (int c = 0; c < bitmap.width; c++)
-                          {
-                            unsigned char pix = bitmap.buffer[r*bitmap.width+c];
-                            if (x0+c < 0 || x0+c >= pixels.dim2 ()
-                                || y0-r < 0 || y0-r >= pixels.dim3 ())
-                              {
-                                //::error ("out-of-bound indexing!!");
-                              }
-                            else if (pixels(3, x0+c, y0-r).value () == 0)
-                              {
-                                pixels(0, x0+c, y0-r) = red;
-                                pixels(1, x0+c, y0-r) = green;
-                                pixels(2, x0+c, y0-r) = blue;
-                                pixels(3, x0+c, y0-r) = pix;
-                              }
-                          }
-
-                      xoffset += (face->glyph->advance.x >> 6);
-                    }
-                  break;
-
-                case MODE_BBOX:
-                  if (str[i] == '\n')
-                    {
-                      glyph_index = FT_Get_Char_Index (face, ' ');
-                      if (! glyph_index
-                          || FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT))
-                      {
-                        gripe_missing_glyph (' ');
-                      }
-                    else
-                      {
-                        multiline_align_xoffsets.push_back (box_line_width);
-                        // Reset the pixel width for this newline, so we don't
-                        // allocate a bounding box larger than the horizontal
-                        // width of the multi-line
-                        box_line_width = 0;
-                        bbox(1) -= (face->size->metrics.height >> 6);
-                      }
-                    }
-                  else
-                    {
-                    // width
-                    if (previous)
-                      {
-                        FT_Vector delta;
-
-                        FT_Get_Kerning (face, previous, glyph_index,
-                                        FT_KERNING_DEFAULT, &delta);
-
-                        box_line_width += (delta.x >> 6);
-                      }
-
-                    box_line_width += (face->glyph->advance.x >> 6);
-
-                    int asc, desc;
-
-                    if (false /*tight*/)
-                      {
-                        desc = face->glyph->metrics.horiBearingY - face->glyph->metrics.height;
-                        asc = face->glyph->metrics.horiBearingY;
-                      }
-                    else
-                      {
-                        asc = face->size->metrics.ascender;
-                        desc = face->size->metrics.descender;
-                      }
-
-                    asc = yoffset + (asc >> 6);
-                    desc = yoffset + (desc >> 6);
-
-                    if (desc < bbox(1))
-                      {
-                        bbox(3) += (bbox(1) - desc);
-                        bbox(1) = desc;
-                      }
-                    if (asc > (bbox(3)+bbox(1)))
-                      bbox(3) = asc-bbox(1);
-                    if (bbox(2) < box_line_width)
-                      bbox(2) = box_line_width;
-                  }
-                  break;
-                }
-                if (str[i] == '\n')
-                  previous = 0;
-                else
-                  previous = glyph_index;
-            }
-        }
-      if (mode == MODE_BBOX)
-        {
-          /* Push last the width associated with the last line */
-          multiline_align_xoffsets.push_back (box_line_width);
-
-          for (unsigned int i = 0; i < multiline_align_xoffsets.size (); i++)
-            {
-            /* Center align */
-            if (multiline_halign == 1)
-              multiline_align_xoffsets[i] = (bbox(2) - multiline_align_xoffsets[i])/2;
-            /* Right align */
-            else if (multiline_halign == 2)
-              multiline_align_xoffsets[i] = (bbox(2) - multiline_align_xoffsets[i]);
-            /* Left align */
-            else
-              multiline_align_xoffsets[i] = 0;
-            }
-        }
-    }
-}
-
-void
-ft_render::reset (void)
-{
-  set_mode (MODE_BBOX);
-  set_color (Matrix (1, 3, 0.0));
-}
-
-void
-ft_render::set_color (Matrix c)
-{
-  if (c.numel () == 3)
-    {
-      red = static_cast<uint8_t> (c(0)*255);
-      green = static_cast<uint8_t> (c(1)*255);
-      blue = static_cast<uint8_t> (c(2)*255);
-    }
-  else
-    ::warning ("ft_render::set_color: invalid color");
-}
-
-uint8NDArray
-ft_render::render (text_element* elt, Matrix& box, int rotation)
-{
-  set_mode (MODE_BBOX);
-  elt->accept (*this);
-  box = bbox;
-
-  set_mode (MODE_RENDER);
-  if (pixels.numel () > 0)
-    {
-      elt->accept (*this);
-
-      switch (rotation)
-        {
-        case ROTATION_0:
-          break;
-        case ROTATION_90:
-            {
-              Array<octave_idx_type> perm (dim_vector (3, 1));
-              perm(0) = 0;
-              perm(1) = 2;
-              perm(2) = 1;
-              pixels = pixels.permute (perm);
-
-              Array<idx_vector> idx (dim_vector (3, 1));
-              idx(0) = idx_vector (':');
-              idx(1) = idx_vector (pixels.dim2 ()-1, -1, -1);
-              idx(2) = idx_vector (':');
-              pixels = uint8NDArray (pixels.index (idx));
-            }
-          break;
-        case ROTATION_180:
-            {
-              Array<idx_vector> idx (dim_vector (3, 1));
-              idx(0) = idx_vector (':');
-              idx(1) = idx_vector (pixels.dim2 ()-1, -1, -1);
-              idx(2)=  idx_vector (pixels.dim3 ()-1, -1, -1);
-              pixels = uint8NDArray (pixels.index (idx));
-            }
-          break;
-        case ROTATION_270:
-            {
-              Array<octave_idx_type> perm (dim_vector (3, 1));
-              perm(0) = 0;
-              perm(1) = 2;
-              perm(2) = 1;
-              pixels = pixels.permute (perm);
-
-              Array<idx_vector> idx (dim_vector (3, 1));
-              idx(0) = idx_vector (':');
-              idx(1) = idx_vector (':');
-              idx(2) = idx_vector (pixels.dim3 ()-1, -1, -1);
-              pixels = uint8NDArray (pixels.index (idx));
-            }
-          break;
-        }
-    }
-
-  return pixels;
-}
-
-Matrix
-ft_render::get_extent (text_element *elt, double rotation)
-{
-  set_mode (MODE_BBOX);
-  elt->accept (*this);
-
-  Matrix extent (1, 2, 0.0);
-
-  switch (rotation_to_mode (rotation))
-    {
-    case ROTATION_0:
-    case ROTATION_180:
-      extent(0) = bbox(2);
-      extent(1) = bbox(3);
-      break;
-    case ROTATION_90:
-    case ROTATION_270:
-      extent(0) = bbox(3);
-      extent(1) = bbox(2);
-    }
-
-  return extent;
-}
-
-Matrix
-ft_render::get_extent (const std::string& txt, double rotation)
-{
-  text_element *elt = text_parser_none ().parse (txt);
-  Matrix extent = get_extent (elt, rotation);
-  delete elt;
-
-  return extent;
-}
-
-int
-ft_render::rotation_to_mode (double rotation) const
-{
-  if (rotation == 0.0)
-    return ROTATION_0;
-  else if (rotation == 90.0)
-    return ROTATION_90;
-  else if (rotation == 180.0)
-    return ROTATION_180;
-  else if (rotation == 270.0)
-    return ROTATION_270;
-  else
-    return ROTATION_0;
-}
-
-void
-ft_render::text_to_pixels (const std::string& txt,
-                           uint8NDArray& pixels_, Matrix& box,
-                           int halign, int valign, double rotation)
-{
-  // FIXME: clip "rotation" between 0 and 360
-  int rot_mode = rotation_to_mode (rotation);
-
-  multiline_halign = halign;
-
-  text_element *elt = text_parser_none ().parse (txt);
-  pixels_ = render (elt, box, rot_mode);
-  delete elt;
-
-  if (pixels_.numel () == 0)
-    {
-      // nothing to render
-      return;
-    }
-
-  switch (halign)
-    {
-    default: box(0) = 0; break;
-    case 1: box(0) = -box(2)/2; break;
-    case 2: box(0) = -box(2); break;
-    }
-  switch (valign)
-    {
-    default: box(1) = 0; break;
-    case 1: box(1) = -box(3)/2; break;
-    case 2: box(1) = -box(3); break;
-    case 3: break;
-    }
-
-  switch (rot_mode)
-    {
-    case ROTATION_90:
-      std::swap (box(0), box(1));
-      std::swap (box(2), box(3));
-      box(0) = -box(0)-box(2);
-      break;
-    case ROTATION_180:
-      box(0) = -box(0)-box(2);
-      box(1) = -box(1)-box(3);
-      break;
-    case ROTATION_270:
-      std::swap (box(0), box(1));
-      std::swap (box(2), box(3));
-      box(1) = -box(1)-box(3);
-      break;
-    }
-}
-
-#endif // HAVE_FREETYPE
--- a/src/txt-eng-ft.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,107 +0,0 @@
-/*
-
-Copyright (C) 2009-2012 Michael Goffioul
-
-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/>.
-
-*/
-
-#if ! defined (txt_eng_ft_h)
-#define txt_eng_ft_h 1
-
-#if HAVE_FREETYPE
-
-#include <vector>
-
-#include <ft2build.h>
-#include FT_FREETYPE_H
-
-#include <dMatrix.h>
-#include <uint8NDArray.h>
-#include "txt-eng.h"
-
-class
-OCTINTERP_API
-ft_render : public text_processor
-{
-public:
-  enum {
-      MODE_BBOX   = 0,
-      MODE_RENDER = 1
-  };
-
-  enum {
-      ROTATION_0   = 0,
-      ROTATION_90  = 1,
-      ROTATION_180 = 2,
-      ROTATION_270 = 3
-  };
-
-public:
-  ft_render (void);
-
-  ~ft_render (void);
-
-  void visit (text_element_string& e);
-
-  void reset (void);
-
-  uint8NDArray get_pixels (void) const { return pixels; }
-
-  Matrix get_boundingbox (void) const { return bbox; }
-
-  uint8NDArray render (text_element* elt, Matrix& box,
-                       int rotation = ROTATION_0);
-
-  Matrix get_extent (text_element *elt, double rotation = 0.0);
-  Matrix get_extent (const std::string& txt, double rotation = 0.0);
-
-  void set_font (const std::string& name, const std::string& weight,
-                 const std::string& angle, double size);
-
-  void set_color (Matrix c);
-
-  void set_mode (int m);
-
-  void text_to_pixels (const std::string& txt,
-                       uint8NDArray& pixels_, Matrix& bbox,
-                       int halign, int valign, double rotation);
-
-private:
-  int rotation_to_mode (double rotation) const;
-
-  // No copying!
-
-  ft_render (const ft_render&);
-
-  ft_render& operator = (const ft_render&);
-
-private:
-  FT_Face face;
-  Matrix bbox;
-  uint8NDArray pixels;
-  int xoffset;
-  int yoffset;
-  int multiline_halign;
-  std::vector<int> multiline_align_xoffsets;
-  int mode;
-  uint8_t red, green, blue;
-};
-
-#endif // HAVE_FREETYPE
-
-#endif
--- a/src/txt-eng.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,193 +0,0 @@
-/*
-
-Copyright (C) 2009-2012 Michael Goffioul
-
-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/>.
-
-*/
-
-#if ! defined (txt_eng_h)
-#define txt_eng_h 1
-
-#include "base-list.h"
-
-class text_element;
-class text_element_string;
-class text_element_list;
-class text_subscript_element;
-class text_superscript_element;
-
-class text_processor;
-
-class
-OCTINTERP_API
-text_element
-{
-public:
-  text_element (void) { }
-
-  virtual ~text_element (void) { }
-
-  virtual void accept (text_processor& p) = 0;
-
-private:
-  text_element (const text_element&);
-};
-
-class
-OCTINTERP_API
-text_element_string : public text_element
-{
-public:
-  text_element_string (const std::string& s = "")
-      : text_element (), str (s) { }
-
-  ~text_element_string (void) { }
-
-  std::string string_value (void) const { return str; }
-
-  void accept (text_processor& p);
-
-private:
-  std::string str;
-
-private:
-  text_element_string (const text_element_string &);
-};
-
-class
-OCTINTERP_API
-text_element_list :
-    public text_element,
-    public octave_base_list<text_element *>
-{
-public:
-  text_element_list (void)
-      : text_element (), octave_base_list<text_element*> () { }
-
-  ~text_element_list (void)
-    {
-      while (! empty ())
-        {
-          iterator it = begin ();
-          delete (*it);
-          erase (it);
-        }
-    }
-
-  void accept (text_processor& p);
-};
-
-class
-OCTINTERP_API
-text_subscript_element : public text_element_list
-{
-public:
-  text_subscript_element (void)
-      : text_element_list () { }
-
-  ~text_subscript_element (void) { }
-
-  void accept (text_processor& p);
-};
-
-class
-OCTINTERP_API
-text_superscript_element : public text_element_list
-{
-public:
-  text_superscript_element (void)
-      : text_element_list () { }
-
-  ~text_superscript_element (void) { }
-
-  void accept (text_processor& p);
-};
-
-class
-OCTINTERP_API
-text_processor
-{
-public:
-  virtual void visit (text_element_string& e) = 0;
-
-  virtual void visit (text_element_list& e)
-    {
-      for (text_element_list::iterator it = e.begin ();
-           it != e.end (); ++it)
-        {
-          (*it)->accept (*this);
-        }
-    }
-
-  virtual void visit (text_subscript_element& e)
-    { visit (dynamic_cast<text_element_list&> (e)); }
-
-  virtual void visit (text_superscript_element& e)
-    { visit (dynamic_cast<text_element_list&> (e)); }
-
-  virtual void reset (void) { }
-
-protected:
-  text_processor (void) { }
-
-  virtual ~text_processor (void) { }
-};
-
-#define TEXT_ELEMENT_ACCEPT(cls) \
-inline void \
-cls::accept (text_processor& p) \
-{ p.visit (*this); }
-
-TEXT_ELEMENT_ACCEPT(text_element_string)
-TEXT_ELEMENT_ACCEPT(text_element_list)
-TEXT_ELEMENT_ACCEPT(text_subscript_element)
-TEXT_ELEMENT_ACCEPT(text_superscript_element)
-
-class
-OCTINTERP_API
-text_parser
-{
-public:
-  text_parser (void) { }
-
-  virtual ~text_parser (void) { }
-
-  virtual text_element* parse (const std::string& s) = 0;
-};
-
-class
-OCTINTERP_API
-text_parser_none : public text_parser
-{
-public:
-  text_parser_none (void) : text_parser () { }
-
-  ~text_parser_none (void) { }
-
-  // FIXME: is it possible to use reference counting to manage the
-  // memory for the object returned by the text parser?  That would be
-  // preferable to having to know when and where to delete the object it
-  // creates...
-
-  text_element* parse (const std::string& s)
-    {
-      return new text_element_string (s);
-    }
-};
-
-#endif
--- a/src/unwind-prot.cc	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-/*
-
-Copyright (C) 1993-2012 John W. Eaton
-Copyright (C) 2009 VZLU Prague
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <cstddef>
-#include <cstring>
-
-#include "error.h"
-#include "unwind-prot.h"
-#include "utils.h"
-
-void unwind_protect_safe::gripe_exception (void)
-{
-  // FIXME: can this throw an exception?
-  error ("internal: unhandled exception in unwind_protect handler");
-}
--- a/src/unwind-prot.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,344 +0,0 @@
-/*
-
-Copyright (C) 1993-2012 John W. Eaton
-Copyright (C) 2009-2010 VZLU Prague
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#if !defined (octave_unwind_prot_h)
-#define octave_unwind_prot_h 1
-
-#include <cstddef>
-
-#include <string>
-#include <memory>
-
-// This class allows registering cleanup actions.
-class
-OCTINTERP_API
-unwind_protect
-{
-public:
-
-  // A generic unwind_protect element. Knows how to run itself and discard itself.
-  // Also, contains a pointer to the next element.
-  class elem
-  {
-    elem *next;
-
-  public:
-    elem (void) : next (0) { }
-
-    virtual void run (void) { }
-
-    virtual ~elem (void) { }
-
-    friend class unwind_protect;
-
-  private:
-
-    // No copying!
-
-    elem (const elem&);
-
-    elem& operator = (const elem&);
-  };
-
-  // An element that merely runs a void (*)(void) function.
-
-  class fcn_elem : public elem
-  {
-  public:
-    fcn_elem (void (*fptr) (void))
-      : e_fptr (fptr) { }
-
-    void run (void) { e_fptr (); }
-
-  private:
-    void (*e_fptr) (void);
-  };
-
-  // An element that stores a variable of type T along with a void (*) (T)
-  // function pointer, and calls the function with the parameter.
-
-  template <class T>
-  class fcn_arg_elem : public elem
-  {
-  public:
-    fcn_arg_elem (void (*fcn) (T), T arg)
-      : e_fcn (fcn), e_arg (arg) { }
-
-    void run (void) { e_fcn (e_arg); }
-
-  private:
-
-    // No copying!
-
-    fcn_arg_elem (const fcn_arg_elem&);
-
-    fcn_arg_elem& operator = (const fcn_arg_elem&);
-
-    void (*e_fcn) (T);
-    T e_arg;
-  };
-
-  // An element that stores a variable of type T along with a void (*) (const T&)
-  // function pointer, and calls the function with the parameter.
-
-  template <class T>
-  class fcn_crefarg_elem : public elem
-  {
-  public:
-    fcn_crefarg_elem (void (*fcn) (const T&), T arg)
-      : e_fcn (fcn), e_arg (arg) { }
-
-    void run (void) { e_fcn (e_arg); }
-
-  private:
-    void (*e_fcn) (const T&);
-    T e_arg;
-  };
-
-  // An element for calling a member function.
-
-  template <class T>
-  class method_elem : public elem
-  {
-  public:
-    method_elem (T *obj, void (T::*method) (void))
-      : e_obj (obj), e_method (method) { }
-
-    void run (void) { (e_obj->*e_method) (); }
-
-  private:
-
-    T *e_obj;
-    void (T::*e_method) (void);
-
-    // No copying!
-
-    method_elem (const method_elem&);
-
-    method_elem operator = (const method_elem&);
-  };
-
-  // An element that stores arbitrary variable, and restores it.
-
-  template <class T>
-  class restore_var_elem : public elem
-  {
-  public:
-    restore_var_elem (T& ref, const T& val)
-      : e_ptr (&ref), e_val (val) { }
-
-    void run (void) { *e_ptr = e_val; }
-
-  private:
-
-    // No copying!
-
-    restore_var_elem (const restore_var_elem&);
-
-    restore_var_elem& operator = (const restore_var_elem&);
-
-    T *e_ptr, e_val;
-  };
-
-  // Deletes a class allocated using new.
-
-  template <class T>
-  class delete_ptr_elem : public elem
-  {
-  public:
-    delete_ptr_elem (T *ptr)
-      : e_ptr (ptr) { }
-
-    void run (void) { delete e_ptr; }
-
-  private:
-
-    T *e_ptr;
-
-    // No copying!
-
-    delete_ptr_elem (const delete_ptr_elem&);
-
-    delete_ptr_elem operator = (const delete_ptr_elem&);
-  };
-
-  unwind_protect (void) : head () { }
-
-  void add (elem *new_elem)
-    {
-      new_elem->next = head;
-      head = new_elem;
-    }
-
-  // For backward compatibility.
-  void add (void (*fcn) (void *), void *ptr = 0)
-    {
-      add (new fcn_arg_elem<void *> (fcn, ptr));
-    }
-
-  // Call to void func (void).
-  void add_fcn (void (*fcn) (void))
-    {
-      add (new fcn_elem (fcn));
-    }
-
-  // Call to void func (T).
-  template <class T>
-  void add_fcn (void (*action) (T), T val)
-    {
-      add (new fcn_arg_elem<T> (action, val));
-    }
-
-  // Call to void func (const T&).
-  template <class T>
-  void add_fcn (void (*action) (const T&), T val)
-    {
-      add (new fcn_crefarg_elem<T> (action, val));
-    }
-
-  // Call to T::method (void).
-  template <class T>
-  void add_method (T *obj, void (T::*method) (void))
-    {
-      add (new method_elem<T> (obj, method));
-    }
-
-  // Call to delete (T*).
-
-  template <class T>
-  void add_delete (T *obj)
-    {
-      add (new delete_ptr_elem<T> (obj));
-    }
-
-  // Protect any variable.
-  template <class T>
-  void protect_var (T& var)
-    {
-      add (new restore_var_elem<T> (var, var));
-    }
-
-  // Protect any variable, value given.
-  template <class T>
-  void protect_var (T& var, const T& val)
-    {
-      add (new restore_var_elem<T> (var, val));
-    }
-
-  operator bool (void) const
-    {
-      return head != 0;
-    }
-
-  void run_top (void)
-    {
-      if (head)
-        {
-          // No leak on exception!
-          std::auto_ptr<elem> ptr (head);
-          head = ptr->next;
-          ptr->run ();
-        }
-    }
-
-  void run_top (int num)
-    {
-      while (num-- > 0)
-        run_top ();
-    }
-
-  void discard_top (void)
-    {
-      if (head)
-        {
-          elem *ptr = head;
-          head = ptr->next;
-          delete ptr;
-        }
-    }
-
-  void discard_top (int num)
-    {
-      while (num-- > 0)
-        discard_top ();
-    }
-
-  void run (void)
-    {
-      while (head)
-        run_top ();
-    }
-
-  void discard (void)
-    {
-      while (head)
-        discard_top ();
-    }
-
-  // Destructor should not raise an exception, so all actions registered should
-  // be exception-safe (but setting error_state is allowed). If you're not sure,
-  // see unwind_protect_safe.
-  ~unwind_protect (void)
-    {
-      run ();
-    }
-
-private:
-
-  elem *head;
-
-  // No copying!
-
-  unwind_protect (const unwind_protect&);
-
-  unwind_protect& operator = (const unwind_protect&);
-};
-
-// Like unwind_protect, but this one will guard against the possibility of seeing
-// an exception (or interrupt) in the cleanup actions. Not that we can do much about
-// it, but at least we won't crash.
-
-class
-OCTINTERP_API
-unwind_protect_safe : public unwind_protect
-{
-  static void gripe_exception (void);
-
-public:
-  ~unwind_protect_safe (void)
-    {
-      while (*this)
-        {
-          try
-            {
-              run_top ();
-            }
-          catch (...) // Yes, the black hole. Remember we're in a dtor.
-            {
-              gripe_exception ();
-            }
-        }
-    }
-};
-
-#endif
--- a/src/xdiv.cc	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1000 +0,0 @@
-/*
-
-Copyright (C) 1993-2012 John W. Eaton
-Copyright (C) 2008 Jaroslav Hajek
-Copyright (C) 2009-2010 VZLU Prague
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <cassert>
-
-#include "Array-util.h"
-#include "CMatrix.h"
-#include "dMatrix.h"
-#include "CNDArray.h"
-#include "dNDArray.h"
-#include "fCMatrix.h"
-#include "fMatrix.h"
-#include "fCNDArray.h"
-#include "fNDArray.h"
-#include "oct-cmplx.h"
-#include "dDiagMatrix.h"
-#include "fDiagMatrix.h"
-#include "CDiagMatrix.h"
-#include "fCDiagMatrix.h"
-#include "quit.h"
-
-#include "error.h"
-#include "xdiv.h"
-
-static inline bool
-result_ok (octave_idx_type info)
-{
-  assert (info != -1);
-
-  return (info != -2);
-}
-
-static void
-solve_singularity_warning (double rcond)
-{
-  warning_with_id ("Octave:singular-matrix-div",
-                   "matrix singular to machine precision, rcond = %g", rcond);
-}
-
-template <class T1, class T2>
-bool
-mx_leftdiv_conform (const T1& a, const T2& b, blas_trans_type blas_trans)
-{
-  octave_idx_type a_nr = blas_trans == blas_no_trans ? a.rows () : a.cols ();
-  octave_idx_type b_nr = b.rows ();
-
-  if (a_nr != b_nr)
-    {
-      octave_idx_type a_nc = blas_trans == blas_no_trans ? a.cols () : a.rows ();
-      octave_idx_type b_nc = b.cols ();
-
-      gripe_nonconformant ("operator \\", a_nr, a_nc, b_nr, b_nc);
-      return false;
-    }
-
-  return true;
-}
-
-#define INSTANTIATE_MX_LEFTDIV_CONFORM(T1, T2) \
-  template bool mx_leftdiv_conform (const T1&, const T2&, blas_trans_type)
-
-INSTANTIATE_MX_LEFTDIV_CONFORM (Matrix, Matrix);
-INSTANTIATE_MX_LEFTDIV_CONFORM (Matrix, ComplexMatrix);
-INSTANTIATE_MX_LEFTDIV_CONFORM (ComplexMatrix, Matrix);
-INSTANTIATE_MX_LEFTDIV_CONFORM (ComplexMatrix, ComplexMatrix);
-
-template <class T1, class T2>
-bool
-mx_div_conform (const T1& a, const T2& b)
-{
-  octave_idx_type a_nc = a.cols ();
-  octave_idx_type b_nc = b.cols ();
-
-  if (a_nc != b_nc)
-    {
-      octave_idx_type a_nr = a.rows ();
-      octave_idx_type b_nr = b.rows ();
-
-      gripe_nonconformant ("operator /", a_nr, a_nc, b_nr, b_nc);
-      return false;
-    }
-
-  return true;
-}
-
-#define INSTANTIATE_MX_DIV_CONFORM(T1, T2) \
-  template bool mx_div_conform (const T1&, const T2&)
-
-INSTANTIATE_MX_DIV_CONFORM (Matrix, Matrix);
-INSTANTIATE_MX_DIV_CONFORM (Matrix, ComplexMatrix);
-INSTANTIATE_MX_DIV_CONFORM (ComplexMatrix, Matrix);
-INSTANTIATE_MX_DIV_CONFORM (ComplexMatrix, ComplexMatrix);
-
-// Right division functions.
-//
-//       op2 / op1:   m   cm
-//            +--   +---+----+
-//   matrix         | 1 |  3 |
-//                  +---+----+
-//   complex_matrix | 2 |  4 |
-//                  +---+----+
-
-// -*- 1 -*-
-Matrix
-xdiv (const Matrix& a, const Matrix& b, MatrixType &typ)
-{
-  if (! mx_div_conform (a, b))
-    return Matrix ();
-
-  octave_idx_type info;
-  double rcond = 0.0;
-
-  Matrix result
-    = b.solve (typ, a.transpose (), info, rcond,
-               solve_singularity_warning, true, blas_trans);
-
-  return result.transpose ();
-}
-
-// -*- 2 -*-
-ComplexMatrix
-xdiv (const Matrix& a, const ComplexMatrix& b, MatrixType &typ)
-{
-  if (! mx_div_conform (a, b))
-    return ComplexMatrix ();
-
-  octave_idx_type info;
-  double rcond = 0.0;
-
-  ComplexMatrix result
-    = b.solve (typ, a.transpose (), info, rcond,
-               solve_singularity_warning, true, blas_trans);
-
-  return result.transpose ();
-}
-
-// -*- 3 -*-
-ComplexMatrix
-xdiv (const ComplexMatrix& a, const Matrix& b, MatrixType &typ)
-{
-  if (! mx_div_conform (a, b))
-    return ComplexMatrix ();
-
-  octave_idx_type info;
-  double rcond = 0.0;
-
-  ComplexMatrix result
-    = b.solve (typ, a.transpose (), info, rcond,
-               solve_singularity_warning, true, blas_trans);
-
-  return result.transpose ();
-}
-
-// -*- 4 -*-
-ComplexMatrix
-xdiv (const ComplexMatrix& a, const ComplexMatrix& b, MatrixType &typ)
-{
-  if (! mx_div_conform (a, b))
-    return ComplexMatrix ();
-
-  octave_idx_type info;
-  double rcond = 0.0;
-
-  ComplexMatrix result
-    = b.solve (typ, a.transpose (), info, rcond,
-               solve_singularity_warning, true, blas_trans);
-
-  return result.transpose ();
-}
-
-// Funny element by element division operations.
-//
-//       op2 \ op1:   s   cs
-//            +--   +---+----+
-//   matrix         | 1 |  3 |
-//                  +---+----+
-//   complex_matrix | 2 |  4 |
-//                  +---+----+
-
-Matrix
-x_el_div (double a, const Matrix& b)
-{
-  octave_idx_type nr = b.rows ();
-  octave_idx_type nc = b.columns ();
-
-  Matrix result (nr, nc);
-
-  for (octave_idx_type j = 0; j < nc; j++)
-    for (octave_idx_type i = 0; i < nr; i++)
-      {
-        octave_quit ();
-        result (i, j) = a / b (i, j);
-      }
-
-  return result;
-}
-
-ComplexMatrix
-x_el_div (double a, const ComplexMatrix& b)
-{
-  octave_idx_type nr = b.rows ();
-  octave_idx_type nc = b.columns ();
-
-  ComplexMatrix result (nr, nc);
-
-  for (octave_idx_type j = 0; j < nc; j++)
-    for (octave_idx_type i = 0; i < nr; i++)
-      {
-        octave_quit ();
-        result (i, j) = a / b (i, j);
-      }
-
-  return result;
-}
-
-ComplexMatrix
-x_el_div (const Complex a, const Matrix& b)
-{
-  octave_idx_type nr = b.rows ();
-  octave_idx_type nc = b.columns ();
-
-  ComplexMatrix result (nr, nc);
-
-  for (octave_idx_type j = 0; j < nc; j++)
-    for (octave_idx_type i = 0; i < nr; i++)
-      {
-        octave_quit ();
-        result (i, j) = a / b (i, j);
-      }
-
-  return result;
-}
-
-ComplexMatrix
-x_el_div (const Complex a, const ComplexMatrix& b)
-{
-  octave_idx_type nr = b.rows ();
-  octave_idx_type nc = b.columns ();
-
-  ComplexMatrix result (nr, nc);
-
-  for (octave_idx_type j = 0; j < nc; j++)
-    for (octave_idx_type i = 0; i < nr; i++)
-      {
-        octave_quit ();
-        result (i, j) = a / b (i, j);
-      }
-
-  return result;
-}
-
-// Funny element by element division operations.
-//
-//          op2 \ op1:   s   cs
-//               +--   +---+----+
-//   N-d array         | 1 |  3 |
-//                     +---+----+
-//   complex N-d array | 2 |  4 |
-//                     +---+----+
-
-NDArray
-x_el_div (double a, const NDArray& b)
-{
-  NDArray result (b.dims ());
-
-  for (octave_idx_type i = 0; i < b.length (); i++)
-    {
-      octave_quit ();
-      result (i) = a / b (i);
-    }
-
-  return result;
-}
-
-ComplexNDArray
-x_el_div (double a, const ComplexNDArray& b)
-{
-  ComplexNDArray result (b.dims ());
-
-  for (octave_idx_type i = 0; i < b.length (); i++)
-    {
-      octave_quit ();
-      result (i) = a / b (i);
-    }
-
-  return result;
-}
-
-ComplexNDArray
-x_el_div (const Complex a, const NDArray& b)
-{
-  ComplexNDArray result (b.dims ());
-
-  for (octave_idx_type i = 0; i < b.length (); i++)
-    {
-      octave_quit ();
-      result (i) = a / b (i);
-    }
-
-  return result;
-}
-
-ComplexNDArray
-x_el_div (const Complex a, const ComplexNDArray& b)
-{
-  ComplexNDArray result (b.dims ());
-
-  for (octave_idx_type i = 0; i < b.length (); i++)
-    {
-      octave_quit ();
-      result (i) = a / b (i);
-    }
-
-  return result;
-}
-
-// Left division functions.
-//
-//       op2 \ op1:   m   cm
-//            +--   +---+----+
-//   matrix         | 1 |  3 |
-//                  +---+----+
-//   complex_matrix | 2 |  4 |
-//                  +---+----+
-
-// -*- 1 -*-
-Matrix
-xleftdiv (const Matrix& a, const Matrix& b, MatrixType &typ, blas_trans_type transt)
-{
-  if (! mx_leftdiv_conform (a, b, transt))
-    return Matrix ();
-
-  octave_idx_type info;
-  double rcond = 0.0;
-  return a.solve (typ, b, info, rcond, solve_singularity_warning, true, transt);
-}
-
-// -*- 2 -*-
-ComplexMatrix
-xleftdiv (const Matrix& a, const ComplexMatrix& b, MatrixType &typ, blas_trans_type transt)
-{
-  if (! mx_leftdiv_conform (a, b, transt))
-    return ComplexMatrix ();
-
-  octave_idx_type info;
-  double rcond = 0.0;
-
-  return a.solve (typ, b, info, rcond, solve_singularity_warning, true, transt);
-}
-
-// -*- 3 -*-
-ComplexMatrix
-xleftdiv (const ComplexMatrix& a, const Matrix& b, MatrixType &typ, blas_trans_type transt)
-{
-  if (! mx_leftdiv_conform (a, b, transt))
-    return ComplexMatrix ();
-
-  octave_idx_type info;
-  double rcond = 0.0;
-  return a.solve (typ, b, info, rcond, solve_singularity_warning, true, transt);
-}
-
-// -*- 4 -*-
-ComplexMatrix
-xleftdiv (const ComplexMatrix& a, const ComplexMatrix& b, MatrixType &typ, blas_trans_type transt)
-{
-  if (! mx_leftdiv_conform (a, b, transt))
-    return ComplexMatrix ();
-
-  octave_idx_type info;
-  double rcond = 0.0;
-  return a.solve (typ, b, info, rcond, solve_singularity_warning, true, transt);
-}
-
-static void
-solve_singularity_warning (float rcond)
-{
-  warning ("matrix singular to machine precision, rcond = %g", rcond);
-  warning ("attempting to find minimum norm solution");
-}
-
-INSTANTIATE_MX_LEFTDIV_CONFORM (FloatMatrix, FloatMatrix);
-INSTANTIATE_MX_LEFTDIV_CONFORM (FloatMatrix, FloatComplexMatrix);
-INSTANTIATE_MX_LEFTDIV_CONFORM (FloatComplexMatrix, FloatMatrix);
-INSTANTIATE_MX_LEFTDIV_CONFORM (FloatComplexMatrix, FloatComplexMatrix);
-
-INSTANTIATE_MX_DIV_CONFORM (FloatMatrix, FloatMatrix);
-INSTANTIATE_MX_DIV_CONFORM (FloatMatrix, FloatComplexMatrix);
-INSTANTIATE_MX_DIV_CONFORM (FloatComplexMatrix, FloatMatrix);
-INSTANTIATE_MX_DIV_CONFORM (FloatComplexMatrix, FloatComplexMatrix);
-
-// Right division functions.
-//
-//       op2 / op1:   m   cm
-//            +--   +---+----+
-//   matrix         | 1 |  3 |
-//                  +---+----+
-//   complex_matrix | 2 |  4 |
-//                  +---+----+
-
-// -*- 1 -*-
-FloatMatrix
-xdiv (const FloatMatrix& a, const FloatMatrix& b, MatrixType &typ)
-{
-  if (! mx_div_conform (a, b))
-    return FloatMatrix ();
-
-  octave_idx_type info;
-  float rcond = 0.0;
-
-  FloatMatrix result
-    = b.solve (typ, a.transpose (), info, rcond,
-               solve_singularity_warning, true, blas_trans);
-
-  return result.transpose ();
-}
-
-// -*- 2 -*-
-FloatComplexMatrix
-xdiv (const FloatMatrix& a, const FloatComplexMatrix& b, MatrixType &typ)
-{
-  if (! mx_div_conform (a, b))
-    return FloatComplexMatrix ();
-
-  octave_idx_type info;
-  float rcond = 0.0;
-
-  FloatComplexMatrix result
-    = b.solve (typ, a.transpose (), info, rcond,
-               solve_singularity_warning, true, blas_trans);
-
-  return result.transpose ();
-}
-
-// -*- 3 -*-
-FloatComplexMatrix
-xdiv (const FloatComplexMatrix& a, const FloatMatrix& b, MatrixType &typ)
-{
-  if (! mx_div_conform (a, b))
-    return FloatComplexMatrix ();
-
-  octave_idx_type info;
-  float rcond = 0.0;
-
-  FloatComplexMatrix result
-    = b.solve (typ, a.transpose (), info, rcond,
-               solve_singularity_warning, true, blas_trans);
-
-  return result.transpose ();
-}
-
-// -*- 4 -*-
-FloatComplexMatrix
-xdiv (const FloatComplexMatrix& a, const FloatComplexMatrix& b, MatrixType &typ)
-{
-  if (! mx_div_conform (a, b))
-    return FloatComplexMatrix ();
-
-  octave_idx_type info;
-  float rcond = 0.0;
-
-  FloatComplexMatrix result
-    = b.solve (typ, a.transpose (), info, rcond,
-               solve_singularity_warning, true, blas_trans);
-
-  return result.transpose ();
-}
-
-// Funny element by element division operations.
-//
-//       op2 \ op1:   s   cs
-//            +--   +---+----+
-//   matrix         | 1 |  3 |
-//                  +---+----+
-//   complex_matrix | 2 |  4 |
-//                  +---+----+
-
-FloatMatrix
-x_el_div (float a, const FloatMatrix& b)
-{
-  octave_idx_type nr = b.rows ();
-  octave_idx_type nc = b.columns ();
-
-  FloatMatrix result (nr, nc);
-
-  for (octave_idx_type j = 0; j < nc; j++)
-    for (octave_idx_type i = 0; i < nr; i++)
-      {
-        octave_quit ();
-        result (i, j) = a / b (i, j);
-      }
-
-  return result;
-}
-
-FloatComplexMatrix
-x_el_div (float a, const FloatComplexMatrix& b)
-{
-  octave_idx_type nr = b.rows ();
-  octave_idx_type nc = b.columns ();
-
-  FloatComplexMatrix result (nr, nc);
-
-  for (octave_idx_type j = 0; j < nc; j++)
-    for (octave_idx_type i = 0; i < nr; i++)
-      {
-        octave_quit ();
-        result (i, j) = a / b (i, j);
-      }
-
-  return result;
-}
-
-FloatComplexMatrix
-x_el_div (const FloatComplex a, const FloatMatrix& b)
-{
-  octave_idx_type nr = b.rows ();
-  octave_idx_type nc = b.columns ();
-
-  FloatComplexMatrix result (nr, nc);
-
-  for (octave_idx_type j = 0; j < nc; j++)
-    for (octave_idx_type i = 0; i < nr; i++)
-      {
-        octave_quit ();
-        result (i, j) = a / b (i, j);
-      }
-
-  return result;
-}
-
-FloatComplexMatrix
-x_el_div (const FloatComplex a, const FloatComplexMatrix& b)
-{
-  octave_idx_type nr = b.rows ();
-  octave_idx_type nc = b.columns ();
-
-  FloatComplexMatrix result (nr, nc);
-
-  for (octave_idx_type j = 0; j < nc; j++)
-    for (octave_idx_type i = 0; i < nr; i++)
-      {
-        octave_quit ();
-        result (i, j) = a / b (i, j);
-      }
-
-  return result;
-}
-
-// Funny element by element division operations.
-//
-//          op2 \ op1:   s   cs
-//               +--   +---+----+
-//   N-d array         | 1 |  3 |
-//                     +---+----+
-//   complex N-d array | 2 |  4 |
-//                     +---+----+
-
-FloatNDArray
-x_el_div (float a, const FloatNDArray& b)
-{
-  FloatNDArray result (b.dims ());
-
-  for (octave_idx_type i = 0; i < b.length (); i++)
-    {
-      octave_quit ();
-      result (i) = a / b (i);
-    }
-
-  return result;
-}
-
-FloatComplexNDArray
-x_el_div (float a, const FloatComplexNDArray& b)
-{
-  FloatComplexNDArray result (b.dims ());
-
-  for (octave_idx_type i = 0; i < b.length (); i++)
-    {
-      octave_quit ();
-      result (i) = a / b (i);
-    }
-
-  return result;
-}
-
-FloatComplexNDArray
-x_el_div (const FloatComplex a, const FloatNDArray& b)
-{
-  FloatComplexNDArray result (b.dims ());
-
-  for (octave_idx_type i = 0; i < b.length (); i++)
-    {
-      octave_quit ();
-      result (i) = a / b (i);
-    }
-
-  return result;
-}
-
-FloatComplexNDArray
-x_el_div (const FloatComplex a, const FloatComplexNDArray& b)
-{
-  FloatComplexNDArray result (b.dims ());
-
-  for (octave_idx_type i = 0; i < b.length (); i++)
-    {
-      octave_quit ();
-      result (i) = a / b (i);
-    }
-
-  return result;
-}
-
-// Left division functions.
-//
-//       op2 \ op1:   m   cm
-//            +--   +---+----+
-//   matrix         | 1 |  3 |
-//                  +---+----+
-//   complex_matrix | 2 |  4 |
-//                  +---+----+
-
-// -*- 1 -*-
-FloatMatrix
-xleftdiv (const FloatMatrix& a, const FloatMatrix& b, MatrixType &typ, blas_trans_type transt)
-{
-  if (! mx_leftdiv_conform (a, b, transt))
-    return FloatMatrix ();
-
-  octave_idx_type info;
-  float rcond = 0.0;
-  return a.solve (typ, b, info, rcond, solve_singularity_warning, true, transt);
-}
-
-// -*- 2 -*-
-FloatComplexMatrix
-xleftdiv (const FloatMatrix& a, const FloatComplexMatrix& b, MatrixType &typ, blas_trans_type transt)
-{
-  if (! mx_leftdiv_conform (a, b, transt))
-    return FloatComplexMatrix ();
-
-  octave_idx_type info;
-  float rcond = 0.0;
-
-  return a.solve (typ, b, info, rcond, solve_singularity_warning, true, transt);
-}
-
-// -*- 3 -*-
-FloatComplexMatrix
-xleftdiv (const FloatComplexMatrix& a, const FloatMatrix& b, MatrixType &typ, blas_trans_type transt)
-{
-  if (! mx_leftdiv_conform (a, b, transt))
-    return FloatComplexMatrix ();
-
-  octave_idx_type info;
-  float rcond = 0.0;
-  return a.solve (typ, b, info, rcond, solve_singularity_warning, true, transt);
-}
-
-// -*- 4 -*-
-FloatComplexMatrix
-xleftdiv (const FloatComplexMatrix& a, const FloatComplexMatrix& b, MatrixType &typ, blas_trans_type transt)
-{
-  if (! mx_leftdiv_conform (a, b, transt))
-    return FloatComplexMatrix ();
-
-  octave_idx_type info;
-  float rcond = 0.0;
-  return a.solve (typ, b, info, rcond, solve_singularity_warning, true, transt);
-}
-
-// Diagonal matrix division.
-
-template <class MT, class DMT>
-MT
-mdm_div_impl (const MT& a, const DMT& d)
-{
-  if (! mx_div_conform (a, d))
-    return MT ();
-
-  octave_idx_type m = a.rows (), n = d.rows (), l = d.length ();
-  MT x (m, n);
-  typedef typename DMT::element_type S;
-  typedef typename MT::element_type T;
-  const T *aa = a.data ();
-  const S *dd = d.data ();
-  T *xx = x.fortran_vec ();
-
-  for (octave_idx_type j = 0; j < l; j++)
-    {
-      const S del = dd[j];
-      if (del != S ())
-        for (octave_idx_type i = 0; i < m; i++)
-          xx[i] = aa[i] / del;
-      else
-        for (octave_idx_type i = 0; i < m; i++)
-          xx[i] = T ();
-      aa += m; xx += m;
-    }
-
-  for (octave_idx_type i = l*m; i < n*m; i++)
-    xx[i] = T ();
-
-  return x;
-}
-
-// Right division functions.
-//
-//       op2 / op1:   dm  cdm
-//            +--   +---+----+
-//   matrix         | 1 |    |
-//                  +---+----+
-//   complex_matrix | 2 |  3 |
-//                  +---+----+
-
-// -*- 1 -*-
-Matrix
-xdiv (const Matrix& a, const DiagMatrix& b)
-{ return mdm_div_impl (a, b); }
-
-// -*- 2 -*-
-ComplexMatrix
-xdiv (const ComplexMatrix& a, const DiagMatrix& b)
-{ return mdm_div_impl (a, b); }
-
-// -*- 3 -*-
-ComplexMatrix
-xdiv (const ComplexMatrix& a, const ComplexDiagMatrix& b)
-{ return mdm_div_impl (a, b); }
-
-// Right division functions, float type.
-//
-//       op2 / op1:   dm  cdm
-//            +--   +---+----+
-//   matrix         | 1 |    |
-//                  +---+----+
-//   complex_matrix | 2 |  3 |
-//                  +---+----+
-
-// -*- 1 -*-
-FloatMatrix
-xdiv (const FloatMatrix& a, const FloatDiagMatrix& b)
-{ return mdm_div_impl (a, b); }
-
-// -*- 2 -*-
-FloatComplexMatrix
-xdiv (const FloatComplexMatrix& a, const FloatDiagMatrix& b)
-{ return mdm_div_impl (a, b); }
-
-// -*- 3 -*-
-FloatComplexMatrix
-xdiv (const FloatComplexMatrix& a, const FloatComplexDiagMatrix& b)
-{ return mdm_div_impl (a, b); }
-
-template <class MT, class DMT>
-MT
-dmm_leftdiv_impl (const DMT& d, const MT& a)
-{
-  if (! mx_leftdiv_conform (d, a, blas_no_trans))
-    return MT ();
-
-  octave_idx_type m = d.cols (), n = a.cols (), k = a.rows (), l = d.length ();
-  MT x (m, n);
-  typedef typename DMT::element_type S;
-  typedef typename MT::element_type T;
-  const T *aa = a.data ();
-  const S *dd = d.data ();
-  T *xx = x.fortran_vec ();
-
-  for (octave_idx_type j = 0; j < n; j++)
-    {
-      for (octave_idx_type i = 0; i < l; i++)
-        xx[i] = dd[i] != S () ? aa[i] / dd[i] : T ();
-      for (octave_idx_type i = l; i < m; i++)
-        xx[i] = T ();
-      aa += k; xx += m;
-    }
-
-  return x;
-}
-
-// Left division functions.
-//
-//       op2 \ op1:         m   cm
-//                        +---+----+
-//   diag_matrix          | 1 |  2 |
-//                        +---+----+
-//   complex_diag_matrix  |   |  3 |
-//                        +---+----+
-
-// -*- 1 -*-
-Matrix
-xleftdiv (const DiagMatrix& a, const Matrix& b)
-{ return dmm_leftdiv_impl (a, b); }
-
-// -*- 2 -*-
-ComplexMatrix
-xleftdiv (const DiagMatrix& a, const ComplexMatrix& b)
-{ return dmm_leftdiv_impl (a, b); }
-
-// -*- 3 -*-
-ComplexMatrix
-xleftdiv (const ComplexDiagMatrix& a, const ComplexMatrix& b)
-{ return dmm_leftdiv_impl (a, b); }
-
-// Left division functions, float type.
-//
-//       op2 \ op1:         m   cm
-//                        +---+----+
-//   diag_matrix          | 1 |  2 |
-//                        +---+----+
-//   complex_diag_matrix  |   |  3 |
-//                        +---+----+
-
-// -*- 1 -*-
-FloatMatrix
-xleftdiv (const FloatDiagMatrix& a, const FloatMatrix& b)
-{ return dmm_leftdiv_impl (a, b); }
-
-// -*- 2 -*-
-FloatComplexMatrix
-xleftdiv (const FloatDiagMatrix& a, const FloatComplexMatrix& b)
-{ return dmm_leftdiv_impl (a, b); }
-
-// -*- 3 -*-
-FloatComplexMatrix
-xleftdiv (const FloatComplexDiagMatrix& a, const FloatComplexMatrix& b)
-{ return dmm_leftdiv_impl (a, b); }
-
-// Diagonal by diagonal matrix division.
-
-template <class MT, class DMT>
-MT
-dmdm_div_impl (const MT& a, const DMT& d)
-{
-  if (! mx_div_conform (a, d))
-    return MT ();
-
-  octave_idx_type m = a.rows (), n = d.rows (), k = d.cols ();
-  octave_idx_type l = std::min (m, n), lk = std::min (l, k);
-  MT x (m, n);
-  typedef typename DMT::element_type S;
-  typedef typename MT::element_type T;
-  const T *aa = a.data ();
-  const S *dd = d.data ();
-  T *xx = x.fortran_vec ();
-
-  for (octave_idx_type i = 0; i < lk; i++)
-    xx[i] = dd[i] != S () ? aa[i] / dd[i] : T ();
-  for (octave_idx_type i = lk; i < l; i++)
-    xx[i] = T ();
-
-  return x;
-}
-
-// Right division functions.
-//
-//       op2 / op1:        dm  cdm
-//            +--        +---+----+
-//   diag_matrix         | 1 |    |
-//                       +---+----+
-//   complex_diag_matrix | 2 |  3 |
-//                       +---+----+
-
-// -*- 1 -*-
-DiagMatrix
-xdiv (const DiagMatrix& a, const DiagMatrix& b)
-{ return dmdm_div_impl (a, b); }
-
-// -*- 2 -*-
-ComplexDiagMatrix
-xdiv (const ComplexDiagMatrix& a, const DiagMatrix& b)
-{ return dmdm_div_impl (a, b); }
-
-// -*- 3 -*-
-ComplexDiagMatrix
-xdiv (const ComplexDiagMatrix& a, const ComplexDiagMatrix& b)
-{ return dmdm_div_impl (a, b); }
-
-// Right division functions, float type.
-//
-//       op2 / op1:        dm  cdm
-//            +--        +---+----+
-//   diag_matrix         | 1 |    |
-//                       +---+----+
-//   complex_diag_matrix | 2 |  3 |
-//                       +---+----+
-
-// -*- 1 -*-
-FloatDiagMatrix
-xdiv (const FloatDiagMatrix& a, const FloatDiagMatrix& b)
-{ return dmdm_div_impl (a, b); }
-
-// -*- 2 -*-
-FloatComplexDiagMatrix
-xdiv (const FloatComplexDiagMatrix& a, const FloatDiagMatrix& b)
-{ return dmdm_div_impl (a, b); }
-
-// -*- 3 -*-
-FloatComplexDiagMatrix
-xdiv (const FloatComplexDiagMatrix& a, const FloatComplexDiagMatrix& b)
-{ return dmdm_div_impl (a, b); }
-
-template <class MT, class DMT>
-MT
-dmdm_leftdiv_impl (const DMT& d, const MT& a)
-{
-  if (! mx_leftdiv_conform (d, a, blas_no_trans))
-    return MT ();
-
-  octave_idx_type m = d.cols (), n = a.cols (), k = d.rows ();
-  octave_idx_type l = std::min (m, n), lk = std::min (l, k);
-  MT x (m, n);
-  typedef typename DMT::element_type S;
-  typedef typename MT::element_type T;
-  const T *aa = a.data ();
-  const S *dd = d.data ();
-  T *xx = x.fortran_vec ();
-
-  for (octave_idx_type i = 0; i < lk; i++)
-    xx[i] = dd[i] != S () ? aa[i] / dd[i] : T ();
-  for (octave_idx_type i = lk; i < l; i++)
-    xx[i] = T ();
-
-  return x;
-}
-
-// Left division functions.
-//
-//       op2 \ op1:         dm  cdm
-//                        +---+----+
-//   diag_matrix          | 1 |  2 |
-//                        +---+----+
-//   complex_diag_matrix  |   |  3 |
-//                        +---+----+
-
-// -*- 1 -*-
-DiagMatrix
-xleftdiv (const DiagMatrix& a, const DiagMatrix& b)
-{ return dmdm_leftdiv_impl (a, b); }
-
-// -*- 2 -*-
-ComplexDiagMatrix
-xleftdiv (const DiagMatrix& a, const ComplexDiagMatrix& b)
-{ return dmdm_leftdiv_impl (a, b); }
-
-// -*- 3 -*-
-ComplexDiagMatrix
-xleftdiv (const ComplexDiagMatrix& a, const ComplexDiagMatrix& b)
-{ return dmdm_leftdiv_impl (a, b); }
-
-// Left division functions, float type.
-//
-//       op2 \ op1:         dm  cdm
-//                        +---+----+
-//   diag_matrix          | 1 |  2 |
-//                        +---+----+
-//   complex_diag_matrix  |   |  3 |
-//                        +---+----+
-
-// -*- 1 -*-
-FloatDiagMatrix
-xleftdiv (const FloatDiagMatrix& a, const FloatDiagMatrix& b)
-{ return dmdm_leftdiv_impl (a, b); }
-
-// -*- 2 -*-
-FloatComplexDiagMatrix
-xleftdiv (const FloatDiagMatrix& a, const FloatComplexDiagMatrix& b)
-{ return dmdm_leftdiv_impl (a, b); }
-
-// -*- 3 -*-
-FloatComplexDiagMatrix
-xleftdiv (const FloatComplexDiagMatrix& a, const FloatComplexDiagMatrix& b)
-{ return dmdm_leftdiv_impl (a, b); }
--- a/src/xdiv.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,129 +0,0 @@
-/*
-
-Copyright (C) 1993-2012 John W. Eaton
-Copyright (C) 2008 Jaroslav Hajek
-
-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/>.
-
-*/
-
-#if !defined (octave_xdiv_h)
-#define octave_xdiv_h 1
-
-#include "mx-defs.h"
-#include "MatrixType.h"
-
-extern Matrix xdiv (const Matrix& a, const Matrix& b, MatrixType &typ);
-extern ComplexMatrix xdiv (const Matrix& a, const ComplexMatrix& b,
-                           MatrixType &typ);
-extern ComplexMatrix xdiv (const ComplexMatrix& a, const Matrix& b,
-                           MatrixType &typ);
-extern ComplexMatrix xdiv (const ComplexMatrix& a, const ComplexMatrix& b,
-                           MatrixType &typ);
-
-extern Matrix x_el_div (double a, const Matrix& b);
-extern ComplexMatrix x_el_div (double a, const ComplexMatrix& b);
-extern ComplexMatrix x_el_div (const Complex a, const Matrix& b);
-extern ComplexMatrix x_el_div (const Complex a, const ComplexMatrix& b);
-
-extern NDArray x_el_div (double a, const NDArray& b);
-extern ComplexNDArray x_el_div (double a, const ComplexNDArray& b);
-extern ComplexNDArray x_el_div (const Complex a, const NDArray& b);
-extern ComplexNDArray x_el_div (const Complex a, const ComplexNDArray& b);
-
-extern Matrix xleftdiv (const Matrix& a, const Matrix& b, MatrixType &typ,
-                        blas_trans_type transt = blas_no_trans);
-extern ComplexMatrix xleftdiv (const Matrix& a, const ComplexMatrix& b,
-                               MatrixType &typ, blas_trans_type transt = blas_no_trans);
-extern ComplexMatrix xleftdiv (const ComplexMatrix& a, const Matrix& b,
-                               MatrixType &typ, blas_trans_type transt = blas_no_trans);
-extern ComplexMatrix xleftdiv (const ComplexMatrix& a, const ComplexMatrix& b,
-                               MatrixType &typ, blas_trans_type transt = blas_no_trans);
-
-extern FloatMatrix xdiv (const FloatMatrix& a, const FloatMatrix& b, MatrixType &typ);
-extern FloatComplexMatrix xdiv (const FloatMatrix& a, const FloatComplexMatrix& b,
-                           MatrixType &typ);
-extern FloatComplexMatrix xdiv (const FloatComplexMatrix& a, const FloatMatrix& b,
-                           MatrixType &typ);
-extern FloatComplexMatrix xdiv (const FloatComplexMatrix& a, const FloatComplexMatrix& b,
-                           MatrixType &typ);
-
-extern FloatMatrix x_el_div (float a, const FloatMatrix& b);
-extern FloatComplexMatrix x_el_div (float a, const FloatComplexMatrix& b);
-extern FloatComplexMatrix x_el_div (const FloatComplex a, const FloatMatrix& b);
-extern FloatComplexMatrix x_el_div (const FloatComplex a, const FloatComplexMatrix& b);
-
-extern FloatNDArray x_el_div (float a, const FloatNDArray& b);
-extern FloatComplexNDArray x_el_div (float a, const FloatComplexNDArray& b);
-extern FloatComplexNDArray x_el_div (const FloatComplex a, const FloatNDArray& b);
-extern FloatComplexNDArray x_el_div (const FloatComplex a, const FloatComplexNDArray& b);
-
-extern FloatMatrix xleftdiv (const FloatMatrix& a, const FloatMatrix& b, MatrixType &typ,
-                             blas_trans_type transt = blas_no_trans);
-extern FloatComplexMatrix xleftdiv (const FloatMatrix& a, const FloatComplexMatrix& b,
-                               MatrixType &typ, blas_trans_type transt = blas_no_trans);
-extern FloatComplexMatrix xleftdiv (const FloatComplexMatrix& a, const FloatMatrix& b,
-                               MatrixType &typ, blas_trans_type transt = blas_no_trans);
-extern FloatComplexMatrix xleftdiv (const FloatComplexMatrix& a, const FloatComplexMatrix& b,
-                               MatrixType &typ, blas_trans_type transt = blas_no_trans);
-
-
-extern Matrix xdiv (const Matrix& a, const DiagMatrix& b);
-extern ComplexMatrix xdiv (const ComplexMatrix& a, const DiagMatrix& b);
-extern ComplexMatrix xdiv (const ComplexMatrix& a, const ComplexDiagMatrix& b);
-
-extern DiagMatrix xdiv (const DiagMatrix& a, const DiagMatrix& b);
-extern ComplexDiagMatrix xdiv (const ComplexDiagMatrix& a, const DiagMatrix& b);
-extern ComplexDiagMatrix xdiv (const ComplexDiagMatrix& a, const ComplexDiagMatrix& b);
-
-extern FloatMatrix xdiv (const FloatMatrix& a, const FloatDiagMatrix& b);
-extern FloatComplexMatrix xdiv (const FloatComplexMatrix& a,
-                                const FloatDiagMatrix& b);
-extern FloatComplexMatrix xdiv (const FloatMatrix& a,
-                                const FloatComplexDiagMatrix& b);
-extern FloatComplexMatrix xdiv (const FloatComplexMatrix& a,
-                                const FloatComplexDiagMatrix& b);
-
-extern FloatDiagMatrix xdiv (const FloatDiagMatrix& a, const FloatDiagMatrix& b);
-extern FloatComplexDiagMatrix xdiv (const FloatComplexDiagMatrix& a,
-                                    const FloatDiagMatrix& b);
-extern FloatComplexDiagMatrix xdiv (const FloatComplexDiagMatrix& a,
-                                    const FloatComplexDiagMatrix& b);
-
-extern Matrix xleftdiv (const DiagMatrix& a, const Matrix& b);
-extern ComplexMatrix xleftdiv (const DiagMatrix& a, const ComplexMatrix& b);
-extern ComplexMatrix xleftdiv (const ComplexDiagMatrix& a, const ComplexMatrix& b);
-
-extern DiagMatrix xleftdiv (const DiagMatrix& a, const DiagMatrix& b);
-extern ComplexDiagMatrix xleftdiv (const DiagMatrix& a, const ComplexDiagMatrix& b);
-extern ComplexDiagMatrix xleftdiv (const ComplexDiagMatrix& a, const ComplexDiagMatrix& b);
-
-extern FloatMatrix xleftdiv (const FloatDiagMatrix& a,
-                             const FloatMatrix& b);
-extern FloatComplexMatrix xleftdiv (const FloatDiagMatrix& a,
-                                    const FloatComplexMatrix& b);
-extern FloatComplexMatrix xleftdiv (const FloatComplexDiagMatrix& a,
-                                    const FloatComplexMatrix& b);
-
-extern FloatDiagMatrix xleftdiv (const FloatDiagMatrix& a,
-                                 const FloatDiagMatrix& b);
-extern FloatComplexDiagMatrix xleftdiv (const FloatDiagMatrix& a,
-                                        const FloatComplexDiagMatrix& b);
-extern FloatComplexDiagMatrix xleftdiv (const FloatComplexDiagMatrix& a,
-                                        const FloatComplexDiagMatrix& b);
-
-#endif
--- a/src/xgl2ps.c	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-/*
-
-Copyright (C) 2009-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-// Wrapper for "imported" file gl2ps.c so that config.h will be included
-// before any other system or gnulib headers.
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#if defined (HAVE_OPENGL)
-
-#include "gl2ps.c"
-
-#endif
--- a/src/xnorm.cc	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,212 +0,0 @@
-/*
-
-Copyright (C) 2008-2012 VZLU Prague, a.s.
-
-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/>.
-
-*/
-
-// author: Jaroslav Hajek <highegg@gmail.com>
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <cassert>
-#include <cfloat>
-#include <cmath>
-
-#include "oct-norm.h"
-
-#include "error.h"
-#include "xnorm.h"
-#include "ov.h"
-#include "gripes.h"
-
-octave_value xnorm (const octave_value& x, const octave_value& p)
-{
-  octave_value retval;
-
-  bool isvector = (x.columns () == 1 || x.rows () == 1);
-  bool iscomplex = x.is_complex_type ();
-  bool issparse = x.is_sparse_type ();
-  bool isfloat = x.is_single_type ();
-
-  if (isfloat || x.is_double_type ())
-    {
-      if (isvector)
-        {
-          if (isfloat & iscomplex)
-            retval = xnorm (x.float_complex_column_vector_value (),
-                            p.float_value ());
-          else if (isfloat)
-            retval = xnorm (x.float_column_vector_value (),
-                            p.float_value ());
-          else if (iscomplex)
-            retval = xnorm (x.complex_column_vector_value (),
-                            p.double_value ());
-          else
-            retval = xnorm (x.column_vector_value (),
-                            p.double_value ());
-        }
-      else if (issparse)
-        {
-          if (iscomplex)
-            retval = xnorm (x.sparse_complex_matrix_value (),
-                            p.double_value ());
-          else
-            retval = xnorm (x.sparse_matrix_value (),
-                            p.double_value ());
-        }
-      else
-        {
-          if (isfloat & iscomplex)
-            retval = xnorm (x.float_complex_matrix_value (),
-                            p.float_value ());
-          else if (isfloat)
-            retval = xnorm (x.float_matrix_value (),
-                            p.float_value ());
-          else if (iscomplex)
-            retval = xnorm (x.complex_matrix_value (),
-                            p.double_value ());
-          else
-            retval = xnorm (x.matrix_value (),
-                            p.double_value ());
-        }
-    }
-  else
-    gripe_wrong_type_arg ("xnorm", x, true);
-
-  return retval;
-}
-
-octave_value xcolnorms (const octave_value& x, const octave_value& p)
-{
-  octave_value retval;
-
-  bool iscomplex = x.is_complex_type ();
-  bool issparse = x.is_sparse_type ();
-  bool isfloat = x.is_single_type ();
-
-  if (isfloat || x.is_double_type ())
-    {
-      if (issparse)
-        {
-          if (iscomplex)
-            retval = xcolnorms (x.sparse_complex_matrix_value (),
-                                p.double_value ());
-          else
-            retval = xcolnorms (x.sparse_matrix_value (),
-                                p.double_value ());
-        }
-      else
-        {
-          if (isfloat & iscomplex)
-            retval = xcolnorms (x.float_complex_matrix_value (),
-                                p.float_value ());
-          else if (isfloat)
-            retval = xcolnorms (x.float_matrix_value (),
-                                p.float_value ());
-          else if (iscomplex)
-            retval = xcolnorms (x.complex_matrix_value (),
-                                p.double_value ());
-          else
-            retval = xcolnorms (x.matrix_value (),
-                                p.double_value ());
-        }
-    }
-  else
-    gripe_wrong_type_arg ("xcolnorms", x, true);
-
-  return retval;
-}
-
-octave_value xrownorms (const octave_value& x, const octave_value& p)
-{
-  octave_value retval;
-
-  bool iscomplex = x.is_complex_type ();
-  bool issparse = x.is_sparse_type ();
-  bool isfloat = x.is_single_type ();
-
-  if (isfloat || x.is_double_type ())
-    {
-      if (issparse)
-        {
-          if (iscomplex)
-            retval = xrownorms (x.sparse_complex_matrix_value (),
-                                p.double_value ());
-          else
-            retval = xrownorms (x.sparse_matrix_value (),
-                                p.double_value ());
-        }
-      else
-        {
-          if (isfloat & iscomplex)
-            retval = xrownorms (x.float_complex_matrix_value (),
-                                p.float_value ());
-          else if (isfloat)
-            retval = xrownorms (x.float_matrix_value (),
-                                p.float_value ());
-          else if (iscomplex)
-            retval = xrownorms (x.complex_matrix_value (),
-                                p.double_value ());
-          else
-            retval = xrownorms (x.matrix_value (),
-                                p.double_value ());
-        }
-    }
-  else
-    gripe_wrong_type_arg ("xrownorms", x, true);
-
-  return retval;
-}
-
-octave_value xfrobnorm (const octave_value& x)
-{
-  octave_value retval;
-
-  bool iscomplex = x.is_complex_type ();
-  bool issparse = x.is_sparse_type ();
-  bool isfloat = x.is_single_type ();
-
-  if (isfloat || x.is_double_type ())
-    {
-      if (issparse)
-        {
-          if (iscomplex)
-            retval = xfrobnorm (x.sparse_complex_matrix_value ());
-          else
-            retval = xfrobnorm (x.sparse_matrix_value ());
-        }
-      else
-        {
-          if (isfloat & iscomplex)
-            retval = xfrobnorm (x.float_complex_matrix_value ());
-          else if (isfloat)
-            retval = xfrobnorm (x.float_matrix_value ());
-          else if (iscomplex)
-            retval = xfrobnorm (x.complex_matrix_value ());
-          else
-            retval = xfrobnorm (x.matrix_value ());
-        }
-    }
-  else
-    gripe_wrong_type_arg ("xfrobnorm", x, true);
-
-  return retval;
-}
--- a/src/xnorm.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-/*
-
-Copyright (C) 2008-2012 VZLU Prague, a.s.
-
-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/>.
-
-*/
-
-// author: Jaroslav Hajek <highegg@gmail.com>
-
-#if !defined (octave_xnorm_h)
-#define octave_xnorm_h 1
-
-#include "oct-norm.h"
-
-class octave_value;
-
-extern OCTINTERP_API octave_value xnorm (const octave_value& x, const octave_value& p);
-extern OCTINTERP_API octave_value xcolnorms (const octave_value& x, const octave_value& p);
-extern OCTINTERP_API octave_value xrownorms (const octave_value& x, const octave_value& p);
-extern OCTINTERP_API octave_value xfrobnorm (const octave_value& x);
-
-#endif
--- a/src/xpow.cc	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2858 +0,0 @@
-/*
-
-Copyright (C) 1993-2012 John W. Eaton
-Copyright (C) 2009-2010 VZLU Prague
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <cassert>
-#include <climits>
-
-#include "Array-util.h"
-#include "CColVector.h"
-#include "CDiagMatrix.h"
-#include "fCDiagMatrix.h"
-#include "CMatrix.h"
-#include "EIG.h"
-#include "fEIG.h"
-#include "dDiagMatrix.h"
-#include "fDiagMatrix.h"
-#include "dMatrix.h"
-#include "PermMatrix.h"
-#include "mx-cm-cdm.h"
-#include "oct-cmplx.h"
-#include "Range.h"
-#include "quit.h"
-
-#include "error.h"
-#include "oct-obj.h"
-#include "utils.h"
-#include "xpow.h"
-
-#include "bsxfun.h"
-
-#ifdef _OPENMP
-#include <omp.h>
-#endif
-
-static inline int
-xisint (double x)
-{
-  return (D_NINT (x) == x
-          && ((x >= 0 && x < INT_MAX)
-              || (x <= 0 && x > INT_MIN)));
-}
-
-// Safer pow functions.
-//
-//       op2 \ op1:   s   m   cs   cm
-//            +--   +---+---+----+----+
-//   scalar   |     | 1 | 5 |  7 | 11 |
-//                  +---+---+----+----+
-//   matrix         | 2 | * |  8 |  * |
-//                  +---+---+----+----+
-//   complex_scalar | 3 | 6 |  9 | 12 |
-//                  +---+---+----+----+
-//   complex_matrix | 4 | * | 10 |  * |
-//                  +---+---+----+----+
-
-// -*- 1 -*-
-octave_value
-xpow (double a, double b)
-{
-  double retval;
-
-  if (a < 0.0 && ! xisint (b))
-    {
-      Complex atmp (a);
-
-      return std::pow (atmp, b);
-    }
-  else
-    retval = std::pow (a, b);
-
-  return retval;
-}
-
-// -*- 2 -*-
-octave_value
-xpow (double a, const Matrix& b)
-{
-  octave_value retval;
-
-  octave_idx_type nr = b.rows ();
-  octave_idx_type nc = b.cols ();
-
-  if (nr == 0 || nc == 0 || nr != nc)
-    error ("for x^A, A must be a square matrix");
-  else
-    {
-      EIG b_eig (b);
-
-      if (! error_state)
-        {
-          ComplexColumnVector lambda (b_eig.eigenvalues ());
-          ComplexMatrix Q (b_eig.eigenvectors ());
-
-          for (octave_idx_type i = 0; i < nr; i++)
-            {
-              Complex elt = lambda(i);
-              if (std::imag (elt) == 0.0)
-                lambda(i) = std::pow (a, std::real (elt));
-              else
-                lambda(i) = std::pow (a, elt);
-            }
-          ComplexDiagMatrix D (lambda);
-
-          ComplexMatrix C = Q * D * Q.inverse ();
-          if (a > 0)
-            retval = real (C);
-          else
-            retval = C;
-        }
-      else
-        error ("xpow: matrix diagonalization failed");
-    }
-
-  return retval;
-}
-
-// -*- 3 -*-
-octave_value
-xpow (double a, const Complex& b)
-{
-  Complex result = std::pow (a, b);
-  return result;
-}
-
-// -*- 4 -*-
-octave_value
-xpow (double a, const ComplexMatrix& b)
-{
-  octave_value retval;
-
-  octave_idx_type nr = b.rows ();
-  octave_idx_type nc = b.cols ();
-
-  if (nr == 0 || nc == 0 || nr != nc)
-    error ("for x^A, A must be a square matrix");
-  else
-    {
-      EIG b_eig (b);
-
-      if (! error_state)
-        {
-          ComplexColumnVector lambda (b_eig.eigenvalues ());
-          ComplexMatrix Q (b_eig.eigenvectors ());
-
-          for (octave_idx_type i = 0; i < nr; i++)
-            {
-              Complex elt = lambda(i);
-              if (std::imag (elt) == 0.0)
-                lambda(i) = std::pow (a, std::real (elt));
-              else
-                lambda(i) = std::pow (a, elt);
-            }
-          ComplexDiagMatrix D (lambda);
-
-          retval = ComplexMatrix (Q * D * Q.inverse ());
-        }
-      else
-        error ("xpow: matrix diagonalization failed");
-    }
-
-  return retval;
-}
-
-// -*- 5 -*-
-octave_value
-xpow (const Matrix& a, double b)
-{
-  octave_value retval;
-
-  octave_idx_type nr = a.rows ();
-  octave_idx_type nc = a.cols ();
-
-  if (nr == 0 || nc == 0 || nr != nc)
-    error ("for A^b, A must be a square matrix");
-  else
-    {
-      if (static_cast<int> (b) == b)
-        {
-          int btmp = static_cast<int> (b);
-          if (btmp == 0)
-            {
-              retval = DiagMatrix (nr, nr, 1.0);
-            }
-          else
-            {
-              // Too much copying?
-              // FIXME -- we shouldn't do this if the exponent is
-              // large...
-
-              Matrix atmp;
-              if (btmp < 0)
-                {
-                  btmp = -btmp;
-
-                  octave_idx_type info;
-                  double rcond = 0.0;
-                  MatrixType mattype (a);
-
-                  atmp = a.inverse (mattype, info, rcond, 1);
-
-                  if (info == -1)
-                    warning ("inverse: matrix singular to machine\
- precision, rcond = %g", rcond);
-                }
-              else
-                atmp = a;
-
-              Matrix result (atmp);
-
-              btmp--;
-
-              while (btmp > 0)
-                {
-                  if (btmp & 1)
-                    result = result * atmp;
-
-                  btmp >>= 1;
-
-                  if (btmp > 0)
-                    atmp = atmp * atmp;
-                }
-
-              retval = result;
-            }
-        }
-      else
-        {
-          EIG a_eig (a);
-
-          if (! error_state)
-            {
-              ComplexColumnVector lambda (a_eig.eigenvalues ());
-              ComplexMatrix Q (a_eig.eigenvectors ());
-
-              for (octave_idx_type i = 0; i < nr; i++)
-                lambda(i) = std::pow (lambda(i), b);
-
-              ComplexDiagMatrix D (lambda);
-
-              retval = ComplexMatrix (Q * D * Q.inverse ());
-            }
-          else
-            error ("xpow: matrix diagonalization failed");
-        }
-    }
-
-  return retval;
-}
-
-// -*- 5d -*-
-octave_value
-xpow (const DiagMatrix& a, double b)
-{
-  octave_value retval;
-
-  octave_idx_type nr = a.rows ();
-  octave_idx_type nc = a.cols ();
-
-  if (nr == 0 || nc == 0 || nr != nc)
-    error ("for A^b, A must be a square matrix");
-  else
-    {
-      if (static_cast<int> (b) == b)
-        {
-          DiagMatrix r (nr, nc);
-          for (octave_idx_type i = 0; i < nc; i++)
-            r.dgelem (i) = std::pow (a.dgelem (i), b);
-          retval = r;
-        }
-      else
-        {
-          ComplexDiagMatrix r (nr, nc);
-          for (octave_idx_type i = 0; i < nc; i++)
-            r.dgelem (i) = std::pow (static_cast<Complex> (a.dgelem (i)), b);
-          retval = r;
-        }
-    }
-
-  return retval;
-}
-
-// -*- 5p -*-
-octave_value
-xpow (const PermMatrix& a, double b)
-{
-  octave_value retval;
-  int btmp = static_cast<int> (b);
-  if (btmp == b)
-    return a.power (btmp);
-  else
-    return xpow (Matrix (a), b);
-}
-
-// -*- 6 -*-
-octave_value
-xpow (const Matrix& a, const Complex& b)
-{
-  octave_value retval;
-
-  octave_idx_type nr = a.rows ();
-  octave_idx_type nc = a.cols ();
-
-  if (nr == 0 || nc == 0 || nr != nc)
-    error ("for A^b, A must be a square matrix");
-  else
-    {
-      EIG a_eig (a);
-
-      if (! error_state)
-        {
-          ComplexColumnVector lambda (a_eig.eigenvalues ());
-          ComplexMatrix Q (a_eig.eigenvectors ());
-
-          for (octave_idx_type i = 0; i < nr; i++)
-            lambda(i) = std::pow (lambda(i), b);
-
-          ComplexDiagMatrix D (lambda);
-
-          retval = ComplexMatrix (Q * D * Q.inverse ());
-        }
-      else
-        error ("xpow: matrix diagonalization failed");
-    }
-
-  return retval;
-}
-
-// -*- 7 -*-
-octave_value
-xpow (const Complex& a, double b)
-{
-  Complex result;
-
-  if (xisint (b))
-    result = std::pow (a, static_cast<int> (b));
-  else
-    result = std::pow (a, b);
-
-  return result;
-}
-
-// -*- 8 -*-
-octave_value
-xpow (const Complex& a, const Matrix& b)
-{
-  octave_value retval;
-
-  octave_idx_type nr = b.rows ();
-  octave_idx_type nc = b.cols ();
-
-  if (nr == 0 || nc == 0 || nr != nc)
-    error ("for x^A, A must be a square matrix");
-  else
-    {
-      EIG b_eig (b);
-
-      if (! error_state)
-        {
-          ComplexColumnVector lambda (b_eig.eigenvalues ());
-          ComplexMatrix Q (b_eig.eigenvectors ());
-
-          for (octave_idx_type i = 0; i < nr; i++)
-            {
-              Complex elt = lambda(i);
-              if (std::imag (elt) == 0.0)
-                lambda(i) = std::pow (a, std::real (elt));
-              else
-                lambda(i) = std::pow (a, elt);
-            }
-          ComplexDiagMatrix D (lambda);
-
-          retval = ComplexMatrix (Q * D * Q.inverse ());
-        }
-      else
-        error ("xpow: matrix diagonalization failed");
-    }
-
-  return retval;
-}
-
-// -*- 9 -*-
-octave_value
-xpow (const Complex& a, const Complex& b)
-{
-  Complex result;
-  result = std::pow (a, b);
-  return result;
-}
-
-// -*- 10 -*-
-octave_value
-xpow (const Complex& a, const ComplexMatrix& b)
-{
-  octave_value retval;
-
-  octave_idx_type nr = b.rows ();
-  octave_idx_type nc = b.cols ();
-
-  if (nr == 0 || nc == 0 || nr != nc)
-    error ("for x^A, A must be a square matrix");
-  else
-    {
-      EIG b_eig (b);
-
-      if (! error_state)
-        {
-          ComplexColumnVector lambda (b_eig.eigenvalues ());
-          ComplexMatrix Q (b_eig.eigenvectors ());
-
-          for (octave_idx_type i = 0; i < nr; i++)
-            {
-              Complex elt = lambda(i);
-              if (std::imag (elt) == 0.0)
-                lambda(i) = std::pow (a, std::real (elt));
-              else
-                lambda(i) = std::pow (a, elt);
-            }
-          ComplexDiagMatrix D (lambda);
-
-          retval = ComplexMatrix (Q * D * Q.inverse ());
-        }
-      else
-        error ("xpow: matrix diagonalization failed");
-    }
-
-  return retval;
-}
-
-// -*- 11 -*-
-octave_value
-xpow (const ComplexMatrix& a, double b)
-{
-  octave_value retval;
-
-  octave_idx_type nr = a.rows ();
-  octave_idx_type nc = a.cols ();
-
-  if (nr == 0 || nc == 0 || nr != nc)
-    error ("for A^b, A must be a square matrix");
-  else
-    {
-      if (static_cast<int> (b) == b)
-        {
-          int btmp = static_cast<int> (b);
-          if (btmp == 0)
-            {
-              retval = DiagMatrix (nr, nr, 1.0);
-            }
-          else
-            {
-              // Too much copying?
-              // FIXME -- we shouldn't do this if the exponent is
-              // large...
-
-              ComplexMatrix atmp;
-              if (btmp < 0)
-                {
-                  btmp = -btmp;
-
-                  octave_idx_type info;
-                  double rcond = 0.0;
-                  MatrixType mattype (a);
-
-                  atmp = a.inverse (mattype, info, rcond, 1);
-
-                  if (info == -1)
-                    warning ("inverse: matrix singular to machine\
- precision, rcond = %g", rcond);
-                }
-              else
-                atmp = a;
-
-              ComplexMatrix result (atmp);
-
-              btmp--;
-
-              while (btmp > 0)
-                {
-                  if (btmp & 1)
-                    result = result * atmp;
-
-                  btmp >>= 1;
-
-                  if (btmp > 0)
-                    atmp = atmp * atmp;
-                }
-
-              retval = result;
-            }
-        }
-      else
-        {
-          EIG a_eig (a);
-
-          if (! error_state)
-            {
-              ComplexColumnVector lambda (a_eig.eigenvalues ());
-              ComplexMatrix Q (a_eig.eigenvectors ());
-
-              for (octave_idx_type i = 0; i < nr; i++)
-                lambda(i) = std::pow (lambda(i), b);
-
-              ComplexDiagMatrix D (lambda);
-
-              retval = ComplexMatrix (Q * D * Q.inverse ());
-            }
-          else
-            error ("xpow: matrix diagonalization failed");
-        }
-    }
-
-  return retval;
-}
-
-// -*- 12 -*-
-octave_value
-xpow (const ComplexMatrix& a, const Complex& b)
-{
-  octave_value retval;
-
-  octave_idx_type nr = a.rows ();
-  octave_idx_type nc = a.cols ();
-
-  if (nr == 0 || nc == 0 || nr != nc)
-    error ("for A^b, A must be a square matrix");
-  else
-    {
-      EIG a_eig (a);
-
-      if (! error_state)
-        {
-          ComplexColumnVector lambda (a_eig.eigenvalues ());
-          ComplexMatrix Q (a_eig.eigenvectors ());
-
-          for (octave_idx_type i = 0; i < nr; i++)
-            lambda(i) = std::pow (lambda(i), b);
-
-          ComplexDiagMatrix D (lambda);
-
-          retval = ComplexMatrix (Q * D * Q.inverse ());
-        }
-      else
-        error ("xpow: matrix diagonalization failed");
-    }
-
-  return retval;
-}
-
-// -*- 12d -*-
-octave_value
-xpow (const ComplexDiagMatrix& a, const Complex& b)
-{
-  octave_value retval;
-
-  octave_idx_type nr = a.rows ();
-  octave_idx_type nc = a.cols ();
-
-  if (nr == 0 || nc == 0 || nr != nc)
-    error ("for A^b, A must be a square matrix");
-  else
-    {
-      ComplexDiagMatrix r (nr, nc);
-      for (octave_idx_type i = 0; i < nc; i++)
-        r(i, i) = std::pow (a(i, i), b);
-      retval = r;
-    }
-
-  return retval;
-}
-
-// mixed
-octave_value
-xpow (const ComplexDiagMatrix& a, double b)
-{
-  return xpow (a, static_cast<Complex> (b));
-}
-
-octave_value
-xpow (const DiagMatrix& a, const Complex& b)
-{
-  return xpow (ComplexDiagMatrix (a), b);
-}
-
-
-// Safer pow functions that work elementwise for matrices.
-//
-//       op2 \ op1:   s   m   cs   cm
-//            +--   +---+---+----+----+
-//   scalar   |     | * | 3 |  * |  9 |
-//                  +---+---+----+----+
-//   matrix         | 1 | 4 |  7 | 10 |
-//                  +---+---+----+----+
-//   complex_scalar | * | 5 |  * | 11 |
-//                  +---+---+----+----+
-//   complex_matrix | 2 | 6 |  8 | 12 |
-//                  +---+---+----+----+
-//
-//   * -> not needed.
-
-// FIXME -- these functions need to be fixed so that things
-// like
-//
-//   a = -1; b = [ 0, 0.5, 1 ]; r = a .^ b
-//
-// and
-//
-//   a = -1; b = [ 0, 0.5, 1 ]; for i = 1:3, r(i) = a .^ b(i), end
-//
-// produce identical results.  Also, it would be nice if -1^0.5
-// produced a pure imaginary result instead of a complex number with a
-// small real part.  But perhaps that's really a problem with the math
-// library...
-
-// -*- 1 -*-
-octave_value
-elem_xpow (double a, const Matrix& b)
-{
-  octave_value retval;
-
-  octave_idx_type nr = b.rows ();
-  octave_idx_type nc = b.cols ();
-
-  double d1, d2;
-
-  if (a < 0.0 && ! b.all_integers (d1, d2))
-    {
-      Complex atmp (a);
-      ComplexMatrix result (nr, nc);
-
-      for (octave_idx_type j = 0; j < nc; j++)
-        for (octave_idx_type i = 0; i < nr; i++)
-          {
-            octave_quit ();
-            result (i, j) = std::pow (atmp, b (i, j));
-          }
-
-      retval = result;
-    }
-  else
-    {
-      Matrix result (nr, nc);
-
-      for (octave_idx_type j = 0; j < nc; j++)
-        for (octave_idx_type i = 0; i < nr; i++)
-          {
-            octave_quit ();
-            result (i, j) = std::pow (a, b (i, j));
-          }
-
-      retval = result;
-    }
-
-  return retval;
-}
-
-// -*- 2 -*-
-octave_value
-elem_xpow (double a, const ComplexMatrix& b)
-{
-  octave_idx_type nr = b.rows ();
-  octave_idx_type nc = b.cols ();
-
-  ComplexMatrix result (nr, nc);
-  Complex atmp (a);
-
-  for (octave_idx_type j = 0; j < nc; j++)
-    for (octave_idx_type i = 0; i < nr; i++)
-      {
-        octave_quit ();
-        result (i, j) = std::pow (atmp, b (i, j));
-      }
-
-  return result;
-}
-
-static inline bool
-same_sign (double a, double b)
-{
-  return (a >= 0 && b >= 0) || (a <= 0 && b <= 0);
-}
-
-octave_value
-elem_xpow (double a, const Range& r)
-{
-  octave_value retval;
-
-  // Only optimize powers with ranges that are integer and monotonic in
-  // magnitude.
-  if (r.nelem () > 1 && r.all_elements_are_ints ()
-      && same_sign (r.base (), r.limit ()))
-    {
-      octave_idx_type n = r.nelem ();
-      Matrix result (1, n);
-      if (same_sign (r.base (), r.inc ()))
-        {
-          double base = std::pow (a, r.base ());
-          double inc = std::pow (a, r.inc ());
-          result(0) = base;
-          for (octave_idx_type i = 1; i < n; i++)
-            result(i) = (base *= inc);
-        }
-      else
-        {
-          // Don't use Range::limit () here.
-          double limit = std::pow (a, r.base () + (n-1) * r.inc ());
-          double inc = std::pow (a, -r.inc ());
-          result(n-1) = limit;
-          for (octave_idx_type i = n-2; i >= 0; i--)
-            result(i) = (limit *= inc);
-        }
-
-      retval = result;
-    }
-  else
-    retval = elem_xpow (a, r.matrix_value ());
-
-  return retval;
-}
-
-// -*- 3 -*-
-octave_value
-elem_xpow (const Matrix& a, double b)
-{
-  octave_value retval;
-
-  octave_idx_type nr = a.rows ();
-  octave_idx_type nc = a.cols ();
-
-  if (! xisint (b) && a.any_element_is_negative ())
-    {
-      ComplexMatrix result (nr, nc);
-
-      for (octave_idx_type j = 0; j < nc; j++)
-        for (octave_idx_type i = 0; i < nr; i++)
-          {
-            octave_quit ();
-
-            Complex atmp (a (i, j));
-
-            result (i, j) = std::pow (atmp, b);
-          }
-
-      retval = result;
-    }
-  else
-    {
-      Matrix result (nr, nc);
-
-      for (octave_idx_type j = 0; j < nc; j++)
-        for (octave_idx_type i = 0; i < nr; i++)
-          {
-            octave_quit ();
-            result (i, j) = std::pow (a (i, j), b);
-          }
-
-      retval = result;
-    }
-
-  return retval;
-}
-
-// -*- 4 -*-
-octave_value
-elem_xpow (const Matrix& a, const Matrix& b)
-{
-  octave_value retval;
-
-  octave_idx_type nr = a.rows ();
-  octave_idx_type nc = a.cols ();
-
-  octave_idx_type b_nr = b.rows ();
-  octave_idx_type b_nc = b.cols ();
-
-  if (nr != b_nr || nc != b_nc)
-    {
-      gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc);
-      return octave_value ();
-    }
-
-  int convert_to_complex = 0;
-  for (octave_idx_type j = 0; j < nc; j++)
-    for (octave_idx_type i = 0; i < nr; i++)
-      {
-        octave_quit ();
-        double atmp = a (i, j);
-        double btmp = b (i, j);
-        if (atmp < 0.0 && static_cast<int> (btmp) != btmp)
-          {
-            convert_to_complex = 1;
-            goto done;
-          }
-      }
-
-done:
-
-  if (convert_to_complex)
-    {
-      ComplexMatrix complex_result (nr, nc);
-
-      for (octave_idx_type j = 0; j < nc; j++)
-        for (octave_idx_type i = 0; i < nr; i++)
-          {
-            octave_quit ();
-            Complex atmp (a (i, j));
-            Complex btmp (b (i, j));
-            complex_result (i, j) = std::pow (atmp, btmp);
-          }
-
-      retval = complex_result;
-    }
-  else
-    {
-      Matrix result (nr, nc);
-
-      for (octave_idx_type j = 0; j < nc; j++)
-        for (octave_idx_type i = 0; i < nr; i++)
-          {
-            octave_quit ();
-            result (i, j) = std::pow (a (i, j), b (i, j));
-          }
-
-      retval = result;
-    }
-
-  return retval;
-}
-
-// -*- 5 -*-
-octave_value
-elem_xpow (const Matrix& a, const Complex& b)
-{
-  octave_idx_type nr = a.rows ();
-  octave_idx_type nc = a.cols ();
-
-  ComplexMatrix result (nr, nc);
-
-  for (octave_idx_type j = 0; j < nc; j++)
-    for (octave_idx_type i = 0; i < nr; i++)
-      {
-        octave_quit ();
-        result (i, j) = std::pow (Complex (a (i, j)), b);
-      }
-
-  return result;
-}
-
-// -*- 6 -*-
-octave_value
-elem_xpow (const Matrix& a, const ComplexMatrix& b)
-{
-  octave_idx_type nr = a.rows ();
-  octave_idx_type nc = a.cols ();
-
-  octave_idx_type b_nr = b.rows ();
-  octave_idx_type b_nc = b.cols ();
-
-  if (nr != b_nr || nc != b_nc)
-    {
-      gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc);
-      return octave_value ();
-    }
-
-  ComplexMatrix result (nr, nc);
-
-  for (octave_idx_type j = 0; j < nc; j++)
-    for (octave_idx_type i = 0; i < nr; i++)
-      {
-        octave_quit ();
-        result (i, j) = std::pow (Complex (a (i, j)), b (i, j));
-      }
-
-  return result;
-}
-
-// -*- 7 -*-
-octave_value
-elem_xpow (const Complex& a, const Matrix& b)
-{
-  octave_idx_type nr = b.rows ();
-  octave_idx_type nc = b.cols ();
-
-  ComplexMatrix result (nr, nc);
-
-  for (octave_idx_type j = 0; j < nc; j++)
-    for (octave_idx_type i = 0; i < nr; i++)
-      {
-        octave_quit ();
-        double btmp = b (i, j);
-        if (xisint (btmp))
-          result (i, j) = std::pow (a, static_cast<int> (btmp));
-        else
-          result (i, j) = std::pow (a, btmp);
-      }
-
-  return result;
-}
-
-// -*- 8 -*-
-octave_value
-elem_xpow (const Complex& a, const ComplexMatrix& b)
-{
-  octave_idx_type nr = b.rows ();
-  octave_idx_type nc = b.cols ();
-
-  ComplexMatrix result (nr, nc);
-
-  for (octave_idx_type j = 0; j < nc; j++)
-    for (octave_idx_type i = 0; i < nr; i++)
-      {
-        octave_quit ();
-        result (i, j) = std::pow (a, b (i, j));
-      }
-
-  return result;
-}
-
-octave_value
-elem_xpow (const Complex& a, const Range& r)
-{
-  octave_value retval;
-
-  // Only optimize powers with ranges that are integer and monotonic in
-  // magnitude.
-  if (r.nelem () > 1 && r.all_elements_are_ints ()
-      && same_sign (r.base (), r.limit ()))
-    {
-      octave_idx_type n = r.nelem ();
-      ComplexMatrix result (1, n);
-
-      if (same_sign (r.base (), r.inc ()))
-        {
-          Complex base = std::pow (a, r.base ());
-          Complex inc = std::pow (a, r.inc ());
-          result(0) = base;
-          for (octave_idx_type i = 1; i < n; i++)
-            result(i) = (base *= inc);
-        }
-      else
-        {
-          // Don't use Range::limit () here.
-          Complex limit = std::pow (a, r.base () + (n-1) * r.inc ());
-          Complex inc = std::pow (a, -r.inc ());
-          result(n-1) = limit;
-          for (octave_idx_type i = n-2; i >= 0; i--)
-            result(i) = (limit *= inc);
-        }
-
-      retval = result;
-    }
-  else
-    retval = elem_xpow (a, r.matrix_value ());
-
-
-  return retval;
-}
-
-// -*- 9 -*-
-octave_value
-elem_xpow (const ComplexMatrix& a, double b)
-{
-  octave_idx_type nr = a.rows ();
-  octave_idx_type nc = a.cols ();
-
-  ComplexMatrix result (nr, nc);
-
-  if (xisint (b))
-    {
-      for (octave_idx_type j = 0; j < nc; j++)
-        for (octave_idx_type i = 0; i < nr; i++)
-          {
-            octave_quit ();
-            result (i, j) = std::pow (a (i, j), static_cast<int> (b));
-          }
-    }
-  else
-    {
-      for (octave_idx_type j = 0; j < nc; j++)
-        for (octave_idx_type i = 0; i < nr; i++)
-          {
-            octave_quit ();
-            result (i, j) = std::pow (a (i, j), b);
-          }
-    }
-
-  return result;
-}
-
-// -*- 10 -*-
-octave_value
-elem_xpow (const ComplexMatrix& a, const Matrix& b)
-{
-  octave_idx_type nr = a.rows ();
-  octave_idx_type nc = a.cols ();
-
-  octave_idx_type b_nr = b.rows ();
-  octave_idx_type b_nc = b.cols ();
-
-  if (nr != b_nr || nc != b_nc)
-    {
-      gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc);
-      return octave_value ();
-    }
-
-  ComplexMatrix result (nr, nc);
-
-  for (octave_idx_type j = 0; j < nc; j++)
-    for (octave_idx_type i = 0; i < nr; i++)
-      {
-        octave_quit ();
-        double btmp = b (i, j);
-        if (xisint (btmp))
-          result (i, j) = std::pow (a (i, j), static_cast<int> (btmp));
-        else
-          result (i, j) = std::pow (a (i, j), btmp);
-      }
-
-  return result;
-}
-
-// -*- 11 -*-
-octave_value
-elem_xpow (const ComplexMatrix& a, const Complex& b)
-{
-  octave_idx_type nr = a.rows ();
-  octave_idx_type nc = a.cols ();
-
-  ComplexMatrix result (nr, nc);
-
-  for (octave_idx_type j = 0; j < nc; j++)
-    for (octave_idx_type i = 0; i < nr; i++)
-      {
-        octave_quit ();
-        result (i, j) = std::pow (a (i, j), b);
-      }
-
-  return result;
-}
-
-// -*- 12 -*-
-octave_value
-elem_xpow (const ComplexMatrix& a, const ComplexMatrix& b)
-{
-  octave_idx_type nr = a.rows ();
-  octave_idx_type nc = a.cols ();
-
-  octave_idx_type b_nr = b.rows ();
-  octave_idx_type b_nc = b.cols ();
-
-  if (nr != b_nr || nc != b_nc)
-    {
-      gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc);
-      return octave_value ();
-    }
-
-  ComplexMatrix result (nr, nc);
-
-  for (octave_idx_type j = 0; j < nc; j++)
-    for (octave_idx_type i = 0; i < nr; i++)
-      {
-        octave_quit ();
-        result (i, j) = std::pow (a (i, j), b (i, j));
-      }
-
-  return result;
-}
-
-// Safer pow functions that work elementwise for N-d arrays.
-//
-//       op2 \ op1:   s   nd  cs   cnd
-//            +--   +---+---+----+----+
-//   scalar   |     | * | 3 |  * |  9 |
-//                  +---+---+----+----+
-//   N_d            | 1 | 4 |  7 | 10 |
-//                  +---+---+----+----+
-//   complex_scalar | * | 5 |  * | 11 |
-//                  +---+---+----+----+
-//   complex_N_d    | 2 | 6 |  8 | 12 |
-//                  +---+---+----+----+
-//
-//   * -> not needed.
-
-// FIXME -- these functions need to be fixed so that things
-// like
-//
-//   a = -1; b = [ 0, 0.5, 1 ]; r = a .^ b
-//
-// and
-//
-//   a = -1; b = [ 0, 0.5, 1 ]; for i = 1:3, r(i) = a .^ b(i), end
-//
-// produce identical results.  Also, it would be nice if -1^0.5
-// produced a pure imaginary result instead of a complex number with a
-// small real part.  But perhaps that's really a problem with the math
-// library...
-
-// -*- 1 -*-
-octave_value
-elem_xpow (double a, const NDArray& b)
-{
-  octave_value retval;
-
-  if (a < 0.0 && ! b.all_integers ())
-    {
-      Complex atmp (a);
-      ComplexNDArray result (b.dims ());
-      for (octave_idx_type i = 0; i < b.length (); i++)
-        {
-          octave_quit ();
-          result(i) = std::pow (atmp, b(i));
-        }
-
-      retval = result;
-    }
-  else
-    {
-      NDArray result (b.dims ());
-      for (octave_idx_type i = 0; i < b.length (); i++)
-        {
-          octave_quit ();
-          result (i) = std::pow (a, b(i));
-        }
-
-      retval = result;
-    }
-
-  return retval;
-}
-
-// -*- 2 -*-
-octave_value
-elem_xpow (double a, const ComplexNDArray& b)
-{
-  ComplexNDArray result (b.dims ());
-
-  for (octave_idx_type i = 0; i < b.length (); i++)
-    {
-      octave_quit ();
-      result(i) = std::pow (a, b(i));
-    }
-
-  return result;
-}
-
-// -*- 3 -*-
-octave_value
-elem_xpow (const NDArray& a, double b)
-{
-  octave_value retval;
-
-  if (! xisint (b))
-    {
-      if (a.any_element_is_negative ())
-        {
-          ComplexNDArray result (a.dims ());
-
-          for (octave_idx_type i = 0; i < a.length (); i++)
-            {
-              octave_quit ();
-
-              Complex atmp (a (i));
-
-              result(i) = std::pow (atmp, b);
-            }
-
-          retval = result;
-        }
-      else
-        {
-          NDArray result (a.dims ());
-          for (octave_idx_type i = 0; i < a.length (); i++)
-            {
-              octave_quit ();
-              result(i) = std::pow (a(i), b);
-            }
-
-          retval = result;
-        }
-    }
-  else
-    {
-      NoAlias<NDArray> result (a.dims ());
-
-      int ib = static_cast<int> (b);
-      if (ib == 2)
-        {
-          for (octave_idx_type i = 0; i < a.length (); i++)
-            result(i) = a(i) * a(i);
-        }
-      else if (ib == 3)
-        {
-          for (octave_idx_type i = 0; i < a.length (); i++)
-            result(i) = a(i) * a(i) * a(i);
-        }
-      else if (ib == -1)
-        {
-          for (octave_idx_type i = 0; i < a.length (); i++)
-            result(i) = 1.0 / a(i);
-        }
-      else
-        {
-          for (octave_idx_type i = 0; i < a.length (); i++)
-            {
-              octave_quit ();
-              result(i) = std::pow (a(i), ib);
-            }
-        }
-
-      retval = result;
-    }
-
-  return retval;
-}
-
-// -*- 4 -*-
-octave_value
-elem_xpow (const NDArray& a, const NDArray& b)
-{
-  octave_value retval;
-
-  dim_vector a_dims = a.dims ();
-  dim_vector b_dims = b.dims ();
-
-  if (a_dims != b_dims)
-    {
-      if (is_valid_bsxfun ("operator .^", a_dims, b_dims))
-        {
-          //Potentially complex results
-          NDArray xa = octave_value_extract<NDArray> (a);
-          NDArray xb = octave_value_extract<NDArray> (b);
-          if (! xb.all_integers () && xa.any_element_is_negative ())
-            return octave_value (bsxfun_pow (ComplexNDArray (xa), xb));
-          else
-            return octave_value (bsxfun_pow (xa, xb));
-        }
-      else
-        {
-          gripe_nonconformant ("operator .^", a_dims, b_dims);
-          return octave_value ();
-        }
-    }
-
-  int len = a.length ();
-
-  bool convert_to_complex = false;
-
-  for (octave_idx_type i = 0; i < len; i++)
-    {
-      octave_quit ();
-      double atmp = a(i);
-      double btmp = b(i);
-      if (atmp < 0.0 && static_cast<int> (btmp) != btmp)
-        {
-          convert_to_complex = true;
-          goto done;
-        }
-    }
-
-done:
-
-  if (convert_to_complex)
-    {
-      ComplexNDArray complex_result (a_dims);
-
-      for (octave_idx_type i = 0; i < len; i++)
-        {
-          octave_quit ();
-          Complex atmp (a(i));
-          complex_result(i) = std::pow (atmp, b(i));
-        }
-
-      retval = complex_result;
-    }
-  else
-    {
-      NDArray result (a_dims);
-
-      for (octave_idx_type i = 0; i < len; i++)
-        {
-          octave_quit ();
-          result(i) = std::pow (a(i), b(i));
-        }
-
-      retval = result;
-    }
-
-  return retval;
-}
-
-// -*- 5 -*-
-octave_value
-elem_xpow (const NDArray& a, const Complex& b)
-{
-  ComplexNDArray result (a.dims ());
-
-  for (octave_idx_type i = 0; i < a.length (); i++)
-    {
-      octave_quit ();
-      result(i) = std::pow (a(i), b);
-    }
-
-  return result;
-}
-
-// -*- 6 -*-
-octave_value
-elem_xpow (const NDArray& a, const ComplexNDArray& b)
-{
-  dim_vector a_dims = a.dims ();
-  dim_vector b_dims = b.dims ();
-
-  if (a_dims != b_dims)
-    {
-      if (is_valid_bsxfun ("operator .^", a_dims, b_dims))
-        {
-          return bsxfun_pow (a, b);
-        }
-      else
-        {
-          gripe_nonconformant ("operator .^", a_dims, b_dims);
-          return octave_value ();
-        }
-    }
-
-  ComplexNDArray result (a_dims);
-
-  for (octave_idx_type i = 0; i < a.length (); i++)
-    {
-      octave_quit ();
-      result(i) = std::pow (a(i), b(i));
-    }
-
-  return result;
-}
-
-// -*- 7 -*-
-octave_value
-elem_xpow (const Complex& a, const NDArray& b)
-{
-  ComplexNDArray result (b.dims ());
-
-  for (octave_idx_type i = 0; i < b.length (); i++)
-    {
-      octave_quit ();
-      double btmp = b(i);
-      if (xisint (btmp))
-        result(i) = std::pow (a, static_cast<int> (btmp));
-      else
-        result(i) = std::pow (a, btmp);
-    }
-
-  return result;
-}
-
-// -*- 8 -*-
-octave_value
-elem_xpow (const Complex& a, const ComplexNDArray& b)
-{
-  ComplexNDArray result (b.dims ());
-
-  for (octave_idx_type i = 0; i < b.length (); i++)
-    {
-      octave_quit ();
-      result(i) = std::pow (a, b(i));
-    }
-
-  return result;
-}
-
-// -*- 9 -*-
-octave_value
-elem_xpow (const ComplexNDArray& a, double b)
-{
-  ComplexNDArray result (a.dims ());
-
-  if (xisint (b))
-    {
-      if (b == -1)
-        {
-          for (octave_idx_type i = 0; i < a.length (); i++)
-            result.xelem (i) = 1.0 / a(i);
-        }
-      else
-        {
-          for (octave_idx_type i = 0; i < a.length (); i++)
-            {
-              octave_quit ();
-              result(i) = std::pow (a(i), static_cast<int> (b));
-            }
-        }
-    }
-  else
-    {
-      for (octave_idx_type i = 0; i < a.length (); i++)
-        {
-          octave_quit ();
-          result(i) = std::pow (a(i), b);
-        }
-    }
-
-  return result;
-}
-
-// -*- 10 -*-
-octave_value
-elem_xpow (const ComplexNDArray& a, const NDArray& b)
-{
-  dim_vector a_dims = a.dims ();
-  dim_vector b_dims = b.dims ();
-
-  if (a_dims != b_dims)
-    {
-      if (is_valid_bsxfun ("operator .^", a_dims, b_dims))
-        {
-          return bsxfun_pow (a, b);
-        }
-      else
-        {
-          gripe_nonconformant ("operator .^", a_dims, b_dims);
-          return octave_value ();
-        }
-    }
-
-  ComplexNDArray result (a_dims);
-
-  for (octave_idx_type i = 0; i < a.length (); i++)
-    {
-      octave_quit ();
-      double btmp = b(i);
-      if (xisint (btmp))
-        result(i) = std::pow (a(i), static_cast<int> (btmp));
-      else
-        result(i) = std::pow (a(i), btmp);
-    }
-
-  return result;
-}
-
-// -*- 11 -*-
-octave_value
-elem_xpow (const ComplexNDArray& a, const Complex& b)
-{
-  ComplexNDArray result (a.dims ());
-
-  for (octave_idx_type i = 0; i < a.length (); i++)
-    {
-      octave_quit ();
-      result(i) = std::pow (a(i), b);
-    }
-
-  return result;
-}
-
-// -*- 12 -*-
-octave_value
-elem_xpow (const ComplexNDArray& a, const ComplexNDArray& b)
-{
-  dim_vector a_dims = a.dims ();
-  dim_vector b_dims = b.dims ();
-
-  if (a_dims != b_dims)
-    {
-      if (is_valid_bsxfun ("operator .^", a_dims, b_dims))
-        {
-          return bsxfun_pow (a, b);
-        }
-      else
-        {
-          gripe_nonconformant ("operator .^", a_dims, b_dims);
-          return octave_value ();
-        }
-    }
-
-  ComplexNDArray result (a_dims);
-
-  for (octave_idx_type i = 0; i < a.length (); i++)
-    {
-      octave_quit ();
-      result(i) = std::pow (a(i), b(i));
-    }
-
-  return result;
-}
-
-static inline int
-xisint (float x)
-{
-  return (D_NINT (x) == x
-          && ((x >= 0 && x < INT_MAX)
-              || (x <= 0 && x > INT_MIN)));
-}
-
-// Safer pow functions.
-//
-//       op2 \ op1:   s   m   cs   cm
-//            +--   +---+---+----+----+
-//   scalar   |     | 1 | 5 |  7 | 11 |
-//                  +---+---+----+----+
-//   matrix         | 2 | * |  8 |  * |
-//                  +---+---+----+----+
-//   complex_scalar | 3 | 6 |  9 | 12 |
-//                  +---+---+----+----+
-//   complex_matrix | 4 | * | 10 |  * |
-//                  +---+---+----+----+
-
-// -*- 1 -*-
-octave_value
-xpow (float a, float b)
-{
-  float retval;
-
-  if (a < 0.0 && ! xisint (b))
-    {
-      FloatComplex atmp (a);
-
-      return std::pow (atmp, b);
-    }
-  else
-    retval = std::pow (a, b);
-
-  return retval;
-}
-
-// -*- 2 -*-
-octave_value
-xpow (float a, const FloatMatrix& b)
-{
-  octave_value retval;
-
-  octave_idx_type nr = b.rows ();
-  octave_idx_type nc = b.cols ();
-
-  if (nr == 0 || nc == 0 || nr != nc)
-    error ("for x^A, A must be a square matrix");
-  else
-    {
-      FloatEIG b_eig (b);
-
-      if (! error_state)
-        {
-          FloatComplexColumnVector lambda (b_eig.eigenvalues ());
-          FloatComplexMatrix Q (b_eig.eigenvectors ());
-
-          for (octave_idx_type i = 0; i < nr; i++)
-            {
-              FloatComplex elt = lambda(i);
-              if (std::imag (elt) == 0.0)
-                lambda(i) = std::pow (a, std::real (elt));
-              else
-                lambda(i) = std::pow (a, elt);
-            }
-          FloatComplexDiagMatrix D (lambda);
-
-          FloatComplexMatrix C = Q * D * Q.inverse ();
-
-          if (a > 0)
-            retval = real (C);
-          else
-            retval = C;
-        }
-      else
-        error ("xpow: matrix diagonalization failed");
-    }
-
-  return retval;
-}
-
-// -*- 3 -*-
-octave_value
-xpow (float a, const FloatComplex& b)
-{
-  FloatComplex result = std::pow (a, b);
-  return result;
-}
-
-// -*- 4 -*-
-octave_value
-xpow (float a, const FloatComplexMatrix& b)
-{
-  octave_value retval;
-
-  octave_idx_type nr = b.rows ();
-  octave_idx_type nc = b.cols ();
-
-  if (nr == 0 || nc == 0 || nr != nc)
-    error ("for x^A, A must be a square matrix");
-  else
-    {
-      FloatEIG b_eig (b);
-
-      if (! error_state)
-        {
-          FloatComplexColumnVector lambda (b_eig.eigenvalues ());
-          FloatComplexMatrix Q (b_eig.eigenvectors ());
-
-          for (octave_idx_type i = 0; i < nr; i++)
-            {
-              FloatComplex elt = lambda(i);
-              if (std::imag (elt) == 0.0)
-                lambda(i) = std::pow (a, std::real (elt));
-              else
-                lambda(i) = std::pow (a, elt);
-            }
-          FloatComplexDiagMatrix D (lambda);
-
-          retval = FloatComplexMatrix (Q * D * Q.inverse ());
-        }
-      else
-        error ("xpow: matrix diagonalization failed");
-    }
-
-  return retval;
-}
-
-// -*- 5 -*-
-octave_value
-xpow (const FloatMatrix& a, float b)
-{
-  octave_value retval;
-
-  octave_idx_type nr = a.rows ();
-  octave_idx_type nc = a.cols ();
-
-  if (nr == 0 || nc == 0 || nr != nc)
-    error ("for A^b, A must be a square matrix");
-  else
-    {
-      if (static_cast<int> (b) == b)
-        {
-          int btmp = static_cast<int> (b);
-          if (btmp == 0)
-            {
-              retval = FloatDiagMatrix (nr, nr, 1.0);
-            }
-          else
-            {
-              // Too much copying?
-              // FIXME -- we shouldn't do this if the exponent is
-              // large...
-
-              FloatMatrix atmp;
-              if (btmp < 0)
-                {
-                  btmp = -btmp;
-
-                  octave_idx_type info;
-                  float rcond = 0.0;
-                  MatrixType mattype (a);
-
-                  atmp = a.inverse (mattype, info, rcond, 1);
-
-                  if (info == -1)
-                    warning ("inverse: matrix singular to machine\
- precision, rcond = %g", rcond);
-                }
-              else
-                atmp = a;
-
-              FloatMatrix result (atmp);
-
-              btmp--;
-
-              while (btmp > 0)
-                {
-                  if (btmp & 1)
-                    result = result * atmp;
-
-                  btmp >>= 1;
-
-                  if (btmp > 0)
-                    atmp = atmp * atmp;
-                }
-
-              retval = result;
-            }
-        }
-      else
-        {
-          FloatEIG a_eig (a);
-
-          if (! error_state)
-            {
-              FloatComplexColumnVector lambda (a_eig.eigenvalues ());
-              FloatComplexMatrix Q (a_eig.eigenvectors ());
-
-              for (octave_idx_type i = 0; i < nr; i++)
-                lambda(i) = std::pow (lambda(i), b);
-
-              FloatComplexDiagMatrix D (lambda);
-
-              retval = FloatComplexMatrix (Q * D * Q.inverse ());
-            }
-          else
-            error ("xpow: matrix diagonalization failed");
-        }
-    }
-
-  return retval;
-}
-
-// -*- 5d -*-
-octave_value
-xpow (const FloatDiagMatrix& a, float b)
-{
-  octave_value retval;
-
-  octave_idx_type nr = a.rows ();
-  octave_idx_type nc = a.cols ();
-
-  if (nr == 0 || nc == 0 || nr != nc)
-    error ("for A^b, A must be a square matrix");
-  else
-    {
-      if (static_cast<int> (b) == b)
-        {
-          FloatDiagMatrix r (nr, nc);
-          for (octave_idx_type i = 0; i < nc; i++)
-            r.dgelem (i) = std::pow (a.dgelem (i), b);
-          retval = r;
-        }
-      else
-        {
-          FloatComplexDiagMatrix r (nr, nc);
-          for (octave_idx_type i = 0; i < nc; i++)
-            r.dgelem (i) = std::pow (static_cast<FloatComplex> (a.dgelem (i)), b);
-          retval = r;
-        }
-    }
-
-  return retval;
-}
-
-// -*- 6 -*-
-octave_value
-xpow (const FloatMatrix& a, const FloatComplex& b)
-{
-  octave_value retval;
-
-  octave_idx_type nr = a.rows ();
-  octave_idx_type nc = a.cols ();
-
-  if (nr == 0 || nc == 0 || nr != nc)
-    error ("for A^b, A must be a square matrix");
-  else
-    {
-      FloatEIG a_eig (a);
-
-      if (! error_state)
-        {
-          FloatComplexColumnVector lambda (a_eig.eigenvalues ());
-          FloatComplexMatrix Q (a_eig.eigenvectors ());
-
-          for (octave_idx_type i = 0; i < nr; i++)
-            lambda(i) = std::pow (lambda(i), b);
-
-          FloatComplexDiagMatrix D (lambda);
-
-          retval = FloatComplexMatrix (Q * D * Q.inverse ());
-        }
-      else
-        error ("xpow: matrix diagonalization failed");
-    }
-
-  return retval;
-}
-
-// -*- 7 -*-
-octave_value
-xpow (const FloatComplex& a, float b)
-{
-  FloatComplex result;
-
-  if (xisint (b))
-    result = std::pow (a, static_cast<int> (b));
-  else
-    result = std::pow (a, b);
-
-  return result;
-}
-
-// -*- 8 -*-
-octave_value
-xpow (const FloatComplex& a, const FloatMatrix& b)
-{
-  octave_value retval;
-
-  octave_idx_type nr = b.rows ();
-  octave_idx_type nc = b.cols ();
-
-  if (nr == 0 || nc == 0 || nr != nc)
-    error ("for x^A, A must be a square matrix");
-  else
-    {
-      FloatEIG b_eig (b);
-
-      if (! error_state)
-        {
-          FloatComplexColumnVector lambda (b_eig.eigenvalues ());
-          FloatComplexMatrix Q (b_eig.eigenvectors ());
-
-          for (octave_idx_type i = 0; i < nr; i++)
-            {
-              FloatComplex elt = lambda(i);
-              if (std::imag (elt) == 0.0)
-                lambda(i) = std::pow (a, std::real (elt));
-              else
-                lambda(i) = std::pow (a, elt);
-            }
-          FloatComplexDiagMatrix D (lambda);
-
-          retval = FloatComplexMatrix (Q * D * Q.inverse ());
-        }
-      else
-        error ("xpow: matrix diagonalization failed");
-    }
-
-  return retval;
-}
-
-// -*- 9 -*-
-octave_value
-xpow (const FloatComplex& a, const FloatComplex& b)
-{
-  FloatComplex result;
-  result = std::pow (a, b);
-  return result;
-}
-
-// -*- 10 -*-
-octave_value
-xpow (const FloatComplex& a, const FloatComplexMatrix& b)
-{
-  octave_value retval;
-
-  octave_idx_type nr = b.rows ();
-  octave_idx_type nc = b.cols ();
-
-  if (nr == 0 || nc == 0 || nr != nc)
-    error ("for x^A, A must be a square matrix");
-  else
-    {
-      FloatEIG b_eig (b);
-
-      if (! error_state)
-        {
-          FloatComplexColumnVector lambda (b_eig.eigenvalues ());
-          FloatComplexMatrix Q (b_eig.eigenvectors ());
-
-          for (octave_idx_type i = 0; i < nr; i++)
-            {
-              FloatComplex elt = lambda(i);
-              if (std::imag (elt) == 0.0)
-                lambda(i) = std::pow (a, std::real (elt));
-              else
-                lambda(i) = std::pow (a, elt);
-            }
-          FloatComplexDiagMatrix D (lambda);
-
-          retval = FloatComplexMatrix (Q * D * Q.inverse ());
-        }
-      else
-        error ("xpow: matrix diagonalization failed");
-    }
-
-  return retval;
-}
-
-// -*- 11 -*-
-octave_value
-xpow (const FloatComplexMatrix& a, float b)
-{
-  octave_value retval;
-
-  octave_idx_type nr = a.rows ();
-  octave_idx_type nc = a.cols ();
-
-  if (nr == 0 || nc == 0 || nr != nc)
-    error ("for A^b, A must be a square matrix");
-  else
-    {
-      if (static_cast<int> (b) == b)
-        {
-          int btmp = static_cast<int> (b);
-          if (btmp == 0)
-            {
-              retval = FloatDiagMatrix (nr, nr, 1.0);
-            }
-          else
-            {
-              // Too much copying?
-              // FIXME -- we shouldn't do this if the exponent is
-              // large...
-
-              FloatComplexMatrix atmp;
-              if (btmp < 0)
-                {
-                  btmp = -btmp;
-
-                  octave_idx_type info;
-                  float rcond = 0.0;
-                  MatrixType mattype (a);
-
-                  atmp = a.inverse (mattype, info, rcond, 1);
-
-                  if (info == -1)
-                    warning ("inverse: matrix singular to machine\
- precision, rcond = %g", rcond);
-                }
-              else
-                atmp = a;
-
-              FloatComplexMatrix result (atmp);
-
-              btmp--;
-
-              while (btmp > 0)
-                {
-                  if (btmp & 1)
-                    result = result * atmp;
-
-                  btmp >>= 1;
-
-                  if (btmp > 0)
-                    atmp = atmp * atmp;
-                }
-
-              retval = result;
-            }
-        }
-      else
-        {
-          FloatEIG a_eig (a);
-
-          if (! error_state)
-            {
-              FloatComplexColumnVector lambda (a_eig.eigenvalues ());
-              FloatComplexMatrix Q (a_eig.eigenvectors ());
-
-              for (octave_idx_type i = 0; i < nr; i++)
-                lambda(i) = std::pow (lambda(i), b);
-
-              FloatComplexDiagMatrix D (lambda);
-
-              retval = FloatComplexMatrix (Q * D * Q.inverse ());
-            }
-          else
-            error ("xpow: matrix diagonalization failed");
-        }
-    }
-
-  return retval;
-}
-
-// -*- 12 -*-
-octave_value
-xpow (const FloatComplexMatrix& a, const FloatComplex& b)
-{
-  octave_value retval;
-
-  octave_idx_type nr = a.rows ();
-  octave_idx_type nc = a.cols ();
-
-  if (nr == 0 || nc == 0 || nr != nc)
-    error ("for A^b, A must be a square matrix");
-  else
-    {
-      FloatEIG a_eig (a);
-
-      if (! error_state)
-        {
-          FloatComplexColumnVector lambda (a_eig.eigenvalues ());
-          FloatComplexMatrix Q (a_eig.eigenvectors ());
-
-          for (octave_idx_type i = 0; i < nr; i++)
-            lambda(i) = std::pow (lambda(i), b);
-
-          FloatComplexDiagMatrix D (lambda);
-
-          retval = FloatComplexMatrix (Q * D * Q.inverse ());
-        }
-      else
-        error ("xpow: matrix diagonalization failed");
-    }
-
-  return retval;
-}
-
-// -*- 12d -*-
-octave_value
-xpow (const FloatComplexDiagMatrix& a, const FloatComplex& b)
-{
-  octave_value retval;
-
-  octave_idx_type nr = a.rows ();
-  octave_idx_type nc = a.cols ();
-
-  if (nr == 0 || nc == 0 || nr != nc)
-    error ("for A^b, A must be a square matrix");
-  else
-    {
-      FloatComplexDiagMatrix r (nr, nc);
-      for (octave_idx_type i = 0; i < nc; i++)
-        r(i, i) = std::pow (a(i, i), b);
-      retval = r;
-    }
-
-  return retval;
-}
-
-// mixed
-octave_value
-xpow (const FloatComplexDiagMatrix& a, float b)
-{
-  return xpow (a, static_cast<FloatComplex> (b));
-}
-
-octave_value
-xpow (const FloatDiagMatrix& a, const FloatComplex& b)
-{
-  return xpow (FloatComplexDiagMatrix (a), b);
-}
-
-// Safer pow functions that work elementwise for matrices.
-//
-//       op2 \ op1:   s   m   cs   cm
-//            +--   +---+---+----+----+
-//   scalar   |     | * | 3 |  * |  9 |
-//                  +---+---+----+----+
-//   matrix         | 1 | 4 |  7 | 10 |
-//                  +---+---+----+----+
-//   complex_scalar | * | 5 |  * | 11 |
-//                  +---+---+----+----+
-//   complex_matrix | 2 | 6 |  8 | 12 |
-//                  +---+---+----+----+
-//
-//   * -> not needed.
-
-// FIXME -- these functions need to be fixed so that things
-// like
-//
-//   a = -1; b = [ 0, 0.5, 1 ]; r = a .^ b
-//
-// and
-//
-//   a = -1; b = [ 0, 0.5, 1 ]; for i = 1:3, r(i) = a .^ b(i), end
-//
-// produce identical results.  Also, it would be nice if -1^0.5
-// produced a pure imaginary result instead of a complex number with a
-// small real part.  But perhaps that's really a problem with the math
-// library...
-
-// -*- 1 -*-
-octave_value
-elem_xpow (float a, const FloatMatrix& b)
-{
-  octave_value retval;
-
-  octave_idx_type nr = b.rows ();
-  octave_idx_type nc = b.cols ();
-
-  float d1, d2;
-
-  if (a < 0.0 && ! b.all_integers (d1, d2))
-    {
-      FloatComplex atmp (a);
-      FloatComplexMatrix result (nr, nc);
-
-      for (octave_idx_type j = 0; j < nc; j++)
-        for (octave_idx_type i = 0; i < nr; i++)
-          {
-            octave_quit ();
-            result (i, j) = std::pow (atmp, b (i, j));
-          }
-
-      retval = result;
-    }
-  else
-    {
-      FloatMatrix result (nr, nc);
-
-      for (octave_idx_type j = 0; j < nc; j++)
-        for (octave_idx_type i = 0; i < nr; i++)
-          {
-            octave_quit ();
-            result (i, j) = std::pow (a, b (i, j));
-          }
-
-      retval = result;
-    }
-
-  return retval;
-}
-
-// -*- 2 -*-
-octave_value
-elem_xpow (float a, const FloatComplexMatrix& b)
-{
-  octave_idx_type nr = b.rows ();
-  octave_idx_type nc = b.cols ();
-
-  FloatComplexMatrix result (nr, nc);
-  FloatComplex atmp (a);
-
-  for (octave_idx_type j = 0; j < nc; j++)
-    for (octave_idx_type i = 0; i < nr; i++)
-      {
-        octave_quit ();
-        result (i, j) = std::pow (atmp, b (i, j));
-      }
-
-  return result;
-}
-
-// -*- 3 -*-
-octave_value
-elem_xpow (const FloatMatrix& a, float b)
-{
-  octave_value retval;
-
-  octave_idx_type nr = a.rows ();
-  octave_idx_type nc = a.cols ();
-
-  if (! xisint (b) && a.any_element_is_negative ())
-    {
-      FloatComplexMatrix result (nr, nc);
-
-      for (octave_idx_type j = 0; j < nc; j++)
-        for (octave_idx_type i = 0; i < nr; i++)
-          {
-            octave_quit ();
-
-            FloatComplex atmp (a (i, j));
-
-            result (i, j) = std::pow (atmp, b);
-          }
-
-      retval = result;
-    }
-  else
-    {
-      FloatMatrix result (nr, nc);
-
-      for (octave_idx_type j = 0; j < nc; j++)
-        for (octave_idx_type i = 0; i < nr; i++)
-          {
-            octave_quit ();
-            result (i, j) = std::pow (a (i, j), b);
-          }
-
-      retval = result;
-    }
-
-  return retval;
-}
-
-// -*- 4 -*-
-octave_value
-elem_xpow (const FloatMatrix& a, const FloatMatrix& b)
-{
-  octave_value retval;
-
-  octave_idx_type nr = a.rows ();
-  octave_idx_type nc = a.cols ();
-
-  octave_idx_type b_nr = b.rows ();
-  octave_idx_type b_nc = b.cols ();
-
-  if (nr != b_nr || nc != b_nc)
-    {
-      gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc);
-      return octave_value ();
-    }
-
-  int convert_to_complex = 0;
-  for (octave_idx_type j = 0; j < nc; j++)
-    for (octave_idx_type i = 0; i < nr; i++)
-      {
-        octave_quit ();
-        float atmp = a (i, j);
-        float btmp = b (i, j);
-        if (atmp < 0.0 && static_cast<int> (btmp) != btmp)
-          {
-            convert_to_complex = 1;
-            goto done;
-          }
-      }
-
-done:
-
-  if (convert_to_complex)
-    {
-      FloatComplexMatrix complex_result (nr, nc);
-
-      for (octave_idx_type j = 0; j < nc; j++)
-        for (octave_idx_type i = 0; i < nr; i++)
-          {
-            octave_quit ();
-            FloatComplex atmp (a (i, j));
-            FloatComplex btmp (b (i, j));
-            complex_result (i, j) = std::pow (atmp, btmp);
-          }
-
-      retval = complex_result;
-    }
-  else
-    {
-      FloatMatrix result (nr, nc);
-
-      for (octave_idx_type j = 0; j < nc; j++)
-        for (octave_idx_type i = 0; i < nr; i++)
-          {
-            octave_quit ();
-            result (i, j) = std::pow (a (i, j), b (i, j));
-          }
-
-      retval = result;
-    }
-
-  return retval;
-}
-
-// -*- 5 -*-
-octave_value
-elem_xpow (const FloatMatrix& a, const FloatComplex& b)
-{
-  octave_idx_type nr = a.rows ();
-  octave_idx_type nc = a.cols ();
-
-  FloatComplexMatrix result (nr, nc);
-
-  for (octave_idx_type j = 0; j < nc; j++)
-    for (octave_idx_type i = 0; i < nr; i++)
-      {
-        octave_quit ();
-        result (i, j) = std::pow (FloatComplex (a (i, j)), b);
-      }
-
-  return result;
-}
-
-// -*- 6 -*-
-octave_value
-elem_xpow (const FloatMatrix& a, const FloatComplexMatrix& b)
-{
-  octave_idx_type nr = a.rows ();
-  octave_idx_type nc = a.cols ();
-
-  octave_idx_type b_nr = b.rows ();
-  octave_idx_type b_nc = b.cols ();
-
-  if (nr != b_nr || nc != b_nc)
-    {
-      gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc);
-      return octave_value ();
-    }
-
-  FloatComplexMatrix result (nr, nc);
-
-  for (octave_idx_type j = 0; j < nc; j++)
-    for (octave_idx_type i = 0; i < nr; i++)
-      {
-        octave_quit ();
-        result (i, j) = std::pow (FloatComplex (a (i, j)), b (i, j));
-      }
-
-  return result;
-}
-
-// -*- 7 -*-
-octave_value
-elem_xpow (const FloatComplex& a, const FloatMatrix& b)
-{
-  octave_idx_type nr = b.rows ();
-  octave_idx_type nc = b.cols ();
-
-  FloatComplexMatrix result (nr, nc);
-
-  for (octave_idx_type j = 0; j < nc; j++)
-    for (octave_idx_type i = 0; i < nr; i++)
-      {
-        octave_quit ();
-        float btmp = b (i, j);
-        if (xisint (btmp))
-          result (i, j) = std::pow (a, static_cast<int> (btmp));
-        else
-          result (i, j) = std::pow (a, btmp);
-      }
-
-  return result;
-}
-
-// -*- 8 -*-
-octave_value
-elem_xpow (const FloatComplex& a, const FloatComplexMatrix& b)
-{
-  octave_idx_type nr = b.rows ();
-  octave_idx_type nc = b.cols ();
-
-  FloatComplexMatrix result (nr, nc);
-
-  for (octave_idx_type j = 0; j < nc; j++)
-    for (octave_idx_type i = 0; i < nr; i++)
-      {
-        octave_quit ();
-        result (i, j) = std::pow (a, b (i, j));
-      }
-
-  return result;
-}
-
-// -*- 9 -*-
-octave_value
-elem_xpow (const FloatComplexMatrix& a, float b)
-{
-  octave_idx_type nr = a.rows ();
-  octave_idx_type nc = a.cols ();
-
-  FloatComplexMatrix result (nr, nc);
-
-  if (xisint (b))
-    {
-      for (octave_idx_type j = 0; j < nc; j++)
-        for (octave_idx_type i = 0; i < nr; i++)
-          {
-            octave_quit ();
-            result (i, j) = std::pow (a (i, j), static_cast<int> (b));
-          }
-    }
-  else
-    {
-      for (octave_idx_type j = 0; j < nc; j++)
-        for (octave_idx_type i = 0; i < nr; i++)
-          {
-            octave_quit ();
-            result (i, j) = std::pow (a (i, j), b);
-          }
-    }
-
-  return result;
-}
-
-// -*- 10 -*-
-octave_value
-elem_xpow (const FloatComplexMatrix& a, const FloatMatrix& b)
-{
-  octave_idx_type nr = a.rows ();
-  octave_idx_type nc = a.cols ();
-
-  octave_idx_type b_nr = b.rows ();
-  octave_idx_type b_nc = b.cols ();
-
-  if (nr != b_nr || nc != b_nc)
-    {
-      gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc);
-      return octave_value ();
-    }
-
-  FloatComplexMatrix result (nr, nc);
-
-  for (octave_idx_type j = 0; j < nc; j++)
-    for (octave_idx_type i = 0; i < nr; i++)
-      {
-        octave_quit ();
-        float btmp = b (i, j);
-        if (xisint (btmp))
-          result (i, j) = std::pow (a (i, j), static_cast<int> (btmp));
-        else
-          result (i, j) = std::pow (a (i, j), btmp);
-      }
-
-  return result;
-}
-
-// -*- 11 -*-
-octave_value
-elem_xpow (const FloatComplexMatrix& a, const FloatComplex& b)
-{
-  octave_idx_type nr = a.rows ();
-  octave_idx_type nc = a.cols ();
-
-  FloatComplexMatrix result (nr, nc);
-
-  for (octave_idx_type j = 0; j < nc; j++)
-    for (octave_idx_type i = 0; i < nr; i++)
-      {
-        octave_quit ();
-        result (i, j) = std::pow (a (i, j), b);
-      }
-
-  return result;
-}
-
-// -*- 12 -*-
-octave_value
-elem_xpow (const FloatComplexMatrix& a, const FloatComplexMatrix& b)
-{
-  octave_idx_type nr = a.rows ();
-  octave_idx_type nc = a.cols ();
-
-  octave_idx_type b_nr = b.rows ();
-  octave_idx_type b_nc = b.cols ();
-
-  if (nr != b_nr || nc != b_nc)
-    {
-      gripe_nonconformant ("operator .^", nr, nc, b_nr, b_nc);
-      return octave_value ();
-    }
-
-  FloatComplexMatrix result (nr, nc);
-
-  for (octave_idx_type j = 0; j < nc; j++)
-    for (octave_idx_type i = 0; i < nr; i++)
-      {
-        octave_quit ();
-        result (i, j) = std::pow (a (i, j), b (i, j));
-      }
-
-  return result;
-}
-
-// Safer pow functions that work elementwise for N-d arrays.
-//
-//       op2 \ op1:   s   nd  cs   cnd
-//            +--   +---+---+----+----+
-//   scalar   |     | * | 3 |  * |  9 |
-//                  +---+---+----+----+
-//   N_d            | 1 | 4 |  7 | 10 |
-//                  +---+---+----+----+
-//   complex_scalar | * | 5 |  * | 11 |
-//                  +---+---+----+----+
-//   complex_N_d    | 2 | 6 |  8 | 12 |
-//                  +---+---+----+----+
-//
-//   * -> not needed.
-
-// FIXME -- these functions need to be fixed so that things
-// like
-//
-//   a = -1; b = [ 0, 0.5, 1 ]; r = a .^ b
-//
-// and
-//
-//   a = -1; b = [ 0, 0.5, 1 ]; for i = 1:3, r(i) = a .^ b(i), end
-//
-// produce identical results.  Also, it would be nice if -1^0.5
-// produced a pure imaginary result instead of a complex number with a
-// small real part.  But perhaps that's really a problem with the math
-// library...
-
-// -*- 1 -*-
-octave_value
-elem_xpow (float a, const FloatNDArray& b)
-{
-  octave_value retval;
-
-  if (a < 0.0 && ! b.all_integers ())
-    {
-      FloatComplex atmp (a);
-      FloatComplexNDArray result (b.dims ());
-      for (octave_idx_type i = 0; i < b.length (); i++)
-        {
-          octave_quit ();
-          result(i) = std::pow (atmp, b(i));
-        }
-
-      retval = result;
-    }
-  else
-    {
-      FloatNDArray result (b.dims ());
-      for (octave_idx_type i = 0; i < b.length (); i++)
-        {
-          octave_quit ();
-          result (i) = std::pow (a, b(i));
-        }
-
-      retval = result;
-    }
-
-  return retval;
-}
-
-// -*- 2 -*-
-octave_value
-elem_xpow (float a, const FloatComplexNDArray& b)
-{
-  FloatComplexNDArray result (b.dims ());
-
-  for (octave_idx_type i = 0; i < b.length (); i++)
-    {
-      octave_quit ();
-      result(i) = std::pow (a, b(i));
-    }
-
-  return result;
-}
-
-// -*- 3 -*-
-octave_value
-elem_xpow (const FloatNDArray& a, float b)
-{
-  octave_value retval;
-
-  if (! xisint (b))
-    {
-      if (a.any_element_is_negative ())
-        {
-          FloatComplexNDArray result (a.dims ());
-
-          for (octave_idx_type i = 0; i < a.length (); i++)
-            {
-              octave_quit ();
-
-              FloatComplex atmp (a (i));
-
-              result(i) = std::pow (atmp, b);
-            }
-
-          retval = result;
-        }
-      else
-        {
-          FloatNDArray result (a.dims ());
-          for (octave_idx_type i = 0; i < a.length (); i++)
-            {
-              octave_quit ();
-              result(i) = std::pow (a(i), b);
-            }
-
-          retval = result;
-        }
-    }
-  else
-    {
-      NoAlias<FloatNDArray> result (a.dims ());
-
-      int ib = static_cast<int> (b);
-      if (ib == 2)
-        {
-          for (octave_idx_type i = 0; i < a.length (); i++)
-            result(i) = a(i) * a(i);
-        }
-      else if (ib == 3)
-        {
-          for (octave_idx_type i = 0; i < a.length (); i++)
-            result(i) = a(i) * a(i) * a(i);
-        }
-      else if (ib == -1)
-        {
-          for (octave_idx_type i = 0; i < a.length (); i++)
-            result(i) = 1.0f / a(i);
-        }
-      else
-        {
-          for (octave_idx_type i = 0; i < a.length (); i++)
-            {
-              octave_quit ();
-              result(i) = std::pow (a(i), ib);
-            }
-        }
-
-      retval = result;
-    }
-
-  return retval;
-}
-
-// -*- 4 -*-
-octave_value
-elem_xpow (const FloatNDArray& a, const FloatNDArray& b)
-{
-  octave_value retval;
-
-  dim_vector a_dims = a.dims ();
-  dim_vector b_dims = b.dims ();
-
-  if (a_dims != b_dims)
-    {
-      if (is_valid_bsxfun ("operator .^", a_dims, b_dims))
-        {
-          //Potentially complex results
-          FloatNDArray xa = octave_value_extract<FloatNDArray> (a);
-          FloatNDArray xb = octave_value_extract<FloatNDArray> (b);
-          if (! xb.all_integers () && xa.any_element_is_negative ())
-            return octave_value (bsxfun_pow (FloatComplexNDArray (xa), xb));
-          else
-            return octave_value (bsxfun_pow (xa, xb));
-        }
-      else
-        {
-          gripe_nonconformant ("operator .^", a_dims, b_dims);
-          return octave_value ();
-        }
-    }
-
-  int len = a.length ();
-
-  bool convert_to_complex = false;
-
-  for (octave_idx_type i = 0; i < len; i++)
-    {
-      octave_quit ();
-      float atmp = a(i);
-      float btmp = b(i);
-      if (atmp < 0.0 && static_cast<int> (btmp) != btmp)
-        {
-          convert_to_complex = true;
-          goto done;
-        }
-    }
-
-done:
-
-  if (convert_to_complex)
-    {
-      FloatComplexNDArray complex_result (a_dims);
-
-      for (octave_idx_type i = 0; i < len; i++)
-        {
-          octave_quit ();
-          FloatComplex atmp (a(i));
-          complex_result(i) = std::pow (atmp, b(i));
-        }
-
-      retval = complex_result;
-    }
-  else
-    {
-      FloatNDArray result (a_dims);
-
-      for (octave_idx_type i = 0; i < len; i++)
-        {
-          octave_quit ();
-          result(i) = std::pow (a(i), b(i));
-        }
-
-      retval = result;
-    }
-
-  return retval;
-}
-
-// -*- 5 -*-
-octave_value
-elem_xpow (const FloatNDArray& a, const FloatComplex& b)
-{
-  FloatComplexNDArray result (a.dims ());
-
-  for (octave_idx_type i = 0; i < a.length (); i++)
-    {
-      octave_quit ();
-      result(i) = std::pow (a(i), b);
-    }
-
-  return result;
-}
-
-// -*- 6 -*-
-octave_value
-elem_xpow (const FloatNDArray& a, const FloatComplexNDArray& b)
-{
-  dim_vector a_dims = a.dims ();
-  dim_vector b_dims = b.dims ();
-
-  if (a_dims != b_dims)
-    {
-      if (is_valid_bsxfun ("operator .^", a_dims, b_dims))
-        {
-          return bsxfun_pow (a, b);
-        }
-      else
-        {
-          gripe_nonconformant ("operator .^", a_dims, b_dims);
-          return octave_value ();
-        }
-    }
-
-  FloatComplexNDArray result (a_dims);
-
-  for (octave_idx_type i = 0; i < a.length (); i++)
-    {
-      octave_quit ();
-      result(i) = std::pow (a(i), b(i));
-    }
-
-  return result;
-}
-
-// -*- 7 -*-
-octave_value
-elem_xpow (const FloatComplex& a, const FloatNDArray& b)
-{
-  FloatComplexNDArray result (b.dims ());
-
-  for (octave_idx_type i = 0; i < b.length (); i++)
-    {
-      octave_quit ();
-      float btmp = b(i);
-      if (xisint (btmp))
-        result(i) = std::pow (a, static_cast<int> (btmp));
-      else
-        result(i) = std::pow (a, btmp);
-    }
-
-  return result;
-}
-
-// -*- 8 -*-
-octave_value
-elem_xpow (const FloatComplex& a, const FloatComplexNDArray& b)
-{
-  FloatComplexNDArray result (b.dims ());
-
-  for (octave_idx_type i = 0; i < b.length (); i++)
-    {
-      octave_quit ();
-      result(i) = std::pow (a, b(i));
-    }
-
-  return result;
-}
-
-// -*- 9 -*-
-octave_value
-elem_xpow (const FloatComplexNDArray& a, float b)
-{
-  FloatComplexNDArray result (a.dims ());
-
-  if (xisint (b))
-    {
-      if (b == -1)
-        {
-          for (octave_idx_type i = 0; i < a.length (); i++)
-            result.xelem (i) = 1.0f / a(i);
-        }
-      else
-        {
-          for (octave_idx_type i = 0; i < a.length (); i++)
-            {
-              octave_quit ();
-              result(i) = std::pow (a(i), static_cast<int> (b));
-            }
-        }
-    }
-  else
-    {
-      for (octave_idx_type i = 0; i < a.length (); i++)
-        {
-          octave_quit ();
-          result(i) = std::pow (a(i), b);
-        }
-    }
-
-  return result;
-}
-
-// -*- 10 -*-
-octave_value
-elem_xpow (const FloatComplexNDArray& a, const FloatNDArray& b)
-{
-  dim_vector a_dims = a.dims ();
-  dim_vector b_dims = b.dims ();
-
-  if (a_dims != b_dims)
-    {
-      if (is_valid_bsxfun ("operator .^", a_dims, b_dims))
-        {
-          return bsxfun_pow (a, b);
-        }
-      else
-        {
-          gripe_nonconformant ("operator .^", a_dims, b_dims);
-          return octave_value ();
-        }
-    }
-
-  FloatComplexNDArray result (a_dims);
-
-  for (octave_idx_type i = 0; i < a.length (); i++)
-    {
-      octave_quit ();
-      float btmp = b(i);
-      if (xisint (btmp))
-        result(i) = std::pow (a(i), static_cast<int> (btmp));
-      else
-        result(i) = std::pow (a(i), btmp);
-    }
-
-  return result;
-}
-
-// -*- 11 -*-
-octave_value
-elem_xpow (const FloatComplexNDArray& a, const FloatComplex& b)
-{
-  FloatComplexNDArray result (a.dims ());
-
-  for (octave_idx_type i = 0; i < a.length (); i++)
-    {
-      octave_quit ();
-      result(i) = std::pow (a(i), b);
-    }
-
-  return result;
-}
-
-// -*- 12 -*-
-octave_value
-elem_xpow (const FloatComplexNDArray& a, const FloatComplexNDArray& b)
-{
-  dim_vector a_dims = a.dims ();
-  dim_vector b_dims = b.dims ();
-
-  if (a_dims != b_dims)
-    {
-      if (is_valid_bsxfun ("operator .^", a_dims, b_dims))
-        {
-          return bsxfun_pow (a, b);
-        }
-      else
-        {
-          gripe_nonconformant ("operator .^", a_dims, b_dims);
-          return octave_value ();
-        }
-    }
-
-  FloatComplexNDArray result (a_dims);
-
-  for (octave_idx_type i = 0; i < a.length (); i++)
-    {
-      octave_quit ();
-      result(i) = std::pow (a(i), b(i));
-    }
-
-  return result;
-}
--- a/src/xpow.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,158 +0,0 @@
-/*
-
-Copyright (C) 1993-2012 John W. Eaton
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#if !defined (octave_xpow_h)
-#define octave_xpow_h 1
-
-#include "oct-cmplx.h"
-
-class Matrix;
-class ComplexMatrix;
-class FloatMatrix;
-class FloatComplexMatrix;
-class DiagMatrix;
-class ComplexDiagMatrix;
-class FloatDiagMatrix;
-class FloatComplexDiagMatrix;
-class PermMatrix;
-class NDArray;
-class FloatNDArray;
-class ComplexNDArray;
-class FloatComplexNDArray;
-class octave_value;
-class Range;
-
-extern OCTINTERP_API octave_value xpow (double a, double b);
-extern OCTINTERP_API octave_value xpow (double a, const Matrix& b);
-extern OCTINTERP_API octave_value xpow (double a, const Complex& b);
-extern OCTINTERP_API octave_value xpow (double a, const ComplexMatrix& b);
-
-extern OCTINTERP_API octave_value xpow (const Matrix& a, double b);
-extern OCTINTERP_API octave_value xpow (const Matrix& a, const Complex& b);
-
-extern OCTINTERP_API octave_value xpow (const DiagMatrix& a, double b);
-extern OCTINTERP_API octave_value xpow (const DiagMatrix& a, const Complex& b);
-
-extern OCTINTERP_API octave_value xpow (const PermMatrix& a, double b);
-
-extern OCTINTERP_API octave_value xpow (const Complex& a, double b);
-extern OCTINTERP_API octave_value xpow (const Complex& a, const Matrix& b);
-extern OCTINTERP_API octave_value xpow (const Complex& a, const Complex& b);
-extern OCTINTERP_API octave_value xpow (const Complex& a, const ComplexMatrix& b);
-
-extern OCTINTERP_API octave_value xpow (const ComplexMatrix& a, double b);
-extern OCTINTERP_API octave_value xpow (const ComplexMatrix& a, const Complex& b);
-
-extern OCTINTERP_API octave_value xpow (const ComplexDiagMatrix& a, double b);
-extern OCTINTERP_API octave_value xpow (const ComplexDiagMatrix& a, const Complex& b);
-
-extern OCTINTERP_API octave_value elem_xpow (double a, const Matrix& b);
-extern OCTINTERP_API octave_value elem_xpow (double a, const ComplexMatrix& b);
-extern OCTINTERP_API octave_value elem_xpow (double a, const Range& r);
-
-extern OCTINTERP_API octave_value elem_xpow (const Matrix& a, double b);
-extern OCTINTERP_API octave_value elem_xpow (const Matrix& a, const Matrix& b);
-extern OCTINTERP_API octave_value elem_xpow (const Matrix& a, const Complex& b);
-extern OCTINTERP_API octave_value elem_xpow (const Matrix& a, const ComplexMatrix& b);
-
-extern OCTINTERP_API octave_value elem_xpow (const Complex& a, const Matrix& b);
-extern OCTINTERP_API octave_value elem_xpow (const Complex& a, const ComplexMatrix& b);
-extern OCTINTERP_API octave_value elem_xpow (const Complex& a, const Range& r);
-
-extern OCTINTERP_API octave_value elem_xpow (const ComplexMatrix& a, double b);
-extern OCTINTERP_API octave_value elem_xpow (const ComplexMatrix& a, const Matrix& b);
-extern OCTINTERP_API octave_value elem_xpow (const ComplexMatrix& a, const Complex& b);
-extern OCTINTERP_API octave_value elem_xpow (const ComplexMatrix& a, const ComplexMatrix& b);
-
-
-extern OCTINTERP_API octave_value elem_xpow (double a, const NDArray& b);
-extern OCTINTERP_API octave_value elem_xpow (double a, const ComplexNDArray& b);
-
-extern OCTINTERP_API octave_value elem_xpow (const NDArray& a, double b);
-extern OCTINTERP_API octave_value elem_xpow (const NDArray& a, const NDArray& b);
-extern OCTINTERP_API octave_value elem_xpow (const NDArray& a, const Complex& b);
-extern OCTINTERP_API octave_value elem_xpow (const NDArray& a, const ComplexNDArray& b);
-
-extern OCTINTERP_API octave_value elem_xpow (const Complex& a, const NDArray& b);
-extern OCTINTERP_API octave_value elem_xpow (const Complex& a, const ComplexNDArray& b);
-
-extern OCTINTERP_API octave_value elem_xpow (const ComplexNDArray& a, double b);
-extern OCTINTERP_API octave_value elem_xpow (const ComplexNDArray& a, const NDArray& b);
-extern OCTINTERP_API octave_value elem_xpow (const ComplexNDArray& a, const Complex& b);
-extern OCTINTERP_API octave_value elem_xpow (const ComplexNDArray& a, const ComplexNDArray& b);
-
-extern OCTINTERP_API octave_value xpow (float a, float b);
-extern OCTINTERP_API octave_value xpow (float a, const FloatMatrix& b);
-extern OCTINTERP_API octave_value xpow (float a, const FloatComplex& b);
-extern OCTINTERP_API octave_value xpow (float a, const FloatComplexMatrix& b);
-
-extern OCTINTERP_API octave_value xpow (const FloatMatrix& a, float b);
-extern OCTINTERP_API octave_value xpow (const FloatMatrix& a, const FloatComplex& b);
-
-extern OCTINTERP_API octave_value xpow (const FloatDiagMatrix& a, float b);
-extern OCTINTERP_API octave_value xpow (const FloatDiagMatrix& a, const FloatComplex& b);
-
-extern OCTINTERP_API octave_value xpow (const FloatComplex& a, float b);
-extern OCTINTERP_API octave_value xpow (const FloatComplex& a, const FloatMatrix& b);
-extern OCTINTERP_API octave_value xpow (const FloatComplex& a, const FloatComplex& b);
-extern OCTINTERP_API octave_value xpow (const FloatComplex& a, const FloatComplexMatrix& b);
-
-extern OCTINTERP_API octave_value xpow (const FloatComplexMatrix& a, float b);
-extern OCTINTERP_API octave_value xpow (const FloatComplexMatrix& a, const FloatComplex& b);
-
-extern OCTINTERP_API octave_value xpow (const FloatComplexDiagMatrix& a, float b);
-extern OCTINTERP_API octave_value xpow (const FloatComplexDiagMatrix& a, const FloatComplex& b);
-
-extern OCTINTERP_API octave_value elem_xpow (float a, const FloatMatrix& b);
-extern OCTINTERP_API octave_value elem_xpow (float a, const FloatComplexMatrix& b);
-
-extern OCTINTERP_API octave_value elem_xpow (const FloatMatrix& a, float b);
-extern OCTINTERP_API octave_value elem_xpow (const FloatMatrix& a, const FloatMatrix& b);
-extern OCTINTERP_API octave_value elem_xpow (const FloatMatrix& a, const FloatComplex& b);
-extern OCTINTERP_API octave_value elem_xpow (const FloatMatrix& a, const FloatComplexMatrix& b);
-
-extern OCTINTERP_API octave_value elem_xpow (const FloatComplex& a, const FloatMatrix& b);
-extern OCTINTERP_API octave_value elem_xpow (const FloatComplex& a, const FloatComplexMatrix& b);
-
-extern OCTINTERP_API octave_value elem_xpow (const FloatComplexMatrix& a, float b);
-extern OCTINTERP_API octave_value elem_xpow (const FloatComplexMatrix& a, const FloatMatrix& b);
-extern OCTINTERP_API octave_value elem_xpow (const FloatComplexMatrix& a, const FloatComplex& b);
-extern OCTINTERP_API octave_value elem_xpow (const FloatComplexMatrix& a, const FloatComplexMatrix& b);
-
-
-extern OCTINTERP_API octave_value elem_xpow (float a, const FloatNDArray& b);
-extern OCTINTERP_API octave_value elem_xpow (float a, const FloatComplexNDArray& b);
-
-extern OCTINTERP_API octave_value elem_xpow (const FloatNDArray& a, float b);
-extern OCTINTERP_API octave_value elem_xpow (const FloatNDArray& a, const FloatNDArray& b);
-extern OCTINTERP_API octave_value elem_xpow (const FloatNDArray& a, const FloatComplex& b);
-extern OCTINTERP_API octave_value elem_xpow (const FloatNDArray& a, const FloatComplexNDArray& b);
-
-extern OCTINTERP_API octave_value elem_xpow (const FloatComplex& a, const FloatNDArray& b);
-extern OCTINTERP_API octave_value elem_xpow (const FloatComplex& a, const FloatComplexNDArray& b);
-
-extern OCTINTERP_API octave_value elem_xpow (const FloatComplexNDArray& a, float b);
-extern OCTINTERP_API octave_value elem_xpow (const FloatComplexNDArray& a, const FloatNDArray& b);
-extern OCTINTERP_API octave_value elem_xpow (const FloatComplexNDArray& a, const FloatComplex& b);
-extern OCTINTERP_API octave_value elem_xpow (const FloatComplexNDArray& a, const FloatComplexNDArray& b);
-
-#endif
--- a/src/zfstream.cc	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,625 +0,0 @@
-/*
-
-Copyright (C) 2005-2012 Ludwig Schwardt, Kevin Ruland
-
-
-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/>.
-
-*/
-
-/*
-
- This file is adapted from the zlib 1.2.2 contrib/iostream3 code,
- written by
-
-   Ludwig Schwardt <schwardt@sun.ac.za>
-   original version by Kevin Ruland <kevin@rodin.wustl.edu>
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <iostream>
-
-#include "zfstream.h"
-
-#ifdef HAVE_ZLIB
-
-#include <cstring>          // for strcpy, strcat, strlen (mode strings)
-#include <cstdio>           // for BUFSIZ
-
-// Internal buffer sizes (default and "unbuffered" versions)
-#define STASHED_CHARACTERS 16
-#define BIGBUFSIZE (256 * 1024 + STASHED_CHARACTERS)
-#define SMALLBUFSIZE 1
-
-/*****************************************************************************/
-
-// Default constructor
-gzfilebuf::gzfilebuf ()
-: file(0), io_mode(std::ios_base::openmode(0)), own_fd(false),
-  buffer(0), buffer_size(BIGBUFSIZE), own_buffer(true)
-{
-  // No buffers to start with
-  this->disable_buffer ();
-}
-
-// Destructor
-gzfilebuf::~gzfilebuf ()
-{
-  // Sync output buffer and close only if responsible for file
-  // (i.e. attached streams should be left open at this stage)
-  this->sync ();
-  if (own_fd)
-    this->close ();
-  // Make sure internal buffer is deallocated
-  this->disable_buffer ();
-}
-
-// Set compression level and strategy
-int
-gzfilebuf::setcompression (int comp_level,
-                           int comp_strategy)
-{
-  return gzsetparams (file, comp_level, comp_strategy);
-}
-
-// Open gzipped file
-gzfilebuf*
-gzfilebuf::open (const char *name,
-                 std::ios_base::openmode mode)
-{
-  // Fail if file already open
-  if (this->is_open ())
-    return 0;
-  // Don't support simultaneous read/write access (yet)
-  if ((mode & std::ios_base::in) && (mode & std::ios_base::out))
-    return 0;
-
-  // Build mode string for gzopen and check it [27.8.1.3.2]
-  char char_mode[6] = "\0\0\0\0\0";
-  if (! this->open_mode (mode, char_mode))
-    return 0;
-
-  // Attempt to open file
-  if ((file = gzopen (name, char_mode)) == 0)
-    return 0;
-
-  // On success, allocate internal buffer and set flags
-  this->enable_buffer ();
-  io_mode = mode;
-  own_fd = true;
-  return this;
-}
-
-// Attach to gzipped file
-gzfilebuf*
-gzfilebuf::attach (int fd,
-                   std::ios_base::openmode mode)
-{
-  // Fail if file already open
-  if (this->is_open ())
-    return 0;
-  // Don't support simultaneous read/write access (yet)
-  if ((mode & std::ios_base::in) && (mode & std::ios_base::out))
-    return 0;
-
-  // Build mode string for gzdopen and check it [27.8.1.3.2]
-  char char_mode[6] = "\0\0\0\0\0";
-  if (! this->open_mode (mode, char_mode))
-    return 0;
-
-  // Attempt to attach to file
-  if ((file = gzdopen (fd, char_mode)) == 0)
-    return 0;
-
-  // On success, allocate internal buffer and set flags
-  this->enable_buffer ();
-  io_mode = mode;
-  own_fd = false;
-  return this;
-}
-
-// Close gzipped file
-gzfilebuf*
-gzfilebuf::close ()
-{
-  // Fail immediately if no file is open
-  if (! this->is_open ())
-    return 0;
-  // Assume success
-  gzfilebuf* retval = this;
-  // Attempt to sync and close gzipped file
-  if (this->sync () == -1)
-    retval = 0;
-  if (gzclose (file) < 0)
-    retval = 0;
-  // File is now gone anyway (postcondition [27.8.1.3.8])
-  file = 0;
-  own_fd = false;
-  // Destroy internal buffer if it exists
-  this->disable_buffer ();
-  return retval;
-}
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-// Convert int open mode to mode string
-bool
-gzfilebuf::open_mode (std::ios_base::openmode mode,
-                      char* c_mode) const
-{
-  // FIXME -- do we need testb?
-  // bool testb = mode & std::ios_base::binary;
-  bool testi = mode & std::ios_base::in;
-  bool testo = mode & std::ios_base::out;
-  bool testt = mode & std::ios_base::trunc;
-  bool testa = mode & std::ios_base::app;
-
-  // Check for valid flag combinations - see [27.8.1.3.2] (Table 92)
-  // Original zfstream hardcoded the compression level to maximum here...
-  // Double the time for less than 1% size improvement seems
-  // excessive though - keeping it at the default level
-  // To change back, just append "9" to the next three mode strings
-  if (!testi && testo && !testt && !testa)
-    strcpy (c_mode, "w");
-  if (!testi && testo && !testt && testa)
-    strcpy (c_mode, "a");
-  if (!testi && testo && testt && !testa)
-    strcpy (c_mode, "w");
-  if (testi && !testo && !testt && !testa)
-    strcpy (c_mode, "r");
-  // No read/write mode yet
-//  if (testi && testo && !testt && !testa)
-//    strcpy(c_mode, "r+");
-//  if (testi && testo && testt && !testa)
-//    strcpy(c_mode, "w+");
-
-  // Mode string should be empty for invalid combination of flags
-  if (strlen (c_mode) == 0)
-    return false;
-
-  strcat (c_mode, "b");
-
-  return true;
-}
-
-// Determine number of characters in internal get buffer
-std::streamsize
-gzfilebuf::showmanyc ()
-{
-  // Calls to underflow will fail if file not opened for reading
-  if (! this->is_open () || !(io_mode & std::ios_base::in))
-    return -1;
-  // Make sure get area is in use
-  if (this->gptr () && (this->gptr () < this->egptr ()))
-    return std::streamsize (this->egptr () - this->gptr ());
-  else
-    return 0;
-}
-
-// Puts back a character to the stream in two cases. Firstly, when there
-// is no putback position available, and secondly when the character putback
-// differs from the one in the file. We can only support the first case
-// with gzipped files.
-gzfilebuf::int_type
-gzfilebuf::pbackfail (gzfilebuf::int_type c)
-{
-  if (this->is_open ())
-    {
-      if (gzseek (file, this->gptr () - this->egptr () - 1, SEEK_CUR) < 0)
-        return traits_type::eof ();
-
-      // Invalidates contents of the buffer
-      enable_buffer ();
-
-      // Attempt to fill internal buffer from gzipped file
-      // (buffer must be guaranteed to exist...)
-      int bytes_read = gzread (file, buffer, buffer_size);
-      // Indicates error or EOF
-      if (bytes_read <= 0)
-        {
-          // Reset get area
-          this->setg (buffer, buffer, buffer);
-          return traits_type::eof ();
-        }
-
-      // Make all bytes read from file available as get area
-      this->setg (buffer, buffer, buffer + bytes_read);
-
-      // If next character in get area differs from putback character
-      // flag a failure
-      gzfilebuf::int_type ret = traits_type::to_int_type (*(this->gptr ()));
-      if (ret != c)
-        return traits_type::eof ();
-      else
-        return ret;
-    }
-  else
-    return traits_type::eof ();
-}
-
-// Fill get area from gzipped file
-gzfilebuf::int_type
-gzfilebuf::underflow ()
-{
-  // If something is left in the get area by chance, return it
-  // (this shouldn't normally happen, as underflow is only supposed
-  // to be called when gptr >= egptr, but it serves as error check)
-  if (this->gptr () && (this->gptr () < this->egptr ()))
-    return traits_type::to_int_type (*(this->gptr ()));
-
-  // If the file hasn't been opened for reading, produce error
-  if (! this->is_open () || !(io_mode & std::ios_base::in))
-    return traits_type::eof ();
-
-  // Copy the final characters to the front of the buffer
-  int stash = 0;
-  if (this->eback () && buffer && buffer_size > STASHED_CHARACTERS)
-    {
-      char_type *ptr1 = buffer;
-      char_type *ptr2 = this->egptr () - STASHED_CHARACTERS + 1;
-      if (ptr2 > this->eback ())
-        while (stash++ <= STASHED_CHARACTERS)
-          *ptr1++ = *ptr2++;
-    }
-
-  // Attempt to fill internal buffer from gzipped file
-  // (buffer must be guaranteed to exist...)
-  int bytes_read = gzread (file, buffer + stash, buffer_size - stash);
-
-  // Indicates error or EOF
-  if (bytes_read <= 0)
-  {
-    // Reset get area
-    this->setg (buffer, buffer, buffer);
-    return traits_type::eof ();
-  }
-  // Make all bytes read from file plus the stash available as get area
-  this->setg (buffer, buffer + stash, buffer + bytes_read + stash);
-
-  // Return next character in get area
-  return traits_type::to_int_type (*(this->gptr ()));
-}
-
-// Write put area to gzipped file
-gzfilebuf::int_type
-gzfilebuf::overflow (int_type c)
-{
-  // Determine whether put area is in use
-  if (this->pbase ())
-  {
-    // Double-check pointer range
-    if (this->pptr () > this->epptr () || this->pptr () < this->pbase ())
-      return traits_type::eof ();
-    // Add extra character to buffer if not EOF
-    if (! traits_type::eq_int_type (c, traits_type::eof ()))
-    {
-      *(this->pptr ()) = traits_type::to_char_type (c);
-      this->pbump (1);
-    }
-    // Number of characters to write to file
-    int bytes_to_write = this->pptr () - this->pbase ();
-    // Overflow doesn't fail if nothing is to be written
-    if (bytes_to_write > 0)
-    {
-      // If the file hasn't been opened for writing, produce error
-      if (! this->is_open () || !(io_mode & std::ios_base::out))
-        return traits_type::eof ();
-      // If gzipped file won't accept all bytes written to it, fail
-      if (gzwrite (file, this->pbase (), bytes_to_write) != bytes_to_write)
-        return traits_type::eof ();
-      // Reset next pointer to point to pbase on success
-      this->pbump (-bytes_to_write);
-    }
-  }
-  // Write extra character to file if not EOF
-  else if (! traits_type::eq_int_type (c, traits_type::eof ()))
-  {
-    // If the file hasn't been opened for writing, produce error
-    if (! this->is_open () || !(io_mode & std::ios_base::out))
-      return traits_type::eof ();
-    // Impromptu char buffer (allows "unbuffered" output)
-    char_type last_char = traits_type::to_char_type (c);
-    // If gzipped file won't accept this character, fail
-    if (gzwrite (file, &last_char, 1) != 1)
-      return traits_type::eof ();
-  }
-
-  // If you got here, you have succeeded (even if c was EOF)
-  // The return value should therefore be non-EOF
-  if (traits_type::eq_int_type (c, traits_type::eof ()))
-    return traits_type::not_eof (c);
-  else
-    return c;
-}
-
-// Assign new buffer
-std::streambuf*
-gzfilebuf::setbuf (char_type* p,
-                   std::streamsize n)
-{
-  // First make sure stuff is sync'ed, for safety
-  if (this->sync () == -1)
-    return 0;
-  // If buffering is turned off on purpose via setbuf(0,0), still allocate one...
-  // "Unbuffered" only really refers to put [27.8.1.4.10], while get needs at
-  // least a buffer of size 1 (very inefficient though, therefore make it bigger?)
-  // This follows from [27.5.2.4.3]/12 (gptr needs to point at something, it seems)
-  if (!p || !n)
-  {
-    // Replace existing buffer (if any) with small internal buffer
-    this->disable_buffer ();
-    buffer = 0;
-    buffer_size = 0;
-    own_buffer = true;
-    this->enable_buffer ();
-  }
-  else
-  {
-    // Replace existing buffer (if any) with external buffer
-    this->disable_buffer ();
-    buffer = p;
-    buffer_size = n;
-    own_buffer = false;
-    this->enable_buffer ();
-  }
-  return this;
-}
-
-// Write put area to gzipped file (i.e. ensures that put area is empty)
-int
-gzfilebuf::sync ()
-{
-  return traits_type::eq_int_type (this->overflow (), traits_type::eof ()) ? -1 : 0;
-}
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-// Allocate internal buffer
-void
-gzfilebuf::enable_buffer ()
-{
-  // If internal buffer required, allocate one
-  if (own_buffer && !buffer)
-  {
-    // Check for buffered vs. "unbuffered"
-    if (buffer_size > 0)
-    {
-      // Allocate internal buffer
-      buffer = new char_type [buffer_size];
-      // Get area starts empty and will be expanded by underflow as need arises
-      this->setg (buffer, buffer, buffer);
-      // Setup entire internal buffer as put area.
-      // The one-past-end pointer actually points to the last element of the buffer,
-      // so that overflow(c) can safely add the extra character c to the sequence.
-      // These pointers remain in place for the duration of the buffer
-      this->setp (buffer, buffer + buffer_size - 1);
-    }
-    else
-    {
-      // Even in "unbuffered" case, (small?) get buffer is still required
-      buffer_size = SMALLBUFSIZE;
-      buffer = new char_type [buffer_size];
-      this->setg (buffer, buffer, buffer);
-      // "Unbuffered" means no put buffer
-      this->setp (0, 0);
-    }
-  }
-  else
-  {
-    // If buffer already allocated, reset buffer pointers just to make sure no
-    // stale chars are lying around
-    this->setg (buffer, buffer, buffer);
-    this->setp (buffer, buffer + buffer_size - 1);
-  }
-}
-
-// Destroy internal buffer
-void
-gzfilebuf::disable_buffer ()
-{
-  // If internal buffer exists, deallocate it
-  if (own_buffer && buffer)
-  {
-    // Preserve unbuffered status by zeroing size
-    if (! this->pbase ())
-      buffer_size = 0;
-    delete[] buffer;
-    buffer = 0;
-    this->setg (0, 0, 0);
-    this->setp (0, 0);
-  }
-  else
-  {
-    // Reset buffer pointers to initial state if external buffer exists
-    this->setg (buffer, buffer, buffer);
-    if (buffer)
-      this->setp (buffer, buffer + buffer_size - 1);
-    else
-      this->setp (0, 0);
-  }
-}
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-// Seek functions
-gzfilebuf::pos_type
-gzfilebuf::seekoff (off_type off, std::ios_base::seekdir way,
-                   std::ios_base::openmode)
-{
-  pos_type ret = pos_type (off_type (-1));
-
-  if (this->is_open ())
-    {
-      off_type computed_off = off;
-
-      if ((io_mode & std::ios_base::in) && way == std::ios_base::cur)
-        computed_off += this->gptr () - this->egptr ();
-
-      if (way == std::ios_base::beg)
-        ret = pos_type (gzseek (file, computed_off, SEEK_SET));
-      else if (way == std::ios_base::cur)
-        ret = pos_type (gzseek (file, computed_off, SEEK_CUR));
-      else
-        // Can't seek from end of a gzipped file, so this will give -1
-        ret = pos_type (gzseek (file, computed_off, SEEK_END));
-
-      if (io_mode & std::ios_base::in)
-        // Invalidates contents of the buffer
-        enable_buffer ();
-      else
-        // flush contents of buffer to file
-        overflow ();
-    }
-
-  return ret;
-}
-
-gzfilebuf::pos_type
-gzfilebuf::seekpos (pos_type sp, std::ios_base::openmode)
-{
-  pos_type ret = pos_type (off_type (-1));
-
-  if (this->is_open ())
-    {
-      ret = pos_type (gzseek (file, sp, SEEK_SET));
-
-      if (io_mode & std::ios_base::in)
-        // Invalidates contents of the buffer
-        enable_buffer ();
-      else
-        // flush contents of buffer to file
-        overflow ();
-    }
-
-  return ret;
-}
-
-/*****************************************************************************/
-
-// Default constructor initializes stream buffer
-gzifstream::gzifstream ()
-: std::istream (0), sb ()
-{ this->init (&sb); }
-
-// Initialize stream buffer and open file
-gzifstream::gzifstream (const char* name,
-                        std::ios_base::openmode mode)
-: std::istream (0), sb ()
-{
-  this->init (&sb);
-  this->open (name, mode);
-}
-
-// Initialize stream buffer and attach to file
-gzifstream::gzifstream (int fd,
-                        std::ios_base::openmode mode)
-: std::istream (0), sb ()
-{
-  this->init (&sb);
-  this->attach (fd, mode);
-}
-
-// Open file and go into fail() state if unsuccessful
-void
-gzifstream::open (const char* name,
-                  std::ios_base::openmode mode)
-{
-  if (! sb.open (name, mode | std::ios_base::in))
-    this->setstate (std::ios_base::failbit);
-  else
-    this->clear ();
-}
-
-// Attach to file and go into fail() state if unsuccessful
-void
-gzifstream::attach (int fd,
-                    std::ios_base::openmode mode)
-{
-  if (! sb.attach (fd, mode | std::ios_base::in))
-    this->setstate (std::ios_base::failbit);
-  else
-    this->clear ();
-}
-
-// Close file
-void
-gzifstream::close ()
-{
-  if (! sb.close ())
-    this->setstate (std::ios_base::failbit);
-}
-
-/*****************************************************************************/
-
-// Default constructor initializes stream buffer
-gzofstream::gzofstream ()
-: std::ostream (0), sb ()
-{ this->init (&sb); }
-
-// Initialize stream buffer and open file
-gzofstream::gzofstream (const char* name,
-                        std::ios_base::openmode mode)
-: std::ostream (0), sb ()
-{
-  this->init (&sb);
-  this->open (name, mode);
-}
-
-// Initialize stream buffer and attach to file
-gzofstream::gzofstream (int fd,
-                        std::ios_base::openmode mode)
-: std::ostream (0), sb ()
-{
-  this->init (&sb);
-  this->attach (fd, mode);
-}
-
-// Open file and go into fail() state if unsuccessful
-void
-gzofstream::open (const char* name,
-                  std::ios_base::openmode mode)
-{
-  if (! sb.open (name, mode | std::ios_base::out))
-    this->setstate (std::ios_base::failbit);
-  else
-    this->clear ();
-}
-
-// Attach to file and go into fail() state if unsuccessful
-void
-gzofstream::attach (int fd,
-                    std::ios_base::openmode mode)
-{
-  if (! sb.attach (fd, mode | std::ios_base::out))
-    this->setstate (std::ios_base::failbit);
-  else
-    this->clear ();
-}
-
-// Close file
-void
-gzofstream::close ()
-{
-  if (! sb.close ())
-    this->setstate (std::ios_base::failbit);
-}
-
-#endif // HAVE_ZLIB
--- a/src/zfstream.h	Fri Aug 03 10:14:57 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,515 +0,0 @@
-/*
-
-Copyright (C) 2005-2012 Ludwig Schwardt, Kevin Ruland
-
-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/>.
-
-*/
-
-/*
-
- This file is adapted from the zlib 1.2.2 contrib/iostream3 code,
- written by
-
-   Ludwig Schwardt <schwardt@sun.ac.za>
-   original version by Kevin Ruland <kevin@rodin.wustl.edu>
-
-*/
-
-#ifndef ZFSTREAM_H
-#define ZFSTREAM_H
-
-#ifdef HAVE_ZLIB
-
-#include <iosfwd>
-
-#include "zlib.h"
-
-/*****************************************************************************/
-
-/**
- *  @brief  Gzipped file stream buffer class.
- *
- *  This class implements basic_filebuf for gzipped files. It doesn't yet support
- *  seeking (allowed by zlib but slow/limited), putback and read/write access
- *  (tricky). Otherwise, it attempts to be a drop-in replacement for the standard
- *  file streambuf.
-*/
-class gzfilebuf : public std::streambuf
-{
-public:
-  //  Default constructor.
-  gzfilebuf ();
-
-  //  Destructor.
-  virtual
-  ~gzfilebuf ();
-
-  /**
-   *  @brief  Set compression level and strategy on the fly.
-   *  @param  comp_level  Compression level (see zlib.h for allowed values)
-   *  @param  comp_strategy  Compression strategy (see zlib.h for allowed values)
-   *  @return  Z_OK on success, Z_STREAM_ERROR otherwise.
-   *
-   *  Unfortunately, these parameters cannot be modified separately, as the
-   *  previous zfstream version assumed. Since the strategy is seldom changed,
-   *  it can default and setcompression(level) then becomes like the old
-   *  setcompressionlevel(level).
-  */
-  int
-  setcompression (int comp_level,
-                  int comp_strategy = Z_DEFAULT_STRATEGY);
-
-  /**
-   *  @brief  Check if file is open.
-   *  @return  True if file is open.
-  */
-  bool
-  is_open () const { return (file != 0); }
-
-  /**
-   *  @brief  Open gzipped file.
-   *  @param  name  File name.
-   *  @param  mode  Open mode flags.
-   *  @return  @c this on success, NULL on failure.
-  */
-  gzfilebuf*
-  open (const char* name,
-        std::ios_base::openmode mode);
-
-  /**
-   *  @brief  Attach to already open gzipped file.
-   *  @param  fd  File descriptor.
-   *  @param  mode  Open mode flags.
-   *  @return  @c this on success, NULL on failure.
-  */
-  gzfilebuf*
-  attach (int fd,
-          std::ios_base::openmode mode);
-
-  /**
-   *  @brief  Close gzipped file.
-   *  @return  @c this on success, NULL on failure.
-  */
-  gzfilebuf*
-  close ();
-
-protected:
-  /**
-   *  @brief  Convert ios open mode int to mode string used by zlib.
-   *  @return  True if valid mode flag combination.
-  */
-  bool
-  open_mode (std::ios_base::openmode mode,
-             char* c_mode) const;
-
-  /**
-   *  @brief  Number of characters available in stream buffer.
-   *  @return  Number of characters.
-   *
-   *  This indicates number of characters in get area of stream buffer.
-   *  These characters can be read without accessing the gzipped file.
-  */
-  virtual std::streamsize
-  showmanyc ();
-
-  /**
-   *  @brief  Fill get area from gzipped file.
-   *  @return  First character in get area on success, EOF on error.
-   *
-   *  This actually reads characters from gzipped file to stream
-   *  buffer. Always buffered.
-  */
-  virtual int_type
-  underflow ();
-
-  /**
-   *  @brief  Write put area to gzipped file.
-   *  @param  c  Extra character to add to buffer contents.
-   *  @return  Non-EOF on success, EOF on error.
-   *
-   *  This actually writes characters in stream buffer to
-   *  gzipped file. With unbuffered output this is done one
-   *  character at a time.
-  */
-  virtual int_type
-  overflow (int_type c = traits_type::eof ());
-
-  /**
-   *  @brief  Installs external stream buffer.
-   *  @param  p  Pointer to char buffer.
-   *  @param  n  Size of external buffer.
-   *  @return  @c this on success, NULL on failure.
-   *
-   *  Call setbuf(0,0) to enable unbuffered output.
-  */
-  virtual std::streambuf*
-  setbuf (char_type* p,
-          std::streamsize n);
-
-  /**
-   *  @brief  Flush stream buffer to file.
-   *  @return  0 on success, -1 on error.
-   *
-   *  This calls underflow(EOF) to do the job.
-  */
-  virtual int
-  sync ();
-
-  /**
-   *  @brief  Alters the stream positions.
-   *
-   *  Each derived class provides its own appropriate behavior.
-   */
-  virtual pos_type
-  seekoff (off_type off, std::ios_base::seekdir way,
-           std::ios_base::openmode mode =
-           std::ios_base::in|std::ios_base::out);
-
-  /**
-   *  @brief  Alters the stream positions.
-   *
-   *  Each derived class provides its own appropriate behavior.
-   */
-  virtual pos_type
-  seekpos (pos_type sp, std::ios_base::openmode mode =
-           std::ios_base::in|std::ios_base::out);
-
-  virtual int_type
-  pbackfail (int_type c = traits_type::eof ());
-
-//
-// Some future enhancements
-//
-//  virtual int_type uflow();
-//  virtual int_type pbackfail(int_type c = traits_type::eof());
-
-private:
-
-  // No copying!
-
-  gzfilebuf (const gzfilebuf&);
-
-  gzfilebuf& operator = (const gzfilebuf&);
-
-  /**
-   *  @brief  Allocate internal buffer.
-   *
-   *  This function is safe to call multiple times. It will ensure
-   *  that a proper internal buffer exists if it is required. If the
-   *  buffer already exists or is external, the buffer pointers will be
-   *  reset to their original state.
-  */
-  void
-  enable_buffer ();
-
-  /**
-   *  @brief  Destroy internal buffer.
-   *
-   *  This function is safe to call multiple times. It will ensure
-   *  that the internal buffer is deallocated if it exists. In any
-   *  case, it will also reset the buffer pointers.
-  */
-  void
-  disable_buffer ();
-
-  /**
-   *  Underlying file pointer.
-  */
-  gzFile file;
-
-  /**
-   *  Mode in which file was opened.
-  */
-  std::ios_base::openmode io_mode;
-
-  /**
-   *  @brief  True if this object owns file descriptor.
-   *
-   *  This makes the class responsible for closing the file
-   *  upon destruction.
-  */
-  bool own_fd;
-
-  /**
-   *  @brief  Stream buffer.
-   *
-   *  For simplicity this remains allocated on the free store for the
-   *  entire life span of the gzfilebuf object, unless replaced by setbuf.
-  */
-  char_type* buffer;
-
-  /**
-   *  @brief  Stream buffer size.
-   *
-   *  Defaults to system default buffer size (typically 8192 bytes).
-   *  Modified by setbuf.
-  */
-  std::streamsize buffer_size;
-
-  /**
-   *  @brief  True if this object owns stream buffer.
-   *
-   *  This makes the class responsible for deleting the buffer
-   *  upon destruction.
-  */
-  bool own_buffer;
-};
-
-/*****************************************************************************/
-
-/**
- *  @brief  Gzipped file input stream class.
- *
- *  This class implements ifstream for gzipped files. Seeking and putback
- *  is not supported yet.
-*/
-class gzifstream : public std::istream
-{
-public:
-  //  Default constructor
-  gzifstream ();
-
-  /**
-   *  @brief  Construct stream on gzipped file to be opened.
-   *  @param  name  File name.
-   *  @param  mode  Open mode flags (forced to contain ios::in).
-  */
-  explicit
-  gzifstream (const char* name,
-              std::ios_base::openmode mode = std::ios_base::in);
-
-  /**
-   *  @brief  Construct stream on already open gzipped file.
-   *  @param  fd    File descriptor.
-   *  @param  mode  Open mode flags (forced to contain ios::in).
-  */
-  explicit
-  gzifstream (int fd,
-              std::ios_base::openmode mode = std::ios_base::in);
-
-  /**
-   *  Obtain underlying stream buffer.
-  */
-  gzfilebuf*
-  rdbuf () const
-  { return const_cast<gzfilebuf*>(&sb); }
-
-  /**
-   *  @brief  Check if file is open.
-   *  @return  True if file is open.
-  */
-  bool
-  is_open () { return sb.is_open (); }
-
-  /**
-   *  @brief  Open gzipped file.
-   *  @param  name  File name.
-   *  @param  mode  Open mode flags (forced to contain ios::in).
-   *
-   *  Stream will be in state good() if file opens successfully;
-   *  otherwise in state fail(). This differs from the behavior of
-   *  ifstream, which never sets the state to good() and therefore
-   *  won't allow you to reuse the stream for a second file unless
-   *  you manually clear() the state. The choice is a matter of
-   *  convenience.
-  */
-  void
-  open (const char* name,
-        std::ios_base::openmode mode = std::ios_base::in);
-
-  /**
-   *  @brief  Attach to already open gzipped file.
-   *  @param  fd  File descriptor.
-   *  @param  mode  Open mode flags (forced to contain ios::in).
-   *
-   *  Stream will be in state good() if attach succeeded; otherwise
-   *  in state fail().
-  */
-  void
-  attach (int fd,
-          std::ios_base::openmode mode = std::ios_base::in);
-
-  /**
-   *  @brief  Close gzipped file.
-   *
-   *  Stream will be in state fail() if close failed.
-  */
-  void
-  close ();
-
-private:
-  /**
-   *  Underlying stream buffer.
-  */
-  gzfilebuf sb;
-};
-
-/*****************************************************************************/
-
-/**
- *  @brief  Gzipped file output stream class.
- *
- *  This class implements ofstream for gzipped files. Seeking and putback
- *  is not supported yet.
-*/
-class gzofstream : public std::ostream
-{
-public:
-  //  Default constructor
-  gzofstream ();
-
-  /**
-   *  @brief  Construct stream on gzipped file to be opened.
-   *  @param  name  File name.
-   *  @param  mode  Open mode flags (forced to contain ios::out).
-  */
-  explicit
-  gzofstream (const char* name,
-              std::ios_base::openmode mode = std::ios_base::out);
-
-  /**
-   *  @brief  Construct stream on already open gzipped file.
-   *  @param  fd    File descriptor.
-   *  @param  mode  Open mode flags (forced to contain ios::out).
-  */
-  explicit
-  gzofstream (int fd,
-              std::ios_base::openmode mode = std::ios_base::out);
-
-  /**
-   *  Obtain underlying stream buffer.
-  */
-  gzfilebuf*
-  rdbuf () const
-  { return const_cast<gzfilebuf*>(&sb); }
-
-  /**
-   *  @brief  Check if file is open.
-   *  @return  True if file is open.
-  */
-  bool
-  is_open () { return sb.is_open (); }
-
-  /**
-   *  @brief  Open gzipped file.
-   *  @param  name  File name.
-   *  @param  mode  Open mode flags (forced to contain ios::out).
-   *
-   *  Stream will be in state good() if file opens successfully;
-   *  otherwise in state fail(). This differs from the behavior of
-   *  ofstream, which never sets the state to good() and therefore
-   *  won't allow you to reuse the stream for a second file unless
-   *  you manually clear() the state. The choice is a matter of
-   *  convenience.
-  */
-  void
-  open (const char* name,
-        std::ios_base::openmode mode = std::ios_base::out);
-
-  /**
-   *  @brief  Attach to already open gzipped file.
-   *  @param  fd  File descriptor.
-   *  @param  mode  Open mode flags (forced to contain ios::out).
-   *
-   *  Stream will be in state good() if attach succeeded; otherwise
-   *  in state fail().
-  */
-  void
-  attach (int fd,
-          std::ios_base::openmode mode = std::ios_base::out);
-
-  /**
-   *  @brief  Close gzipped file.
-   *
-   *  Stream will be in state fail() if close failed.
-  */
-  void
-  close ();
-
-private:
-  /**
-   *  Underlying stream buffer.
-  */
-  gzfilebuf sb;
-};
-
-/*****************************************************************************/
-
-/**
- *  @brief  Gzipped file output stream manipulator class.
- *
- *  This class defines a two-argument manipulator for gzofstream. It is used
- *  as base for the setcompression(int,int) manipulator.
-*/
-template<typename T1, typename T2>
-  class gzomanip2
-  {
-  public:
-    // Allows insertor to peek at internals
-    template <typename Ta, typename Tb>
-      friend gzofstream&
-      operator<<(gzofstream&,
-                 const gzomanip2<Ta,Tb>&);
-
-    // Constructor
-    gzomanip2 (gzofstream& (*f)(gzofstream&, T1, T2),
-               T1 v1,
-               T2 v2);
-  private:
-    // Underlying manipulator function
-    gzofstream&
-    (*func)(gzofstream&, T1, T2);
-
-    // Arguments for manipulator function
-    T1 val1;
-    T2 val2;
-  };
-
-/*****************************************************************************/
-
-// Manipulator function thunks through to stream buffer
-inline gzofstream&
-setcompression (gzofstream &gzs, int l, int s = Z_DEFAULT_STRATEGY)
-{
-  (gzs.rdbuf ())->setcompression (l, s);
-  return gzs;
-}
-
-// Manipulator constructor stores arguments
-template<typename T1, typename T2>
-  inline
-  gzomanip2<T1,T2>::gzomanip2 (gzofstream &(*f)(gzofstream &, T1, T2),
-                               T1 v1,
-                               T2 v2)
-  : func(f), val1(v1), val2(v2)
-  { }
-
-// Insertor applies underlying manipulator function to stream
-template<typename T1, typename T2>
-  inline gzofstream&
-  operator<<(gzofstream& s, const gzomanip2<T1,T2>& m)
-  { return (*m.func)(s, m.val1, m.val2); }
-
-// Insert this onto stream to simplify setting of compression level
-inline gzomanip2<int,int>
-setcompression (int l, int s = Z_DEFAULT_STRATEGY)
-{ return gzomanip2<int,int>(&setcompression, l, s); }
-
-#endif // HAVE_ZLIB
-
-#endif // ZFSTREAM_H