view libinterp/corefcn/oct-stream.cc @ 22755:3a2b891d0b33

maint: Standardize Copyright formatting. * Makefile.am, README, build-aux/check-subst-vars.in.sh, build-aux/find-files-with-tests.sh, build-aux/mk-builtins.sh, build-aux/mk-default-qt-settings.in.sh, build-aux/mk-f77-def.in.sh, build-aux/mk-hg-id.sh, build-aux/mk-mxarray-h.in.sh, build-aux/mk-octave-config-h.sh, build-aux/mk-opts.pl, build-aux/mk-version-h.in.sh, build-aux/subst-config-vals.in.sh, build-aux/subst-cross-config-vals.in.sh, build-aux/subst-default-vals.in.sh, build-aux/subst-f77-isnan-macro.in.sh, build-aux/subst-script-vals.in.sh, configure.ac, doc/interpreter/arith.txi, doc/interpreter/audio.txi, doc/interpreter/basics.txi, doc/interpreter/bugs.txi, doc/interpreter/container.txi, doc/interpreter/cp-idx.txi, doc/interpreter/data.txi, doc/interpreter/debug.txi, doc/interpreter/diagperm.txi, doc/interpreter/diffeq.txi, doc/interpreter/errors.txi, doc/interpreter/eval.txi, doc/interpreter/expr.txi, doc/interpreter/external.txi, doc/interpreter/fn-idx.txi, doc/interpreter/func.txi, doc/interpreter/genpropdoc.m, doc/interpreter/geometry.txi, doc/interpreter/geometryimages.m, doc/interpreter/grammar.txi, doc/interpreter/gui.txi, doc/interpreter/image.txi, doc/interpreter/install.txi, doc/interpreter/interp.txi, doc/interpreter/interpimages.m, doc/interpreter/intro.txi, doc/interpreter/io.txi, doc/interpreter/linalg.txi, doc/interpreter/macros.texi, doc/interpreter/matrix.txi, doc/interpreter/mk-doc-cache.pl, doc/interpreter/mkoctfile.1, doc/interpreter/nonlin.txi, doc/interpreter/numbers.txi, doc/interpreter/obsolete.txi, doc/interpreter/octave-cli.1, doc/interpreter/octave-config.1, doc/interpreter/octave.1, doc/interpreter/octave.css, doc/interpreter/octave.texi, doc/interpreter/oop.txi, doc/interpreter/op-idx.txi, doc/interpreter/optim.txi, doc/interpreter/package.txi, doc/interpreter/plot.txi, doc/interpreter/plotimages.m, doc/interpreter/poly.txi, doc/interpreter/preface.txi, doc/interpreter/quad.txi, doc/interpreter/set.txi, doc/interpreter/signal.txi, doc/interpreter/sparse.txi, doc/interpreter/sparseimages.m, doc/interpreter/splineimages.m, doc/interpreter/stats.txi, doc/interpreter/stmt.txi, doc/interpreter/strings.txi, doc/interpreter/system.txi, doc/interpreter/testfun.txi, doc/interpreter/var.txi, doc/interpreter/vectorize.txi, doc/liboctave/array.texi, doc/liboctave/bugs.texi, doc/liboctave/cp-idx.texi, doc/liboctave/dae.texi, doc/liboctave/diffeq.texi, doc/liboctave/error.texi, doc/liboctave/factor.texi, doc/liboctave/fn-idx.texi, doc/liboctave/gpl.texi, doc/liboctave/install.texi, doc/liboctave/intro.texi, doc/liboctave/liboctave.texi, doc/liboctave/matvec.texi, doc/liboctave/nleqn.texi, doc/liboctave/nlfunc.texi, doc/liboctave/ode.texi, doc/liboctave/optim.texi, doc/liboctave/preface.texi, doc/liboctave/quad.texi, doc/liboctave/range.texi, doc/refcard/refcard-a4.tex, doc/refcard/refcard-legal.tex, doc/refcard/refcard-letter.tex, doc/refcard/refcard.tex, etc/HACKING, etc/icons/octave.appdata.xml.in, libgui/graphics/Backend.cc, libgui/graphics/Backend.h, libgui/graphics/BaseControl.cc, libgui/graphics/BaseControl.h, libgui/graphics/ButtonControl.cc, libgui/graphics/ButtonControl.h, libgui/graphics/ButtonGroup.cc, libgui/graphics/ButtonGroup.h, libgui/graphics/Canvas.cc, libgui/graphics/Canvas.h, libgui/graphics/CheckBoxControl.cc, libgui/graphics/CheckBoxControl.h, libgui/graphics/Container.cc, libgui/graphics/Container.h, libgui/graphics/ContextMenu.cc, libgui/graphics/ContextMenu.h, libgui/graphics/EditControl.cc, libgui/graphics/EditControl.h, libgui/graphics/Figure.cc, libgui/graphics/Figure.h, libgui/graphics/FigureWindow.cc, libgui/graphics/FigureWindow.h, libgui/graphics/GLCanvas.cc, libgui/graphics/GLCanvas.h, libgui/graphics/GenericEventNotify.h, libgui/graphics/KeyMap.cc, libgui/graphics/KeyMap.h, libgui/graphics/ListBoxControl.cc, libgui/graphics/ListBoxControl.h, libgui/graphics/Logger.cc, libgui/graphics/Logger.h, libgui/graphics/Menu.cc, libgui/graphics/Menu.h, libgui/graphics/MenuContainer.h, libgui/graphics/MouseModeActionGroup.cc, libgui/graphics/MouseModeActionGroup.h, libgui/graphics/Object.cc, libgui/graphics/Object.h, libgui/graphics/ObjectFactory.cc, libgui/graphics/ObjectFactory.h, libgui/graphics/ObjectProxy.cc, libgui/graphics/ObjectProxy.h, libgui/graphics/Panel.cc, libgui/graphics/Panel.h, libgui/graphics/PopupMenuControl.cc, libgui/graphics/PopupMenuControl.h, libgui/graphics/PushButtonControl.cc, libgui/graphics/PushButtonControl.h, libgui/graphics/PushTool.cc, libgui/graphics/PushTool.h, libgui/graphics/QtHandlesUtils.cc, libgui/graphics/QtHandlesUtils.h, libgui/graphics/RadioButtonControl.cc, libgui/graphics/RadioButtonControl.h, libgui/graphics/SliderControl.cc, libgui/graphics/SliderControl.h, libgui/graphics/TextControl.cc, libgui/graphics/TextControl.h, libgui/graphics/TextEdit.cc, libgui/graphics/TextEdit.h, libgui/graphics/ToggleButtonControl.cc, libgui/graphics/ToggleButtonControl.h, libgui/graphics/ToggleTool.cc, libgui/graphics/ToggleTool.h, libgui/graphics/ToolBar.cc, libgui/graphics/ToolBar.h, libgui/graphics/ToolBarButton.cc, libgui/graphics/ToolBarButton.h, libgui/graphics/__init_qt__.cc, libgui/graphics/__init_qt__.h, libgui/graphics/annotation-dialog.cc, libgui/graphics/annotation-dialog.h, libgui/graphics/gl-select.cc, libgui/graphics/gl-select.h, libgui/src/color-picker.cc, libgui/src/color-picker.h, libgui/src/dialog.cc, libgui/src/dialog.h, libgui/src/documentation-dock-widget.cc, libgui/src/documentation-dock-widget.h, libgui/src/files-dock-widget.cc, libgui/src/files-dock-widget.h, libgui/src/find-files-dialog.cc, libgui/src/find-files-dialog.h, libgui/src/find-files-model.cc, libgui/src/find-files-model.h, libgui/src/history-dock-widget.cc, libgui/src/history-dock-widget.h, libgui/src/liboctgui-build-info.h, libgui/src/liboctgui-build-info.in.cc, libgui/src/m-editor/file-editor-interface.h, libgui/src/m-editor/file-editor-tab.cc, libgui/src/m-editor/file-editor-tab.h, libgui/src/m-editor/file-editor.cc, libgui/src/m-editor/file-editor.h, libgui/src/m-editor/find-dialog.cc, libgui/src/m-editor/find-dialog.h, libgui/src/m-editor/marker.cc, libgui/src/m-editor/marker.h, libgui/src/m-editor/octave-qscintilla.cc, libgui/src/m-editor/octave-qscintilla.h, libgui/src/m-editor/octave-txt-lexer.cc, libgui/src/m-editor/octave-txt-lexer.h, libgui/src/main-window.cc, libgui/src/main-window.h, libgui/src/octave-cmd.cc, libgui/src/octave-cmd.h, libgui/src/octave-dock-widget.cc, libgui/src/octave-dock-widget.h, libgui/src/octave-gui.cc, libgui/src/octave-gui.h, libgui/src/octave-interpreter.cc, libgui/src/octave-interpreter.h, libgui/src/octave-qt-link.cc, libgui/src/octave-qt-link.h, libgui/src/qtinfo/parser.cc, libgui/src/qtinfo/parser.h, libgui/src/qtinfo/webinfo.cc, libgui/src/qtinfo/webinfo.h, libgui/src/resource-manager.cc, libgui/src/resource-manager.h, libgui/src/settings-dialog.cc, libgui/src/settings-dialog.h, libgui/src/shortcut-manager.cc, libgui/src/shortcut-manager.h, libgui/src/terminal-dock-widget.cc, libgui/src/terminal-dock-widget.h, libgui/src/thread-manager.cc, libgui/src/thread-manager.h, libgui/src/welcome-wizard.cc, libgui/src/welcome-wizard.h, libgui/src/workspace-model.cc, libgui/src/workspace-model.h, libgui/src/workspace-view.cc, libgui/src/workspace-view.h, libinterp/build-env.h, libinterp/build-env.in.cc, libinterp/builtins.h, libinterp/corefcn/Cell.cc, libinterp/corefcn/Cell.h, libinterp/corefcn/__contourc__.cc, libinterp/corefcn/__dsearchn__.cc, libinterp/corefcn/__ichol__.cc, libinterp/corefcn/__ilu__.cc, libinterp/corefcn/__lin_interpn__.cc, libinterp/corefcn/__luinc__.cc, libinterp/corefcn/__magick_read__.cc, libinterp/corefcn/__pchip_deriv__.cc, libinterp/corefcn/__qp__.cc, libinterp/corefcn/balance.cc, libinterp/corefcn/base-text-renderer.h, libinterp/corefcn/besselj.cc, libinterp/corefcn/betainc.cc, libinterp/corefcn/bitfcns.cc, libinterp/corefcn/bsxfun.cc, libinterp/corefcn/c-file-ptr-stream.cc, libinterp/corefcn/c-file-ptr-stream.h, libinterp/corefcn/call-stack.cc, libinterp/corefcn/call-stack.h, libinterp/corefcn/cdisplay.c, libinterp/corefcn/cdisplay.h, libinterp/corefcn/cellfun.cc, libinterp/corefcn/coct-hdf5-types.c, libinterp/corefcn/colloc.cc, libinterp/corefcn/comment-list.cc, libinterp/corefcn/comment-list.h, libinterp/corefcn/conv2.cc, libinterp/corefcn/daspk.cc, libinterp/corefcn/dasrt.cc, libinterp/corefcn/dassl.cc, libinterp/corefcn/data.cc, libinterp/corefcn/data.h, libinterp/corefcn/debug.cc, libinterp/corefcn/debug.h, libinterp/corefcn/defaults.cc, libinterp/corefcn/defaults.in.h, libinterp/corefcn/defun-dld.h, libinterp/corefcn/defun-int.h, libinterp/corefcn/defun.cc, libinterp/corefcn/defun.h, libinterp/corefcn/det.cc, libinterp/corefcn/dirfns.cc, libinterp/corefcn/dirfns.h, libinterp/corefcn/display.cc, libinterp/corefcn/display.h, libinterp/corefcn/dlmread.cc, libinterp/corefcn/dot.cc, libinterp/corefcn/dynamic-ld.cc, libinterp/corefcn/dynamic-ld.h, libinterp/corefcn/eig.cc, libinterp/corefcn/ellipj.cc, libinterp/corefcn/error.cc, libinterp/corefcn/error.h, libinterp/corefcn/errwarn.cc, libinterp/corefcn/errwarn.h, libinterp/corefcn/event-queue.cc, libinterp/corefcn/event-queue.h, libinterp/corefcn/fft.cc, libinterp/corefcn/fft2.cc, libinterp/corefcn/fftn.cc, libinterp/corefcn/file-io.cc, libinterp/corefcn/file-io.h, libinterp/corefcn/filter.cc, libinterp/corefcn/find.cc, libinterp/corefcn/ft-text-renderer.cc, libinterp/corefcn/ft-text-renderer.h, libinterp/corefcn/gammainc.cc, libinterp/corefcn/gcd.cc, libinterp/corefcn/getgrent.cc, libinterp/corefcn/getpwent.cc, libinterp/corefcn/getrusage.cc, libinterp/corefcn/givens.cc, libinterp/corefcn/gl-render.cc, libinterp/corefcn/gl-render.h, libinterp/corefcn/gl2ps-print.cc, libinterp/corefcn/gl2ps-print.h, libinterp/corefcn/graphics.cc, libinterp/corefcn/graphics.in.h, libinterp/corefcn/gripes.cc, libinterp/corefcn/gripes.h, libinterp/corefcn/gsvd.cc, libinterp/corefcn/hash.cc, libinterp/corefcn/help.cc, libinterp/corefcn/help.h, libinterp/corefcn/hess.cc, libinterp/corefcn/hex2num.cc, libinterp/corefcn/hook-fcn.cc, libinterp/corefcn/hook-fcn.h, libinterp/corefcn/input.cc, libinterp/corefcn/input.h, libinterp/corefcn/interpreter.cc, libinterp/corefcn/interpreter.h, libinterp/corefcn/inv.cc, libinterp/corefcn/jit-ir.cc, libinterp/corefcn/jit-ir.h, libinterp/corefcn/jit-typeinfo.cc, libinterp/corefcn/jit-typeinfo.h, libinterp/corefcn/jit-util.cc, libinterp/corefcn/jit-util.h, libinterp/corefcn/kron.cc, libinterp/corefcn/load-path.cc, libinterp/corefcn/load-path.h, libinterp/corefcn/load-save.cc, libinterp/corefcn/load-save.h, libinterp/corefcn/lookup.cc, libinterp/corefcn/ls-ascii-helper.cc, libinterp/corefcn/ls-ascii-helper.h, libinterp/corefcn/ls-hdf5.cc, libinterp/corefcn/ls-hdf5.h, libinterp/corefcn/ls-mat-ascii.cc, libinterp/corefcn/ls-mat-ascii.h, libinterp/corefcn/ls-mat4.cc, libinterp/corefcn/ls-mat4.h, libinterp/corefcn/ls-mat5.cc, libinterp/corefcn/ls-mat5.h, libinterp/corefcn/ls-oct-binary.cc, libinterp/corefcn/ls-oct-binary.h, libinterp/corefcn/ls-oct-text.cc, libinterp/corefcn/ls-oct-text.h, libinterp/corefcn/ls-utils.cc, libinterp/corefcn/ls-utils.h, libinterp/corefcn/lsode.cc, libinterp/corefcn/lu.cc, libinterp/corefcn/mappers.cc, libinterp/corefcn/matrix_type.cc, libinterp/corefcn/max.cc, libinterp/corefcn/mex.cc, libinterp/corefcn/mex.h, libinterp/corefcn/mexproto.h, libinterp/corefcn/mgorth.cc, libinterp/corefcn/mxarray.in.h, libinterp/corefcn/nproc.cc, libinterp/corefcn/oct-errno.h, libinterp/corefcn/oct-errno.in.cc, libinterp/corefcn/oct-fstrm.cc, libinterp/corefcn/oct-fstrm.h, libinterp/corefcn/oct-handle.h, libinterp/corefcn/oct-hdf5-types.cc, libinterp/corefcn/oct-hdf5-types.h, libinterp/corefcn/oct-hdf5.h, libinterp/corefcn/oct-hist.cc, libinterp/corefcn/oct-hist.h, libinterp/corefcn/oct-iostrm.cc, libinterp/corefcn/oct-iostrm.h, libinterp/corefcn/oct-lvalue.cc, libinterp/corefcn/oct-lvalue.h, libinterp/corefcn/oct-map.cc, libinterp/corefcn/oct-map.h, libinterp/corefcn/oct-obj.h, libinterp/corefcn/oct-opengl.h, libinterp/corefcn/oct-prcstrm.cc, libinterp/corefcn/oct-prcstrm.h, libinterp/corefcn/oct-procbuf.cc, libinterp/corefcn/oct-procbuf.h, libinterp/corefcn/oct-stdstrm.h, libinterp/corefcn/oct-stream.cc, libinterp/corefcn/oct-stream.h, libinterp/corefcn/oct-strstrm.cc, libinterp/corefcn/oct-strstrm.h, libinterp/corefcn/oct-tex-lexer.in.ll, libinterp/corefcn/oct-tex-parser.in.yy, libinterp/corefcn/oct.h, libinterp/corefcn/octave-default-image.h, libinterp/corefcn/octave-link.cc, libinterp/corefcn/octave-link.h, libinterp/corefcn/octave-preserve-stream-state.h, libinterp/corefcn/ordschur.cc, libinterp/corefcn/pager.cc, libinterp/corefcn/pager.h, libinterp/corefcn/pinv.cc, libinterp/corefcn/pr-output.cc, libinterp/corefcn/pr-output.h, libinterp/corefcn/procstream.cc, libinterp/corefcn/procstream.h, libinterp/corefcn/profiler.cc, libinterp/corefcn/profiler.h, libinterp/corefcn/psi.cc, libinterp/corefcn/pt-jit.cc, libinterp/corefcn/pt-jit.h, libinterp/corefcn/quad.cc, libinterp/corefcn/quadcc.cc, libinterp/corefcn/qz.cc, libinterp/corefcn/rand.cc, libinterp/corefcn/rcond.cc, libinterp/corefcn/regexp.cc, libinterp/corefcn/schur.cc, libinterp/corefcn/sighandlers.cc, libinterp/corefcn/sighandlers.h, libinterp/corefcn/sparse-xdiv.cc, libinterp/corefcn/sparse-xdiv.h, libinterp/corefcn/sparse-xpow.cc, libinterp/corefcn/sparse-xpow.h, libinterp/corefcn/sparse.cc, libinterp/corefcn/spparms.cc, libinterp/corefcn/sqrtm.cc, libinterp/corefcn/str2double.cc, libinterp/corefcn/strfind.cc, libinterp/corefcn/strfns.cc, libinterp/corefcn/sub2ind.cc, libinterp/corefcn/svd.cc, libinterp/corefcn/sylvester.cc, libinterp/corefcn/symtab.cc, libinterp/corefcn/symtab.h, libinterp/corefcn/syscalls.cc, libinterp/corefcn/sysdep.cc, libinterp/corefcn/sysdep.h, libinterp/corefcn/text-renderer.cc, libinterp/corefcn/text-renderer.h, libinterp/corefcn/time.cc, libinterp/corefcn/toplev.cc, libinterp/corefcn/toplev.h, libinterp/corefcn/tril.cc, libinterp/corefcn/tsearch.cc, libinterp/corefcn/txt-eng.cc, libinterp/corefcn/txt-eng.h, libinterp/corefcn/typecast.cc, libinterp/corefcn/urlwrite.cc, libinterp/corefcn/utils.cc, libinterp/corefcn/utils.h, libinterp/corefcn/variables.cc, libinterp/corefcn/variables.h, libinterp/corefcn/workspace-element.h, libinterp/corefcn/xdiv.cc, libinterp/corefcn/xdiv.h, libinterp/corefcn/xnorm.cc, libinterp/corefcn/xnorm.h, libinterp/corefcn/xpow.cc, libinterp/corefcn/xpow.h, libinterp/corefcn/zfstream.cc, libinterp/corefcn/zfstream.h, libinterp/deprecated-config.h, libinterp/dldfcn/__delaunayn__.cc, libinterp/dldfcn/__eigs__.cc, libinterp/dldfcn/__fltk_uigetfile__.cc, libinterp/dldfcn/__glpk__.cc, libinterp/dldfcn/__init_fltk__.cc, libinterp/dldfcn/__init_gnuplot__.cc, libinterp/dldfcn/__osmesa_print__.cc, libinterp/dldfcn/__voronoi__.cc, libinterp/dldfcn/amd.cc, libinterp/dldfcn/audiodevinfo.cc, libinterp/dldfcn/audioread.cc, libinterp/dldfcn/ccolamd.cc, libinterp/dldfcn/chol.cc, libinterp/dldfcn/colamd.cc, libinterp/dldfcn/convhulln.cc, libinterp/dldfcn/dmperm.cc, libinterp/dldfcn/fftw.cc, libinterp/dldfcn/gzip.cc, libinterp/dldfcn/oct-qhull.h, libinterp/dldfcn/qr.cc, libinterp/dldfcn/symbfact.cc, libinterp/dldfcn/symrcm.cc, libinterp/gendoc.pl, libinterp/genprops.awk, libinterp/liboctinterp-build-info.h, libinterp/liboctinterp-build-info.in.cc, libinterp/mk-errno-list, libinterp/mk-pkg-add, libinterp/mkops, libinterp/octave-value/ov-base-diag.cc, libinterp/octave-value/ov-base-diag.h, libinterp/octave-value/ov-base-int.cc, libinterp/octave-value/ov-base-int.h, libinterp/octave-value/ov-base-mat.cc, libinterp/octave-value/ov-base-mat.h, libinterp/octave-value/ov-base-scalar.cc, libinterp/octave-value/ov-base-scalar.h, libinterp/octave-value/ov-base-sparse.cc, libinterp/octave-value/ov-base-sparse.h, libinterp/octave-value/ov-base.cc, libinterp/octave-value/ov-base.h, libinterp/octave-value/ov-bool-mat.cc, libinterp/octave-value/ov-bool-mat.h, libinterp/octave-value/ov-bool-sparse.cc, libinterp/octave-value/ov-bool-sparse.h, libinterp/octave-value/ov-bool.cc, libinterp/octave-value/ov-bool.h, libinterp/octave-value/ov-builtin.cc, libinterp/octave-value/ov-builtin.h, libinterp/octave-value/ov-cell.cc, libinterp/octave-value/ov-cell.h, libinterp/octave-value/ov-ch-mat.cc, libinterp/octave-value/ov-ch-mat.h, libinterp/octave-value/ov-class.cc, libinterp/octave-value/ov-class.h, libinterp/octave-value/ov-classdef.cc, libinterp/octave-value/ov-classdef.h, libinterp/octave-value/ov-colon.cc, libinterp/octave-value/ov-colon.h, libinterp/octave-value/ov-complex.cc, libinterp/octave-value/ov-complex.h, libinterp/octave-value/ov-cs-list.cc, libinterp/octave-value/ov-cs-list.h, libinterp/octave-value/ov-cx-diag.cc, libinterp/octave-value/ov-cx-diag.h, libinterp/octave-value/ov-cx-mat.cc, libinterp/octave-value/ov-cx-mat.h, libinterp/octave-value/ov-cx-sparse.cc, libinterp/octave-value/ov-cx-sparse.h, libinterp/octave-value/ov-dld-fcn.cc, libinterp/octave-value/ov-dld-fcn.h, libinterp/octave-value/ov-fcn-handle.cc, libinterp/octave-value/ov-fcn-handle.h, libinterp/octave-value/ov-fcn-inline.cc, libinterp/octave-value/ov-fcn-inline.h, libinterp/octave-value/ov-fcn.cc, libinterp/octave-value/ov-fcn.h, libinterp/octave-value/ov-float.cc, libinterp/octave-value/ov-float.h, libinterp/octave-value/ov-flt-complex.cc, libinterp/octave-value/ov-flt-complex.h, libinterp/octave-value/ov-flt-cx-diag.cc, libinterp/octave-value/ov-flt-cx-diag.h, libinterp/octave-value/ov-flt-cx-mat.cc, libinterp/octave-value/ov-flt-cx-mat.h, libinterp/octave-value/ov-flt-re-diag.cc, libinterp/octave-value/ov-flt-re-diag.h, libinterp/octave-value/ov-flt-re-mat.cc, libinterp/octave-value/ov-flt-re-mat.h, libinterp/octave-value/ov-int-traits.h, libinterp/octave-value/ov-int16.cc, libinterp/octave-value/ov-int16.h, libinterp/octave-value/ov-int32.cc, libinterp/octave-value/ov-int32.h, libinterp/octave-value/ov-int64.cc, libinterp/octave-value/ov-int64.h, libinterp/octave-value/ov-int8.cc, libinterp/octave-value/ov-int8.h, libinterp/octave-value/ov-intx.h, libinterp/octave-value/ov-java.cc, libinterp/octave-value/ov-java.h, libinterp/octave-value/ov-lazy-idx.cc, libinterp/octave-value/ov-lazy-idx.h, libinterp/octave-value/ov-mex-fcn.cc, libinterp/octave-value/ov-mex-fcn.h, libinterp/octave-value/ov-null-mat.cc, libinterp/octave-value/ov-null-mat.h, libinterp/octave-value/ov-oncleanup.cc, libinterp/octave-value/ov-oncleanup.h, libinterp/octave-value/ov-perm.cc, libinterp/octave-value/ov-perm.h, libinterp/octave-value/ov-range.cc, libinterp/octave-value/ov-range.h, libinterp/octave-value/ov-re-diag.cc, libinterp/octave-value/ov-re-diag.h, libinterp/octave-value/ov-re-mat.cc, libinterp/octave-value/ov-re-mat.h, libinterp/octave-value/ov-re-sparse.cc, libinterp/octave-value/ov-re-sparse.h, libinterp/octave-value/ov-scalar.cc, libinterp/octave-value/ov-scalar.h, libinterp/octave-value/ov-str-mat.cc, libinterp/octave-value/ov-str-mat.h, libinterp/octave-value/ov-struct.cc, libinterp/octave-value/ov-struct.h, libinterp/octave-value/ov-typeinfo.cc, libinterp/octave-value/ov-typeinfo.h, libinterp/octave-value/ov-uint16.cc, libinterp/octave-value/ov-uint16.h, libinterp/octave-value/ov-uint32.cc, libinterp/octave-value/ov-uint32.h, libinterp/octave-value/ov-uint64.cc, libinterp/octave-value/ov-uint64.h, libinterp/octave-value/ov-uint8.cc, libinterp/octave-value/ov-uint8.h, libinterp/octave-value/ov-usr-fcn.cc, libinterp/octave-value/ov-usr-fcn.h, libinterp/octave-value/ov.cc, libinterp/octave-value/ov.h, libinterp/octave-value/ovl.cc, libinterp/octave-value/ovl.h, libinterp/octave.cc, libinterp/octave.h, libinterp/op-kw-docs, libinterp/operators/op-b-b.cc, libinterp/operators/op-b-bm.cc, libinterp/operators/op-b-sbm.cc, libinterp/operators/op-bm-b.cc, libinterp/operators/op-bm-bm.cc, libinterp/operators/op-bm-sbm.cc, libinterp/operators/op-cdm-cdm.cc, libinterp/operators/op-cdm-cm.cc, libinterp/operators/op-cdm-cs.cc, libinterp/operators/op-cdm-dm.cc, libinterp/operators/op-cdm-m.cc, libinterp/operators/op-cdm-s.cc, libinterp/operators/op-cell.cc, libinterp/operators/op-chm.cc, libinterp/operators/op-class.cc, libinterp/operators/op-cm-cdm.cc, libinterp/operators/op-cm-cm.cc, libinterp/operators/op-cm-cs.cc, libinterp/operators/op-cm-dm.cc, libinterp/operators/op-cm-m.cc, libinterp/operators/op-cm-pm.cc, libinterp/operators/op-cm-s.cc, libinterp/operators/op-cm-scm.cc, libinterp/operators/op-cm-sm.cc, libinterp/operators/op-cs-cm.cc, libinterp/operators/op-cs-cs.cc, libinterp/operators/op-cs-m.cc, libinterp/operators/op-cs-s.cc, libinterp/operators/op-cs-scm.cc, libinterp/operators/op-cs-sm.cc, libinterp/operators/op-dm-cdm.cc, libinterp/operators/op-dm-cm.cc, libinterp/operators/op-dm-cs.cc, libinterp/operators/op-dm-dm.cc, libinterp/operators/op-dm-m.cc, libinterp/operators/op-dm-s.cc, libinterp/operators/op-dm-scm.cc, libinterp/operators/op-dm-sm.cc, libinterp/operators/op-dm-template.cc, libinterp/operators/op-dms-template.cc, libinterp/operators/op-fcdm-fcdm.cc, libinterp/operators/op-fcdm-fcm.cc, libinterp/operators/op-fcdm-fcs.cc, libinterp/operators/op-fcdm-fdm.cc, libinterp/operators/op-fcdm-fm.cc, libinterp/operators/op-fcdm-fs.cc, libinterp/operators/op-fcm-fcdm.cc, libinterp/operators/op-fcm-fcm.cc, libinterp/operators/op-fcm-fcs.cc, libinterp/operators/op-fcm-fdm.cc, libinterp/operators/op-fcm-fm.cc, libinterp/operators/op-fcm-fs.cc, libinterp/operators/op-fcm-pm.cc, libinterp/operators/op-fcn.cc, libinterp/operators/op-fcs-fcm.cc, libinterp/operators/op-fcs-fcs.cc, libinterp/operators/op-fcs-fm.cc, libinterp/operators/op-fcs-fs.cc, libinterp/operators/op-fdm-fcdm.cc, libinterp/operators/op-fdm-fcm.cc, libinterp/operators/op-fdm-fcs.cc, libinterp/operators/op-fdm-fdm.cc, libinterp/operators/op-fdm-fm.cc, libinterp/operators/op-fdm-fs.cc, libinterp/operators/op-fm-fcdm.cc, libinterp/operators/op-fm-fcm.cc, libinterp/operators/op-fm-fcs.cc, libinterp/operators/op-fm-fdm.cc, libinterp/operators/op-fm-fm.cc, libinterp/operators/op-fm-fs.cc, libinterp/operators/op-fm-pm.cc, libinterp/operators/op-fs-fcm.cc, libinterp/operators/op-fs-fcs.cc, libinterp/operators/op-fs-fm.cc, libinterp/operators/op-fs-fs.cc, libinterp/operators/op-i16-i16.cc, libinterp/operators/op-i32-i32.cc, libinterp/operators/op-i64-i64.cc, libinterp/operators/op-i8-i8.cc, libinterp/operators/op-int-concat.cc, libinterp/operators/op-int.h, libinterp/operators/op-m-cdm.cc, libinterp/operators/op-m-cm.cc, libinterp/operators/op-m-cs.cc, libinterp/operators/op-m-dm.cc, libinterp/operators/op-m-m.cc, libinterp/operators/op-m-pm.cc, libinterp/operators/op-m-s.cc, libinterp/operators/op-m-scm.cc, libinterp/operators/op-m-sm.cc, libinterp/operators/op-pm-cm.cc, libinterp/operators/op-pm-fcm.cc, libinterp/operators/op-pm-fm.cc, libinterp/operators/op-pm-m.cc, libinterp/operators/op-pm-pm.cc, libinterp/operators/op-pm-scm.cc, libinterp/operators/op-pm-sm.cc, libinterp/operators/op-pm-template.cc, libinterp/operators/op-range.cc, libinterp/operators/op-s-cm.cc, libinterp/operators/op-s-cs.cc, libinterp/operators/op-s-m.cc, libinterp/operators/op-s-s.cc, libinterp/operators/op-s-scm.cc, libinterp/operators/op-s-sm.cc, libinterp/operators/op-sbm-b.cc, libinterp/operators/op-sbm-bm.cc, libinterp/operators/op-sbm-sbm.cc, libinterp/operators/op-scm-cm.cc, libinterp/operators/op-scm-cs.cc, libinterp/operators/op-scm-m.cc, libinterp/operators/op-scm-s.cc, libinterp/operators/op-scm-scm.cc, libinterp/operators/op-scm-sm.cc, libinterp/operators/op-sm-cm.cc, libinterp/operators/op-sm-cs.cc, libinterp/operators/op-sm-m.cc, libinterp/operators/op-sm-s.cc, libinterp/operators/op-sm-scm.cc, libinterp/operators/op-sm-sm.cc, libinterp/operators/op-str-m.cc, libinterp/operators/op-str-s.cc, libinterp/operators/op-str-str.cc, libinterp/operators/op-struct.cc, libinterp/operators/op-ui16-ui16.cc, libinterp/operators/op-ui32-ui32.cc, libinterp/operators/op-ui64-ui64.cc, libinterp/operators/op-ui8-ui8.cc, libinterp/operators/ops.h, libinterp/options-usage.h, libinterp/parse-tree/lex.h, libinterp/parse-tree/lex.ll, libinterp/parse-tree/oct-parse.in.yy, libinterp/parse-tree/octave.gperf, libinterp/parse-tree/parse.h, libinterp/parse-tree/pt-all.h, libinterp/parse-tree/pt-arg-list.cc, libinterp/parse-tree/pt-arg-list.h, libinterp/parse-tree/pt-array-list.cc, libinterp/parse-tree/pt-array-list.h, libinterp/parse-tree/pt-assign.cc, libinterp/parse-tree/pt-assign.h, libinterp/parse-tree/pt-binop.cc, libinterp/parse-tree/pt-binop.h, libinterp/parse-tree/pt-bp.cc, libinterp/parse-tree/pt-bp.h, libinterp/parse-tree/pt-cbinop.cc, libinterp/parse-tree/pt-cbinop.h, libinterp/parse-tree/pt-cell.cc, libinterp/parse-tree/pt-cell.h, libinterp/parse-tree/pt-check.cc, libinterp/parse-tree/pt-check.h, libinterp/parse-tree/pt-classdef.cc, libinterp/parse-tree/pt-classdef.h, libinterp/parse-tree/pt-cmd.cc, libinterp/parse-tree/pt-cmd.h, libinterp/parse-tree/pt-colon.cc, libinterp/parse-tree/pt-colon.h, libinterp/parse-tree/pt-const.cc, libinterp/parse-tree/pt-const.h, libinterp/parse-tree/pt-decl.cc, libinterp/parse-tree/pt-decl.h, libinterp/parse-tree/pt-eval.cc, libinterp/parse-tree/pt-eval.h, libinterp/parse-tree/pt-except.cc, libinterp/parse-tree/pt-except.h, libinterp/parse-tree/pt-exp.cc, libinterp/parse-tree/pt-exp.h, libinterp/parse-tree/pt-fcn-handle.cc, libinterp/parse-tree/pt-fcn-handle.h, libinterp/parse-tree/pt-funcall.cc, libinterp/parse-tree/pt-funcall.h, libinterp/parse-tree/pt-id.cc, libinterp/parse-tree/pt-id.h, libinterp/parse-tree/pt-idx.cc, libinterp/parse-tree/pt-idx.h, libinterp/parse-tree/pt-jump.cc, libinterp/parse-tree/pt-jump.h, libinterp/parse-tree/pt-loop.cc, libinterp/parse-tree/pt-loop.h, libinterp/parse-tree/pt-mat.cc, libinterp/parse-tree/pt-mat.h, libinterp/parse-tree/pt-misc.cc, libinterp/parse-tree/pt-misc.h, libinterp/parse-tree/pt-pr-code.cc, libinterp/parse-tree/pt-pr-code.h, libinterp/parse-tree/pt-select.cc, libinterp/parse-tree/pt-select.h, libinterp/parse-tree/pt-stmt.cc, libinterp/parse-tree/pt-stmt.h, libinterp/parse-tree/pt-unop.cc, libinterp/parse-tree/pt-unop.h, libinterp/parse-tree/pt-walk.h, libinterp/parse-tree/pt.cc, libinterp/parse-tree/pt.h, libinterp/parse-tree/token.cc, libinterp/parse-tree/token.h, libinterp/template-inst/Array-jit.cc, libinterp/template-inst/Array-tc.cc, libinterp/version.cc, libinterp/version.in.h, liboctave/array/Array-C.cc, liboctave/array/Array-b.cc, liboctave/array/Array-ch.cc, liboctave/array/Array-d.cc, liboctave/array/Array-f.cc, liboctave/array/Array-fC.cc, liboctave/array/Array-i.cc, liboctave/array/Array-idx-vec.cc, liboctave/array/Array-s.cc, liboctave/array/Array-str.cc, liboctave/array/Array-util.cc, liboctave/array/Array-util.h, liboctave/array/Array-voidp.cc, liboctave/array/Array.cc, liboctave/array/Array.h, liboctave/array/CColVector.cc, liboctave/array/CColVector.h, liboctave/array/CDiagMatrix.cc, liboctave/array/CDiagMatrix.h, liboctave/array/CMatrix.cc, liboctave/array/CMatrix.h, liboctave/array/CNDArray.cc, liboctave/array/CNDArray.h, liboctave/array/CRowVector.cc, liboctave/array/CRowVector.h, liboctave/array/CSparse.cc, liboctave/array/CSparse.h, liboctave/array/DiagArray2.cc, liboctave/array/DiagArray2.h, liboctave/array/MArray-C.cc, liboctave/array/MArray-d.cc, liboctave/array/MArray-f.cc, liboctave/array/MArray-fC.cc, liboctave/array/MArray-i.cc, liboctave/array/MArray-s.cc, liboctave/array/MArray.cc, liboctave/array/MArray.h, liboctave/array/MDiagArray2.cc, liboctave/array/MDiagArray2.h, liboctave/array/MSparse-C.cc, liboctave/array/MSparse-d.cc, liboctave/array/MSparse.cc, liboctave/array/MSparse.h, liboctave/array/Matrix.h, liboctave/array/MatrixType.cc, liboctave/array/MatrixType.h, liboctave/array/PermMatrix.cc, liboctave/array/PermMatrix.h, liboctave/array/Range.cc, liboctave/array/Range.h, liboctave/array/Sparse-C.cc, liboctave/array/Sparse-b.cc, liboctave/array/Sparse-d.cc, liboctave/array/Sparse.cc, liboctave/array/Sparse.h, liboctave/array/boolMatrix.cc, liboctave/array/boolMatrix.h, liboctave/array/boolNDArray.cc, liboctave/array/boolNDArray.h, liboctave/array/boolSparse.cc, liboctave/array/boolSparse.h, liboctave/array/chMatrix.cc, liboctave/array/chMatrix.h, liboctave/array/chNDArray.cc, liboctave/array/chNDArray.h, liboctave/array/dColVector.cc, liboctave/array/dColVector.h, liboctave/array/dDiagMatrix.cc, liboctave/array/dDiagMatrix.h, liboctave/array/dMatrix.cc, liboctave/array/dMatrix.h, liboctave/array/dNDArray.cc, liboctave/array/dNDArray.h, liboctave/array/dRowVector.cc, liboctave/array/dRowVector.h, liboctave/array/dSparse.cc, liboctave/array/dSparse.h, liboctave/array/dim-vector.cc, liboctave/array/dim-vector.h, liboctave/array/fCColVector.cc, liboctave/array/fCColVector.h, liboctave/array/fCDiagMatrix.cc, liboctave/array/fCDiagMatrix.h, liboctave/array/fCMatrix.cc, liboctave/array/fCMatrix.h, liboctave/array/fCNDArray.cc, liboctave/array/fCNDArray.h, liboctave/array/fCRowVector.cc, liboctave/array/fCRowVector.h, liboctave/array/fColVector.cc, liboctave/array/fColVector.h, liboctave/array/fDiagMatrix.cc, liboctave/array/fDiagMatrix.h, liboctave/array/fMatrix.cc, liboctave/array/fMatrix.h, liboctave/array/fNDArray.cc, liboctave/array/fNDArray.h, liboctave/array/fRowVector.cc, liboctave/array/fRowVector.h, liboctave/array/idx-vector.cc, liboctave/array/idx-vector.h, liboctave/array/int16NDArray.cc, liboctave/array/int16NDArray.h, liboctave/array/int32NDArray.cc, liboctave/array/int32NDArray.h, liboctave/array/int64NDArray.cc, liboctave/array/int64NDArray.h, liboctave/array/int8NDArray.cc, liboctave/array/int8NDArray.h, liboctave/array/intNDArray.cc, liboctave/array/intNDArray.h, liboctave/array/uint16NDArray.cc, liboctave/array/uint16NDArray.h, liboctave/array/uint32NDArray.cc, liboctave/array/uint32NDArray.h, liboctave/array/uint64NDArray.cc, liboctave/array/uint64NDArray.h, liboctave/array/uint8NDArray.cc, liboctave/array/uint8NDArray.h, liboctave/cruft/misc/blaswrap.c, liboctave/cruft/misc/cquit.c, liboctave/cruft/misc/f77-extern.cc, liboctave/cruft/misc/f77-fcn.c, liboctave/cruft/misc/f77-fcn.h, liboctave/cruft/misc/lo-error.c, liboctave/cruft/misc/lo-error.h, liboctave/cruft/misc/quit.cc, liboctave/cruft/misc/quit.h, liboctave/liboctave-build-info.h, liboctave/liboctave-build-info.in.cc, liboctave/numeric/CollocWt.cc, liboctave/numeric/CollocWt.h, liboctave/numeric/DAE.h, liboctave/numeric/DAEFunc.h, liboctave/numeric/DAERT.h, liboctave/numeric/DAERTFunc.h, liboctave/numeric/DASPK-opts.in, liboctave/numeric/DASPK.cc, liboctave/numeric/DASPK.h, liboctave/numeric/DASRT-opts.in, liboctave/numeric/DASRT.cc, liboctave/numeric/DASRT.h, liboctave/numeric/DASSL-opts.in, liboctave/numeric/DASSL.cc, liboctave/numeric/DASSL.h, liboctave/numeric/DET.h, liboctave/numeric/EIG.cc, liboctave/numeric/EIG.h, liboctave/numeric/LSODE-opts.in, liboctave/numeric/LSODE.cc, liboctave/numeric/LSODE.h, liboctave/numeric/ODE.h, liboctave/numeric/ODEFunc.h, liboctave/numeric/ODES.cc, liboctave/numeric/ODES.h, liboctave/numeric/ODESFunc.h, liboctave/numeric/Quad-opts.in, liboctave/numeric/Quad.cc, liboctave/numeric/Quad.h, liboctave/numeric/aepbalance.cc, liboctave/numeric/aepbalance.h, liboctave/numeric/base-dae.h, liboctave/numeric/base-de.h, liboctave/numeric/base-min.h, liboctave/numeric/bsxfun-decl.h, liboctave/numeric/bsxfun-defs.cc, liboctave/numeric/bsxfun.h, liboctave/numeric/chol.cc, liboctave/numeric/chol.h, liboctave/numeric/eigs-base.cc, liboctave/numeric/eigs-base.h, liboctave/numeric/fEIG.cc, liboctave/numeric/fEIG.h, liboctave/numeric/gepbalance.cc, liboctave/numeric/gepbalance.h, liboctave/numeric/gsvd.cc, liboctave/numeric/gsvd.h, liboctave/numeric/hess.cc, liboctave/numeric/hess.h, liboctave/numeric/lo-amos-proto.h, liboctave/numeric/lo-arpack-proto.h, liboctave/numeric/lo-blas-proto.h, liboctave/numeric/lo-fftpack-proto.h, liboctave/numeric/lo-lapack-proto.h, liboctave/numeric/lo-mappers.cc, liboctave/numeric/lo-mappers.h, liboctave/numeric/lo-qrupdate-proto.h, liboctave/numeric/lo-ranlib-proto.h, liboctave/numeric/lo-slatec-proto.h, liboctave/numeric/lo-specfun.cc, liboctave/numeric/lo-specfun.h, liboctave/numeric/lu.cc, liboctave/numeric/lu.h, liboctave/numeric/oct-convn.cc, liboctave/numeric/oct-convn.h, liboctave/numeric/oct-fftw.cc, liboctave/numeric/oct-fftw.h, liboctave/numeric/oct-norm.cc, liboctave/numeric/oct-norm.h, liboctave/numeric/oct-rand.cc, liboctave/numeric/oct-rand.h, liboctave/numeric/oct-spparms.cc, liboctave/numeric/oct-spparms.h, liboctave/numeric/qr.cc, liboctave/numeric/qr.h, liboctave/numeric/qrp.cc, liboctave/numeric/qrp.h, liboctave/numeric/randgamma.cc, liboctave/numeric/randgamma.h, liboctave/numeric/randmtzig.cc, liboctave/numeric/randmtzig.h, liboctave/numeric/randpoisson.cc, liboctave/numeric/randpoisson.h, liboctave/numeric/schur.cc, liboctave/numeric/schur.h, liboctave/numeric/sparse-chol.cc, liboctave/numeric/sparse-chol.h, liboctave/numeric/sparse-dmsolve.cc, liboctave/numeric/sparse-dmsolve.h, liboctave/numeric/sparse-lu.cc, liboctave/numeric/sparse-lu.h, liboctave/numeric/sparse-qr.cc, liboctave/numeric/sparse-qr.h, liboctave/numeric/svd.cc, liboctave/numeric/svd.h, liboctave/operators/Sparse-diag-op-defs.h, liboctave/operators/Sparse-op-decls.h, liboctave/operators/Sparse-op-defs.h, liboctave/operators/Sparse-perm-op-defs.h, liboctave/operators/mk-ops.awk, liboctave/operators/mx-base.h, liboctave/operators/mx-defs.h, liboctave/operators/mx-ext.h, liboctave/operators/mx-inlines.cc, liboctave/operators/mx-op-decl.h, liboctave/operators/mx-op-defs.h, liboctave/operators/mx-ops, liboctave/operators/smx-ops, liboctave/operators/vx-ops, liboctave/system/child-list.cc, liboctave/system/child-list.h, liboctave/system/dir-ops.cc, liboctave/system/dir-ops.h, liboctave/system/file-ops.cc, liboctave/system/file-ops.h, liboctave/system/file-stat.cc, liboctave/system/file-stat.h, liboctave/system/lo-sysdep.cc, liboctave/system/lo-sysdep.h, liboctave/system/mach-info.cc, liboctave/system/mach-info.h, liboctave/system/oct-env.cc, liboctave/system/oct-env.h, liboctave/system/oct-group.cc, liboctave/system/oct-group.h, liboctave/system/oct-passwd.cc, liboctave/system/oct-passwd.h, liboctave/system/oct-syscalls.cc, liboctave/system/oct-syscalls.h, liboctave/system/oct-time.cc, liboctave/system/oct-time.h, liboctave/system/oct-uname.cc, liboctave/system/oct-uname.h, liboctave/util/action-container.h, liboctave/util/base-list.h, liboctave/util/byte-swap.h, liboctave/util/caseless-str.h, liboctave/util/cmd-edit.cc, liboctave/util/cmd-edit.h, liboctave/util/cmd-hist.cc, liboctave/util/cmd-hist.h, liboctave/util/data-conv.cc, liboctave/util/data-conv.h, liboctave/util/f2c-main.c, liboctave/util/functor.h, liboctave/util/glob-match.cc, liboctave/util/glob-match.h, liboctave/util/kpse.cc, liboctave/util/kpse.h, liboctave/util/lo-array-errwarn.cc, liboctave/util/lo-array-errwarn.h, liboctave/util/lo-array-gripes.cc, liboctave/util/lo-array-gripes.h, liboctave/util/lo-cutils.c, liboctave/util/lo-cutils.h, liboctave/util/lo-hash.cc, liboctave/util/lo-hash.h, liboctave/util/lo-ieee.cc, liboctave/util/lo-ieee.h, liboctave/util/lo-macros.h, liboctave/util/lo-math.h, liboctave/util/lo-regexp.cc, liboctave/util/lo-regexp.h, liboctave/util/lo-traits.h, liboctave/util/lo-utils.cc, liboctave/util/lo-utils.h, liboctave/util/oct-alloc.h, liboctave/util/oct-base64.cc, liboctave/util/oct-base64.h, liboctave/util/oct-binmap.h, liboctave/util/oct-cmplx.h, liboctave/util/oct-glob.cc, liboctave/util/oct-glob.h, liboctave/util/oct-inttypes-fwd.h, liboctave/util/oct-inttypes.cc, liboctave/util/oct-inttypes.h, liboctave/util/oct-locbuf.cc, liboctave/util/oct-locbuf.h, liboctave/util/oct-mutex.cc, liboctave/util/oct-mutex.h, liboctave/util/oct-refcount.h, liboctave/util/oct-rl-edit.c, liboctave/util/oct-rl-edit.h, liboctave/util/oct-rl-hist.c, liboctave/util/oct-rl-hist.h, liboctave/util/oct-shlib.cc, liboctave/util/oct-shlib.h, liboctave/util/oct-sort.cc, liboctave/util/oct-sort.h, liboctave/util/oct-sparse.h, liboctave/util/oct-string.cc, liboctave/util/oct-string.h, liboctave/util/pathsearch.cc, liboctave/util/pathsearch.h, liboctave/util/singleton-cleanup.cc, liboctave/util/sparse-sort.cc, liboctave/util/sparse-sort.h, liboctave/util/sparse-util.cc, liboctave/util/sparse-util.h, liboctave/util/str-vec.cc, liboctave/util/str-vec.h, liboctave/util/sun-utils.h, liboctave/util/unwind-prot.cc, liboctave/util/unwind-prot.h, liboctave/util/url-transfer.cc, liboctave/util/url-transfer.h, liboctave/wrappers/areadlink-wrapper.c, liboctave/wrappers/areadlink-wrapper.h, liboctave/wrappers/async-system-wrapper.c, liboctave/wrappers/async-system-wrapper.h, liboctave/wrappers/base64-wrappers.c, liboctave/wrappers/base64-wrappers.h, liboctave/wrappers/canonicalize-file-name-wrapper.c, liboctave/wrappers/canonicalize-file-name-wrapper.h, liboctave/wrappers/dirent-wrappers.c, liboctave/wrappers/dirent-wrappers.h, liboctave/wrappers/fcntl-wrappers.c, liboctave/wrappers/fcntl-wrappers.h, liboctave/wrappers/filepos-wrappers.c, liboctave/wrappers/filepos-wrappers.h, liboctave/wrappers/fpucw-wrappers.c, liboctave/wrappers/fpucw-wrappers.h, liboctave/wrappers/gen-tempname-wrapper.c, liboctave/wrappers/gen-tempname-wrapper.h, liboctave/wrappers/getopt-wrapper.c, liboctave/wrappers/getopt-wrapper.h, liboctave/wrappers/glob-wrappers.c, liboctave/wrappers/glob-wrappers.h, liboctave/wrappers/hash-wrappers.c, liboctave/wrappers/hash-wrappers.h, liboctave/wrappers/math-wrappers.c, liboctave/wrappers/math-wrappers.h, liboctave/wrappers/mkostemp-wrapper.c, liboctave/wrappers/mkostemp-wrapper.h, liboctave/wrappers/nanosleep-wrapper.c, liboctave/wrappers/nanosleep-wrapper.h, liboctave/wrappers/nproc-wrapper.c, liboctave/wrappers/nproc-wrapper.h, liboctave/wrappers/octave-popen2.c, liboctave/wrappers/octave-popen2.h, liboctave/wrappers/putenv-wrapper.c, liboctave/wrappers/putenv-wrapper.h, liboctave/wrappers/set-program-name-wrapper.c, liboctave/wrappers/set-program-name-wrapper.h, liboctave/wrappers/signal-wrappers.c, liboctave/wrappers/signal-wrappers.h, liboctave/wrappers/stat-wrappers.c, liboctave/wrappers/stat-wrappers.h, liboctave/wrappers/strdup-wrapper.c, liboctave/wrappers/strdup-wrapper.h, liboctave/wrappers/strftime-wrapper.c, liboctave/wrappers/strftime-wrapper.h, liboctave/wrappers/strmode-wrapper.c, liboctave/wrappers/strmode-wrapper.h, liboctave/wrappers/strptime-wrapper.c, liboctave/wrappers/strptime-wrapper.h, liboctave/wrappers/time-wrappers.c, liboctave/wrappers/time-wrappers.h, liboctave/wrappers/tmpfile-wrapper.c, liboctave/wrappers/tmpfile-wrapper.h, liboctave/wrappers/uname-wrapper.c, liboctave/wrappers/uname-wrapper.h, liboctave/wrappers/unistd-wrappers.c, liboctave/wrappers/unistd-wrappers.h, liboctave/wrappers/unsetenv-wrapper.c, liboctave/wrappers/unsetenv-wrapper.h, liboctave/wrappers/vasprintf-wrapper.c, liboctave/wrappers/vasprintf-wrapper.h, liboctave/wrappers/wait-for-input.c, liboctave/wrappers/wait-for-input.h, liboctave/wrappers/wait-wrappers.c, liboctave/wrappers/wait-wrappers.h, m4/acinclude.m4, oct-conf-post.in.h, run-octave.in, scripts/@ftp/ascii.m, scripts/@ftp/binary.m, scripts/@ftp/cd.m, scripts/@ftp/close.m, scripts/@ftp/delete.m, scripts/@ftp/dir.m, scripts/@ftp/display.m, scripts/@ftp/ftp.m, scripts/@ftp/loadobj.m, scripts/@ftp/mget.m, scripts/@ftp/mkdir.m, scripts/@ftp/mput.m, scripts/@ftp/rename.m, scripts/@ftp/rmdir.m, scripts/@ftp/saveobj.m, scripts/audio/@audioplayer/__get_properties__.m, scripts/audio/@audioplayer/audioplayer.m, scripts/audio/@audioplayer/display.m, scripts/audio/@audioplayer/get.m, scripts/audio/@audioplayer/isplaying.m, scripts/audio/@audioplayer/pause.m, scripts/audio/@audioplayer/play.m, scripts/audio/@audioplayer/playblocking.m, scripts/audio/@audioplayer/resume.m, scripts/audio/@audioplayer/set.m, scripts/audio/@audioplayer/stop.m, scripts/audio/@audioplayer/subsasgn.m, scripts/audio/@audioplayer/subsref.m, scripts/audio/@audiorecorder/__get_properties__.m, scripts/audio/@audiorecorder/audiorecorder.m, scripts/audio/@audiorecorder/display.m, scripts/audio/@audiorecorder/get.m, scripts/audio/@audiorecorder/getaudiodata.m, scripts/audio/@audiorecorder/getplayer.m, scripts/audio/@audiorecorder/isrecording.m, scripts/audio/@audiorecorder/pause.m, scripts/audio/@audiorecorder/play.m, scripts/audio/@audiorecorder/record.m, scripts/audio/@audiorecorder/recordblocking.m, scripts/audio/@audiorecorder/resume.m, scripts/audio/@audiorecorder/set.m, scripts/audio/@audiorecorder/stop.m, scripts/audio/@audiorecorder/subsasgn.m, scripts/audio/@audiorecorder/subsref.m, scripts/audio/lin2mu.m, scripts/audio/mu2lin.m, scripts/audio/record.m, scripts/audio/sound.m, scripts/audio/soundsc.m, scripts/deprecated/bitmax.m, scripts/deprecated/comma.m, scripts/deprecated/isstr.m, scripts/deprecated/mahalanobis.m, scripts/deprecated/md5sum.m, scripts/deprecated/octave_config_info.m, scripts/deprecated/onenormest.m, scripts/deprecated/paren.m, scripts/deprecated/semicolon.m, scripts/deprecated/sleep.m, scripts/deprecated/usleep.m, scripts/deprecated/wavread.m, scripts/deprecated/wavwrite.m, scripts/elfun/acosd.m, scripts/elfun/acot.m, scripts/elfun/acotd.m, scripts/elfun/acoth.m, scripts/elfun/acsc.m, scripts/elfun/acscd.m, scripts/elfun/acsch.m, scripts/elfun/asec.m, scripts/elfun/asecd.m, scripts/elfun/asech.m, scripts/elfun/asind.m, scripts/elfun/atan2d.m, scripts/elfun/atand.m, scripts/elfun/cosd.m, scripts/elfun/cot.m, scripts/elfun/cotd.m, scripts/elfun/coth.m, scripts/elfun/csc.m, scripts/elfun/cscd.m, scripts/elfun/csch.m, scripts/elfun/sec.m, scripts/elfun/secd.m, scripts/elfun/sech.m, scripts/elfun/sind.m, scripts/elfun/tand.m, scripts/general/accumarray.m, scripts/general/accumdim.m, scripts/general/bincoeff.m, scripts/general/bitcmp.m, scripts/general/bitget.m, scripts/general/bitset.m, scripts/general/blkdiag.m, scripts/general/cart2pol.m, scripts/general/cart2sph.m, scripts/general/cell2mat.m, scripts/general/celldisp.m, scripts/general/chop.m, scripts/general/circshift.m, scripts/general/common_size.m, scripts/general/cplxpair.m, scripts/general/cumtrapz.m, scripts/general/curl.m, scripts/general/dblquad.m, scripts/general/deal.m, scripts/general/deg2rad.m, scripts/general/del2.m, scripts/general/display.m, scripts/general/divergence.m, scripts/general/fieldnames.m, scripts/general/flip.m, scripts/general/flipdim.m, scripts/general/fliplr.m, scripts/general/flipud.m, scripts/general/grabcode.m, scripts/general/gradient.m, scripts/general/idivide.m, scripts/general/inputParser.m, scripts/general/int2str.m, scripts/general/interp1.m, scripts/general/interp2.m, scripts/general/interp3.m, scripts/general/interpft.m, scripts/general/interpn.m, scripts/general/isdir.m, scripts/general/isequal.m, scripts/general/isequaln.m, scripts/general/loadobj.m, scripts/general/logspace.m, scripts/general/methods.m, scripts/general/nargchk.m, scripts/general/narginchk.m, scripts/general/nargoutchk.m, scripts/general/nextpow2.m, scripts/general/nthargout.m, scripts/general/num2str.m, scripts/general/pol2cart.m, scripts/general/polyarea.m, scripts/general/postpad.m, scripts/general/prepad.m, scripts/general/private/__isequal__.m, scripts/general/private/__splinen__.m, scripts/general/publish.m, scripts/general/quadgk.m, scripts/general/quadl.m, scripts/general/quadv.m, scripts/general/rad2deg.m, scripts/general/randi.m, scripts/general/rat.m, scripts/general/repmat.m, scripts/general/rot90.m, scripts/general/rotdim.m, scripts/general/saveobj.m, scripts/general/shift.m, scripts/general/shiftdim.m, scripts/general/sortrows.m, scripts/general/sph2cart.m, scripts/general/structfun.m, scripts/general/subsindex.m, scripts/general/trapz.m, scripts/general/triplequad.m, scripts/general/validateattributes.m, scripts/geometry/convhull.m, scripts/geometry/delaunay.m, scripts/geometry/delaunayn.m, scripts/geometry/dsearch.m, scripts/geometry/dsearchn.m, scripts/geometry/griddata.m, scripts/geometry/griddata3.m, scripts/geometry/griddatan.m, scripts/geometry/inpolygon.m, scripts/geometry/rectint.m, scripts/geometry/tsearchn.m, scripts/geometry/voronoi.m, scripts/geometry/voronoin.m, scripts/gui/dialog.m, scripts/gui/errordlg.m, scripts/gui/guidata.m, scripts/gui/guihandles.m, scripts/gui/helpdlg.m, scripts/gui/inputdlg.m, scripts/gui/listdlg.m, scripts/gui/msgbox.m, scripts/gui/private/__file_filter__.m, scripts/gui/private/__fltk_file_filter__.m, scripts/gui/private/__get_funcname__.m, scripts/gui/private/__is_function__.m, scripts/gui/private/__uigetdir_fltk__.m, scripts/gui/private/__uigetfile_fltk__.m, scripts/gui/private/__uiobject_split_args__.m, scripts/gui/private/__uiputfile_fltk__.m, scripts/gui/questdlg.m, scripts/gui/uibuttongroup.m, scripts/gui/uicontextmenu.m, scripts/gui/uicontrol.m, scripts/gui/uigetdir.m, scripts/gui/uigetfile.m, scripts/gui/uimenu.m, scripts/gui/uipanel.m, scripts/gui/uipushtool.m, scripts/gui/uiputfile.m, scripts/gui/uiresume.m, scripts/gui/uitoggletool.m, scripts/gui/uitoolbar.m, scripts/gui/uiwait.m, scripts/gui/waitbar.m, scripts/gui/waitforbuttonpress.m, scripts/gui/warndlg.m, scripts/help/__gripe_missing_component__.m, scripts/help/__makeinfo__.m, scripts/help/__unimplemented__.m, scripts/help/ans.m, scripts/help/doc.m, scripts/help/doc_cache_create.m, scripts/help/error_ids.m, scripts/help/get_first_help_sentence.m, scripts/help/help.m, scripts/help/lookfor.m, scripts/help/print_usage.m, scripts/help/private/__additional_help_message__.m, scripts/help/private/__strip_html_tags__.m, scripts/help/type.m, scripts/help/warning_ids.m, scripts/help/which.m, scripts/image/autumn.m, scripts/image/bone.m, scripts/image/brighten.m, scripts/image/cmpermute.m, scripts/image/cmunique.m, scripts/image/colorcube.m, scripts/image/colormap.m, scripts/image/contrast.m, scripts/image/cool.m, scripts/image/copper.m, scripts/image/cubehelix.m, scripts/image/flag.m, scripts/image/gray.m, scripts/image/gray2ind.m, scripts/image/hot.m, scripts/image/hsv.m, scripts/image/hsv2rgb.m, scripts/image/im2double.m, scripts/image/image.m, scripts/image/imagesc.m, scripts/image/imfinfo.m, scripts/image/imformats.m, scripts/image/imread.m, scripts/image/imshow.m, scripts/image/imwrite.m, scripts/image/ind2gray.m, scripts/image/ind2rgb.m, scripts/image/iscolormap.m, scripts/image/jet.m, scripts/image/lines.m, scripts/image/ntsc2rgb.m, scripts/image/ocean.m, scripts/image/pink.m, scripts/image/prism.m, scripts/image/private/__imfinfo__.m, scripts/image/private/__imread__.m, scripts/image/private/__imwrite__.m, scripts/image/private/colorspace_conversion_input_check.m, scripts/image/private/colorspace_conversion_revert.m, scripts/image/private/imageIO.m, scripts/image/private/imwrite_filename.m, scripts/image/private/ind2x.m, scripts/image/rainbow.m, scripts/image/rgb2hsv.m, scripts/image/rgb2ind.m, scripts/image/rgb2ntsc.m, scripts/image/rgbplot.m, scripts/image/spinmap.m, scripts/image/spring.m, scripts/image/summer.m, scripts/image/viridis.m, scripts/image/white.m, scripts/image/winter.m, scripts/io/beep.m, scripts/io/csvread.m, scripts/io/csvwrite.m, scripts/io/dlmwrite.m, scripts/io/fileread.m, scripts/io/importdata.m, scripts/io/is_valid_file_id.m, scripts/io/strread.m, scripts/io/textread.m, scripts/java/javaArray.m, scripts/java/java_get.m, scripts/java/java_set.m, scripts/java/javaaddpath.m, scripts/java/javachk.m, scripts/java/javaclasspath.m, scripts/java/javamem.m, scripts/java/javarmpath.m, scripts/java/org/octave/ClassHelper.java, scripts/java/org/octave/Matrix.java, scripts/java/org/octave/OctClassLoader.java, scripts/java/org/octave/Octave.java, scripts/java/org/octave/OctaveReference.java, scripts/java/usejava.m, scripts/linear-algebra/bandwidth.m, scripts/linear-algebra/commutation_matrix.m, scripts/linear-algebra/cond.m, scripts/linear-algebra/condeig.m, scripts/linear-algebra/condest.m, scripts/linear-algebra/cross.m, scripts/linear-algebra/duplication_matrix.m, scripts/linear-algebra/expm.m, scripts/linear-algebra/housh.m, scripts/linear-algebra/isbanded.m, scripts/linear-algebra/isdefinite.m, scripts/linear-algebra/isdiag.m, scripts/linear-algebra/ishermitian.m, scripts/linear-algebra/issymmetric.m, scripts/linear-algebra/istril.m, scripts/linear-algebra/istriu.m, scripts/linear-algebra/krylov.m, scripts/linear-algebra/linsolve.m, scripts/linear-algebra/logm.m, scripts/linear-algebra/normest.m, scripts/linear-algebra/normest1.m, scripts/linear-algebra/null.m, scripts/linear-algebra/orth.m, scripts/linear-algebra/planerot.m, scripts/linear-algebra/qzhess.m, scripts/linear-algebra/rank.m, scripts/linear-algebra/rref.m, scripts/linear-algebra/subspace.m, scripts/linear-algebra/trace.m, scripts/linear-algebra/vech.m, scripts/miscellaneous/bug_report.m, scripts/miscellaneous/bunzip2.m, scripts/miscellaneous/cast.m, scripts/miscellaneous/citation.m, scripts/miscellaneous/compare_versions.m, scripts/miscellaneous/computer.m, scripts/miscellaneous/copyfile.m, scripts/miscellaneous/debug.m, scripts/miscellaneous/delete.m, scripts/miscellaneous/desktop.m, scripts/miscellaneous/dir.m, scripts/miscellaneous/dos.m, scripts/miscellaneous/edit.m, scripts/miscellaneous/fact.m, scripts/miscellaneous/fileattrib.m, scripts/miscellaneous/fileparts.m, scripts/miscellaneous/fullfile.m, scripts/miscellaneous/genvarname.m, scripts/miscellaneous/getappdata.m, scripts/miscellaneous/getfield.m, scripts/miscellaneous/gunzip.m, scripts/miscellaneous/info.m, scripts/miscellaneous/inputname.m, scripts/miscellaneous/isappdata.m, scripts/miscellaneous/isdeployed.m, scripts/miscellaneous/ismac.m, scripts/miscellaneous/ispc.m, scripts/miscellaneous/isunix.m, scripts/miscellaneous/license.m, scripts/miscellaneous/list_primes.m, scripts/miscellaneous/ls.m, scripts/miscellaneous/ls_command.m, scripts/miscellaneous/menu.m, scripts/miscellaneous/mex.m, scripts/miscellaneous/mexext.m, scripts/miscellaneous/mkdir.m, scripts/miscellaneous/mkoctfile.m, scripts/miscellaneous/movefile.m, scripts/miscellaneous/namelengthmax.m, scripts/miscellaneous/news.m, scripts/miscellaneous/open.m, scripts/miscellaneous/orderfields.m, scripts/miscellaneous/pack.m, scripts/miscellaneous/parseparams.m, scripts/miscellaneous/perl.m, scripts/miscellaneous/private/__w2mpth__.m, scripts/miscellaneous/private/display_info_file.m, scripts/miscellaneous/python.m, scripts/miscellaneous/recycle.m, scripts/miscellaneous/rmappdata.m, scripts/miscellaneous/run.m, scripts/miscellaneous/setappdata.m, scripts/miscellaneous/setfield.m, scripts/miscellaneous/substruct.m, scripts/miscellaneous/swapbytes.m, scripts/miscellaneous/symvar.m, scripts/miscellaneous/tar.m, scripts/miscellaneous/tempdir.m, scripts/miscellaneous/tmpnam.m, scripts/miscellaneous/unix.m, scripts/miscellaneous/unpack.m, scripts/miscellaneous/untar.m, scripts/miscellaneous/unzip.m, scripts/miscellaneous/ver.m, scripts/miscellaneous/version.m, scripts/miscellaneous/what.m, scripts/miscellaneous/xor.m, scripts/miscellaneous/zip.m, scripts/mk-pkg-add, scripts/mkdoc.pl, scripts/ode/ode23.m, scripts/ode/ode45.m, scripts/ode/odeget.m, scripts/ode/odeplot.m, scripts/ode/odeset.m, scripts/ode/private/AbsRel_norm.m, scripts/ode/private/integrate_adaptive.m, scripts/ode/private/kahan.m, scripts/ode/private/ode_event_handler.m, scripts/ode/private/odedefaults.m, scripts/ode/private/odemergeopts.m, scripts/ode/private/runge_kutta_23.m, scripts/ode/private/runge_kutta_45_dorpri.m, scripts/ode/private/runge_kutta_interpolate.m, scripts/ode/private/starting_stepsize.m, scripts/optimization/__all_opts__.m, scripts/optimization/fminbnd.m, scripts/optimization/fminsearch.m, scripts/optimization/fminunc.m, scripts/optimization/fsolve.m, scripts/optimization/fzero.m, scripts/optimization/glpk.m, scripts/optimization/lsqnonneg.m, scripts/optimization/optimget.m, scripts/optimization/optimset.m, scripts/optimization/pqpnonneg.m, scripts/optimization/private/__fdjac__.m, scripts/optimization/qp.m, scripts/optimization/sqp.m, scripts/path/matlabroot.m, scripts/path/pathdef.m, scripts/path/private/getsavepath.m, scripts/path/savepath.m, scripts/pkg/pkg.m, scripts/pkg/private/build.m, scripts/pkg/private/configure_make.m, scripts/pkg/private/default_prefix.m, scripts/pkg/private/describe.m, scripts/pkg/private/dirempty.m, scripts/pkg/private/get_description.m, scripts/pkg/private/get_forge_download.m, scripts/pkg/private/get_forge_pkg.m, scripts/pkg/private/get_unsatisfied_deps.m, scripts/pkg/private/getarch.m, scripts/pkg/private/getarchdir.m, scripts/pkg/private/install.m, scripts/pkg/private/installed_packages.m, scripts/pkg/private/list_forge_packages.m, scripts/pkg/private/load_packages.m, scripts/pkg/private/load_packages_and_dependencies.m, scripts/pkg/private/rebuild.m, scripts/pkg/private/save_order.m, scripts/pkg/private/uninstall.m, scripts/pkg/private/unload_packages.m, scripts/plot/appearance/__clabel__.m, scripts/plot/appearance/__getlegenddata__.m, scripts/plot/appearance/annotation.m, scripts/plot/appearance/axis.m, scripts/plot/appearance/box.m, scripts/plot/appearance/caxis.m, scripts/plot/appearance/clabel.m, scripts/plot/appearance/daspect.m, scripts/plot/appearance/datetick.m, scripts/plot/appearance/diffuse.m, scripts/plot/appearance/grid.m, scripts/plot/appearance/gtext.m, scripts/plot/appearance/hidden.m, scripts/plot/appearance/legend.m, scripts/plot/appearance/lighting.m, scripts/plot/appearance/material.m, scripts/plot/appearance/orient.m, scripts/plot/appearance/pbaspect.m, scripts/plot/appearance/private/__axis_label__.m, scripts/plot/appearance/private/__axis_limits__.m, scripts/plot/appearance/shading.m, scripts/plot/appearance/specular.m, scripts/plot/appearance/text.m, scripts/plot/appearance/title.m, scripts/plot/appearance/view.m, scripts/plot/appearance/whitebg.m, scripts/plot/appearance/xlabel.m, scripts/plot/appearance/xlim.m, scripts/plot/appearance/ylabel.m, scripts/plot/appearance/ylim.m, scripts/plot/appearance/zlabel.m, scripts/plot/appearance/zlim.m, scripts/plot/draw/area.m, scripts/plot/draw/bar.m, scripts/plot/draw/barh.m, scripts/plot/draw/camlight.m, scripts/plot/draw/colorbar.m, scripts/plot/draw/comet.m, scripts/plot/draw/comet3.m, scripts/plot/draw/compass.m, scripts/plot/draw/contour.m, scripts/plot/draw/contour3.m, scripts/plot/draw/contourc.m, scripts/plot/draw/contourf.m, scripts/plot/draw/cylinder.m, scripts/plot/draw/ellipsoid.m, scripts/plot/draw/errorbar.m, scripts/plot/draw/ezcontour.m, scripts/plot/draw/ezcontourf.m, scripts/plot/draw/ezmesh.m, scripts/plot/draw/ezmeshc.m, scripts/plot/draw/ezplot.m, scripts/plot/draw/ezplot3.m, scripts/plot/draw/ezpolar.m, scripts/plot/draw/ezsurf.m, scripts/plot/draw/ezsurfc.m, scripts/plot/draw/feather.m, scripts/plot/draw/fill.m, scripts/plot/draw/fplot.m, scripts/plot/draw/hist.m, scripts/plot/draw/isocaps.m, scripts/plot/draw/isocolors.m, scripts/plot/draw/isonormals.m, scripts/plot/draw/isosurface.m, scripts/plot/draw/light.m, scripts/plot/draw/line.m, scripts/plot/draw/loglog.m, scripts/plot/draw/loglogerr.m, scripts/plot/draw/mesh.m, scripts/plot/draw/meshc.m, scripts/plot/draw/meshz.m, scripts/plot/draw/pareto.m, scripts/plot/draw/patch.m, scripts/plot/draw/pcolor.m, scripts/plot/draw/peaks.m, scripts/plot/draw/pie.m, scripts/plot/draw/pie3.m, scripts/plot/draw/plot.m, scripts/plot/draw/plot3.m, scripts/plot/draw/plotmatrix.m, scripts/plot/draw/plotyy.m, scripts/plot/draw/polar.m, scripts/plot/draw/private/__add_datasource__.m, scripts/plot/draw/private/__bar__.m, scripts/plot/draw/private/__calc_isovalue_from_data__.m, scripts/plot/draw/private/__contour__.m, scripts/plot/draw/private/__errplot__.m, scripts/plot/draw/private/__ezplot__.m, scripts/plot/draw/private/__interp_cube__.m, scripts/plot/draw/private/__line__.m, scripts/plot/draw/private/__marching_cube__.m, scripts/plot/draw/private/__patch__.m, scripts/plot/draw/private/__pie__.m, scripts/plot/draw/private/__plt__.m, scripts/plot/draw/private/__quiver__.m, scripts/plot/draw/private/__rotate_around_axis__.m, scripts/plot/draw/private/__scatter__.m, scripts/plot/draw/private/__stem__.m, scripts/plot/draw/private/__unite_shared_vertices__.m, scripts/plot/draw/quiver.m, scripts/plot/draw/quiver3.m, scripts/plot/draw/rectangle.m, scripts/plot/draw/reducepatch.m, scripts/plot/draw/reducevolume.m, scripts/plot/draw/ribbon.m, scripts/plot/draw/rose.m, scripts/plot/draw/scatter.m, scripts/plot/draw/scatter3.m, scripts/plot/draw/semilogx.m, scripts/plot/draw/semilogxerr.m, scripts/plot/draw/semilogy.m, scripts/plot/draw/semilogyerr.m, scripts/plot/draw/shrinkfaces.m, scripts/plot/draw/slice.m, scripts/plot/draw/smooth3.m, scripts/plot/draw/sombrero.m, scripts/plot/draw/sphere.m, scripts/plot/draw/stairs.m, scripts/plot/draw/stem.m, scripts/plot/draw/stem3.m, scripts/plot/draw/stemleaf.m, scripts/plot/draw/surf.m, scripts/plot/draw/surface.m, scripts/plot/draw/surfc.m, scripts/plot/draw/surfl.m, scripts/plot/draw/surfnorm.m, scripts/plot/draw/tetramesh.m, scripts/plot/draw/trimesh.m, scripts/plot/draw/triplot.m, scripts/plot/draw/trisurf.m, scripts/plot/draw/waterfall.m, scripts/plot/util/__actual_axis_position__.m, scripts/plot/util/__default_plot_options__.m, scripts/plot/util/__gnuplot_drawnow__.m, scripts/plot/util/__next_line_color__.m, scripts/plot/util/__next_line_style__.m, scripts/plot/util/__opengl_info__.m, scripts/plot/util/__plt_get_axis_arg__.m, scripts/plot/util/__pltopt__.m, scripts/plot/util/allchild.m, scripts/plot/util/ancestor.m, scripts/plot/util/axes.m, scripts/plot/util/cla.m, scripts/plot/util/clf.m, scripts/plot/util/close.m, scripts/plot/util/closereq.m, scripts/plot/util/colstyle.m, scripts/plot/util/copyobj.m, scripts/plot/util/figure.m, scripts/plot/util/findall.m, scripts/plot/util/findfigs.m, scripts/plot/util/findobj.m, scripts/plot/util/frame2im.m, scripts/plot/util/gca.m, scripts/plot/util/gcbf.m, scripts/plot/util/gcbo.m, scripts/plot/util/gcf.m, scripts/plot/util/gco.m, scripts/plot/util/ginput.m, scripts/plot/util/gnuplot_binary.in.m, scripts/plot/util/graphics_toolkit.m, scripts/plot/util/hdl2struct.m, scripts/plot/util/hggroup.m, scripts/plot/util/hgload.m, scripts/plot/util/hgsave.m, scripts/plot/util/hold.m, scripts/plot/util/im2frame.m, scripts/plot/util/isaxes.m, scripts/plot/util/isfigure.m, scripts/plot/util/ishghandle.m, scripts/plot/util/ishold.m, scripts/plot/util/isprop.m, scripts/plot/util/linkaxes.m, scripts/plot/util/linkprop.m, scripts/plot/util/meshgrid.m, scripts/plot/util/ndgrid.m, scripts/plot/util/newplot.m, scripts/plot/util/pan.m, scripts/plot/util/print.m, scripts/plot/util/printd.m, scripts/plot/util/private/__add_default_menu__.m, scripts/plot/util/private/__ghostscript__.m, scripts/plot/util/private/__gnuplot_draw_axes__.m, scripts/plot/util/private/__gnuplot_draw_figure__.m, scripts/plot/util/private/__gnuplot_get_var__.m, scripts/plot/util/private/__gnuplot_ginput__.m, scripts/plot/util/private/__gnuplot_has_feature__.m, scripts/plot/util/private/__gnuplot_has_terminal__.m, scripts/plot/util/private/__gnuplot_open_stream__.m, scripts/plot/util/private/__gnuplot_print__.m, scripts/plot/util/private/__gnuplot_version__.m, scripts/plot/util/private/__opengl_print__.m, scripts/plot/util/private/__print_parse_opts__.m, scripts/plot/util/refresh.m, scripts/plot/util/refreshdata.m, scripts/plot/util/rotate.m, scripts/plot/util/rotate3d.m, scripts/plot/util/saveas.m, scripts/plot/util/shg.m, scripts/plot/util/struct2hdl.m, scripts/plot/util/subplot.m, scripts/plot/util/zoom.m, scripts/polynomial/compan.m, scripts/polynomial/conv.m, scripts/polynomial/deconv.m, scripts/polynomial/mkpp.m, scripts/polynomial/mpoles.m, scripts/polynomial/padecoef.m, scripts/polynomial/pchip.m, scripts/polynomial/poly.m, scripts/polynomial/polyaffine.m, scripts/polynomial/polyder.m, scripts/polynomial/polyeig.m, scripts/polynomial/polyfit.m, scripts/polynomial/polygcd.m, scripts/polynomial/polyint.m, scripts/polynomial/polyout.m, scripts/polynomial/polyreduce.m, scripts/polynomial/polyval.m, scripts/polynomial/polyvalm.m, scripts/polynomial/ppder.m, scripts/polynomial/ppint.m, scripts/polynomial/ppjumps.m, scripts/polynomial/ppval.m, scripts/polynomial/residue.m, scripts/polynomial/roots.m, scripts/polynomial/spline.m, scripts/polynomial/splinefit.m, scripts/polynomial/unmkpp.m, scripts/prefs/addpref.m, scripts/prefs/getpref.m, scripts/prefs/ispref.m, scripts/prefs/prefdir.m, scripts/prefs/preferences.m, scripts/prefs/private/loadprefs.m, scripts/prefs/private/prefsfile.m, scripts/prefs/private/saveprefs.m, scripts/prefs/rmpref.m, scripts/prefs/setpref.m, scripts/profiler/html/style.css, scripts/profiler/profexplore.m, scripts/profiler/profexport.m, scripts/profiler/profile.m, scripts/profiler/profshow.m, scripts/set/intersect.m, scripts/set/ismember.m, scripts/set/powerset.m, scripts/set/private/validsetargs.m, scripts/set/setdiff.m, scripts/set/setxor.m, scripts/set/union.m, scripts/set/unique.m, scripts/signal/arch_fit.m, scripts/signal/arch_rnd.m, scripts/signal/arch_test.m, scripts/signal/arma_rnd.m, scripts/signal/autoreg_matrix.m, scripts/signal/bartlett.m, scripts/signal/blackman.m, scripts/signal/detrend.m, scripts/signal/diffpara.m, scripts/signal/durbinlevinson.m, scripts/signal/fftconv.m, scripts/signal/fftfilt.m, scripts/signal/fftshift.m, scripts/signal/filter2.m, scripts/signal/fractdiff.m, scripts/signal/freqz.m, scripts/signal/freqz_plot.m, scripts/signal/hamming.m, scripts/signal/hanning.m, scripts/signal/hurst.m, scripts/signal/ifftshift.m, scripts/signal/periodogram.m, scripts/signal/private/rectangle_lw.m, scripts/signal/private/rectangle_sw.m, scripts/signal/private/triangle_lw.m, scripts/signal/private/triangle_sw.m, scripts/signal/sinc.m, scripts/signal/sinetone.m, scripts/signal/sinewave.m, scripts/signal/spectral_adf.m, scripts/signal/spectral_xdf.m, scripts/signal/spencer.m, scripts/signal/stft.m, scripts/signal/synthesis.m, scripts/signal/unwrap.m, scripts/signal/yulewalker.m, scripts/sparse/bicg.m, scripts/sparse/bicgstab.m, scripts/sparse/cgs.m, scripts/sparse/colperm.m, scripts/sparse/eigs.m, scripts/sparse/etreeplot.m, scripts/sparse/gmres.m, scripts/sparse/gplot.m, scripts/sparse/ichol.m, scripts/sparse/ilu.m, scripts/sparse/nonzeros.m, scripts/sparse/pcg.m, scripts/sparse/pcr.m, scripts/sparse/private/__sprand__.m, scripts/sparse/qmr.m, scripts/sparse/spaugment.m, scripts/sparse/spconvert.m, scripts/sparse/spdiags.m, scripts/sparse/speye.m, scripts/sparse/spfun.m, scripts/sparse/spones.m, scripts/sparse/sprand.m, scripts/sparse/sprandn.m, scripts/sparse/sprandsym.m, scripts/sparse/spstats.m, scripts/sparse/spy.m, scripts/sparse/svds.m, scripts/sparse/treelayout.m, scripts/sparse/treeplot.m, scripts/specfun/bessel.m, scripts/specfun/beta.m, scripts/specfun/betaln.m, scripts/specfun/ellipke.m, scripts/specfun/expint.m, scripts/specfun/factor.m, scripts/specfun/factorial.m, scripts/specfun/isprime.m, scripts/specfun/lcm.m, scripts/specfun/legendre.m, scripts/specfun/nchoosek.m, scripts/specfun/nthroot.m, scripts/specfun/perms.m, scripts/specfun/pow2.m, scripts/specfun/primes.m, scripts/specfun/reallog.m, scripts/specfun/realpow.m, scripts/specfun/realsqrt.m, scripts/special-matrix/gallery.m, scripts/special-matrix/hadamard.m, scripts/special-matrix/hankel.m, scripts/special-matrix/hilb.m, scripts/special-matrix/invhilb.m, scripts/special-matrix/magic.m, scripts/special-matrix/pascal.m, scripts/special-matrix/rosser.m, scripts/special-matrix/toeplitz.m, scripts/special-matrix/vander.m, scripts/special-matrix/wilkinson.m, scripts/startup/__finish__.m, scripts/statistics/base/center.m, scripts/statistics/base/cloglog.m, scripts/statistics/base/corr.m, scripts/statistics/base/cov.m, scripts/statistics/base/gls.m, scripts/statistics/base/histc.m, scripts/statistics/base/iqr.m, scripts/statistics/base/kendall.m, scripts/statistics/base/kurtosis.m, scripts/statistics/base/logit.m, scripts/statistics/base/lscov.m, scripts/statistics/base/mean.m, scripts/statistics/base/meansq.m, scripts/statistics/base/median.m, scripts/statistics/base/mode.m, scripts/statistics/base/moment.m, scripts/statistics/base/ols.m, scripts/statistics/base/ppplot.m, scripts/statistics/base/prctile.m, scripts/statistics/base/probit.m, scripts/statistics/base/qqplot.m, scripts/statistics/base/quantile.m, scripts/statistics/base/range.m, scripts/statistics/base/ranks.m, scripts/statistics/base/run_count.m, scripts/statistics/base/runlength.m, scripts/statistics/base/skewness.m, scripts/statistics/base/spearman.m, scripts/statistics/base/statistics.m, scripts/statistics/base/std.m, scripts/statistics/base/table.m, scripts/statistics/base/var.m, scripts/statistics/base/zscore.m, scripts/statistics/distributions/betacdf.m, scripts/statistics/distributions/betainv.m, scripts/statistics/distributions/betapdf.m, scripts/statistics/distributions/betarnd.m, scripts/statistics/distributions/binocdf.m, scripts/statistics/distributions/binoinv.m, scripts/statistics/distributions/binopdf.m, scripts/statistics/distributions/binornd.m, scripts/statistics/distributions/cauchy_cdf.m, scripts/statistics/distributions/cauchy_inv.m, scripts/statistics/distributions/cauchy_pdf.m, scripts/statistics/distributions/cauchy_rnd.m, scripts/statistics/distributions/chi2cdf.m, scripts/statistics/distributions/chi2inv.m, scripts/statistics/distributions/chi2pdf.m, scripts/statistics/distributions/chi2rnd.m, scripts/statistics/distributions/discrete_cdf.m, scripts/statistics/distributions/discrete_inv.m, scripts/statistics/distributions/discrete_pdf.m, scripts/statistics/distributions/discrete_rnd.m, scripts/statistics/distributions/empirical_cdf.m, scripts/statistics/distributions/empirical_inv.m, scripts/statistics/distributions/empirical_pdf.m, scripts/statistics/distributions/empirical_rnd.m, scripts/statistics/distributions/expcdf.m, scripts/statistics/distributions/expinv.m, scripts/statistics/distributions/exppdf.m, scripts/statistics/distributions/exprnd.m, scripts/statistics/distributions/fcdf.m, scripts/statistics/distributions/finv.m, scripts/statistics/distributions/fpdf.m, scripts/statistics/distributions/frnd.m, scripts/statistics/distributions/gamcdf.m, scripts/statistics/distributions/gaminv.m, scripts/statistics/distributions/gampdf.m, scripts/statistics/distributions/gamrnd.m, scripts/statistics/distributions/geocdf.m, scripts/statistics/distributions/geoinv.m, scripts/statistics/distributions/geopdf.m, scripts/statistics/distributions/geornd.m, scripts/statistics/distributions/hygecdf.m, scripts/statistics/distributions/hygeinv.m, scripts/statistics/distributions/hygepdf.m, scripts/statistics/distributions/hygernd.m, scripts/statistics/distributions/kolmogorov_smirnov_cdf.m, scripts/statistics/distributions/laplace_cdf.m, scripts/statistics/distributions/laplace_inv.m, scripts/statistics/distributions/laplace_pdf.m, scripts/statistics/distributions/laplace_rnd.m, scripts/statistics/distributions/logistic_cdf.m, scripts/statistics/distributions/logistic_inv.m, scripts/statistics/distributions/logistic_pdf.m, scripts/statistics/distributions/logistic_rnd.m, scripts/statistics/distributions/logncdf.m, scripts/statistics/distributions/logninv.m, scripts/statistics/distributions/lognpdf.m, scripts/statistics/distributions/lognrnd.m, scripts/statistics/distributions/nbincdf.m, scripts/statistics/distributions/nbininv.m, scripts/statistics/distributions/nbinpdf.m, scripts/statistics/distributions/nbinrnd.m, scripts/statistics/distributions/normcdf.m, scripts/statistics/distributions/norminv.m, scripts/statistics/distributions/normpdf.m, scripts/statistics/distributions/normrnd.m, scripts/statistics/distributions/poisscdf.m, scripts/statistics/distributions/poissinv.m, scripts/statistics/distributions/poisspdf.m, scripts/statistics/distributions/poissrnd.m, scripts/statistics/distributions/stdnormal_cdf.m, scripts/statistics/distributions/stdnormal_inv.m, scripts/statistics/distributions/stdnormal_pdf.m, scripts/statistics/distributions/stdnormal_rnd.m, scripts/statistics/distributions/tcdf.m, scripts/statistics/distributions/tinv.m, scripts/statistics/distributions/tpdf.m, scripts/statistics/distributions/trnd.m, scripts/statistics/distributions/unidcdf.m, scripts/statistics/distributions/unidinv.m, scripts/statistics/distributions/unidpdf.m, scripts/statistics/distributions/unidrnd.m, scripts/statistics/distributions/unifcdf.m, scripts/statistics/distributions/unifinv.m, scripts/statistics/distributions/unifpdf.m, scripts/statistics/distributions/unifrnd.m, scripts/statistics/distributions/wblcdf.m, scripts/statistics/distributions/wblinv.m, scripts/statistics/distributions/wblpdf.m, scripts/statistics/distributions/wblrnd.m, scripts/statistics/distributions/wienrnd.m, scripts/statistics/models/logistic_regression.m, scripts/statistics/models/private/logistic_regression_derivatives.m, scripts/statistics/models/private/logistic_regression_likelihood.m, scripts/statistics/tests/anova.m, scripts/statistics/tests/bartlett_test.m, scripts/statistics/tests/chisquare_test_homogeneity.m, scripts/statistics/tests/chisquare_test_independence.m, scripts/statistics/tests/cor_test.m, scripts/statistics/tests/f_test_regression.m, scripts/statistics/tests/hotelling_test.m, scripts/statistics/tests/hotelling_test_2.m, scripts/statistics/tests/kolmogorov_smirnov_test.m, scripts/statistics/tests/kolmogorov_smirnov_test_2.m, scripts/statistics/tests/kruskal_wallis_test.m, scripts/statistics/tests/manova.m, scripts/statistics/tests/mcnemar_test.m, scripts/statistics/tests/prop_test_2.m, scripts/statistics/tests/run_test.m, scripts/statistics/tests/sign_test.m, scripts/statistics/tests/t_test.m, scripts/statistics/tests/t_test_2.m, scripts/statistics/tests/t_test_regression.m, scripts/statistics/tests/u_test.m, scripts/statistics/tests/var_test.m, scripts/statistics/tests/welch_test.m, scripts/statistics/tests/wilcoxon_test.m, scripts/statistics/tests/z_test.m, scripts/statistics/tests/z_test_2.m, scripts/strings/base2dec.m, scripts/strings/bin2dec.m, scripts/strings/blanks.m, scripts/strings/cstrcat.m, scripts/strings/deblank.m, scripts/strings/dec2base.m, scripts/strings/dec2bin.m, scripts/strings/dec2hex.m, scripts/strings/findstr.m, scripts/strings/hex2dec.m, scripts/strings/index.m, scripts/strings/isletter.m, scripts/strings/isstrprop.m, scripts/strings/mat2str.m, scripts/strings/ostrsplit.m, scripts/strings/regexptranslate.m, scripts/strings/rindex.m, scripts/strings/str2num.m, scripts/strings/strcat.m, scripts/strings/strchr.m, scripts/strings/strjoin.m, scripts/strings/strjust.m, scripts/strings/strmatch.m, scripts/strings/strsplit.m, scripts/strings/strtok.m, scripts/strings/strtrim.m, scripts/strings/strtrunc.m, scripts/strings/substr.m, scripts/strings/untabify.m, scripts/strings/validatestring.m, scripts/testfun/__have_feature__.m, scripts/testfun/__printf_assert__.m, scripts/testfun/__prog_output_assert__.m, scripts/testfun/__run_test_suite__.m, scripts/testfun/assert.m, scripts/testfun/demo.m, scripts/testfun/example.m, scripts/testfun/fail.m, scripts/testfun/private/compare_plot_demos.m, scripts/testfun/private/dump_demos.m, scripts/testfun/private/html_compare_plot_demos.m, scripts/testfun/rundemos.m, scripts/testfun/runtests.m, scripts/testfun/speed.m, scripts/testfun/test.m, scripts/time/addtodate.m, scripts/time/asctime.m, scripts/time/calendar.m, scripts/time/clock.m, scripts/time/ctime.m, scripts/time/date.m, scripts/time/datenum.m, scripts/time/datestr.m, scripts/time/datevec.m, scripts/time/eomday.m, scripts/time/etime.m, scripts/time/is_leap_year.m, scripts/time/now.m, scripts/time/weekday.m, src/display-available.c, src/display-available.h, src/main-cli.cc, src/main-gui.cc, src/main.in.cc, src/mkoctfile.in.cc, src/octave-build-info.h, src/octave-build-info.in.cc, src/octave-config.in.cc, src/shared-fcns.h, test/args.tst, test/classdef/classdef.tst, test/classes/classes.tst, test/colormaps.tst, test/complex.tst, test/ctor-vs-method/ctor-vs-method.tst, test/diag-perm.tst, test/error.tst, test/eval-catch.tst, test/fcn-handle-derived-resolution/fcn-handle-derived-resolution.tst, test/fntests.m, test/for.tst, test/func.tst, test/global.tst, test/if.tst, test/index.tst, test/io.tst, test/jit.tst, test/line-continue.tst, test/logical-index.tst, test/nest/nest.tst, test/null-assign.tst, test/parser.tst, test/prefer.tst, test/range.tst, test/recursion.tst, test/return.tst, test/slice.tst, test/struct.tst, test/switch.tst, test/system.tst, test/transpose.tst, test/try.tst, test/unwind.tst, test/while.tst: Use the same Copyright formatting throughout Octave.
author Rik <rik@octave.org>
date Sun, 13 Nov 2016 20:33:47 -0800
parents 7abc25e6206a
children 86b6f79d4de1
line wrap: on
line source

/*

Copyright (C) 1996-2016 John W. Eaton
Copyright (C) 2015-2016 Lachlan Andrew, Monash University

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 (HAVE_CONFIG_H)
#  include "config.h"
#endif

#include <cassert>
#include <cctype>
#include <cstring>

#include <deque>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>

#include "Array.h"
#include "Cell.h"
#include "byte-swap.h"
#include "lo-ieee.h"
#include "lo-mappers.h"
#include "lo-utils.h"
#include "oct-locbuf.h"
#include "quit.h"
#include "singleton-cleanup.h"
#include "str-vec.h"

#include "error.h"
#include "errwarn.h"
#include "input.h"
#include "interpreter.h"
#include "octave.h"
#include "oct-stdstrm.h"
#include "oct-stream.h"
#include "ov.h"
#include "ovl.h"
#include "utils.h"

// Programming Note: There are two very different error functions used
// in the stream code.  When invoked with "error (...)" the member
// function from octave_stream or octave_base_stream is called.  This
// function sets the error state on the stream AND returns control to
// the caller.  The caller must then return a value at the end of the
// function.  When invoked with "::error (...)" the exception-based
// error function from error.h is used.  This function will throw an
// exception and not return control to the caller.  BE CAREFUL and
// invoke the correct error function!

// 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)
{
  conv_err = 0;

  int retval = 0;

  double dval = 0.0;

  try
    {
      dval = tc.double_value ();
    }
  catch (const octave::execution_exception&)
    {
      recover_from_exception ();

      conv_err = 1;
    }

  if (! conv_err)
    {
      if (! lo_ieee_isnan (dval))
        {
          int ival = octave::math::nint (dval);

          if (ival == dval)
            retval = ival;
          else
            conv_err = 3;
        }
      else
        conv_err = 2;
    }

  return retval;
}

static int
get_size (double d, const std::string& who)
{
  int retval = -1;

  if (lo_ieee_isnan (d))
    ::error ("%s: NaN is invalid as size specification", who.c_str ());

  if (octave::math::isinf (d))
    retval = -1;
  else
    {
      if (d < 0.0)
        ::error ("%s: negative value invalid as size specification",
                 who.c_str ());

      retval = octave::math::nint (d);
    }

  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.numel ();

  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 (octave::math::isinf (dnr))
        ::error ("%s: invalid size specification", who.c_str ());

      dnc = size(1);
    }
  else
    ::error ("%s: invalid size specification", who.c_str ());

  nr = get_size (dnr, who);

  if (dnc >= 0.0)
    nc = get_size (dnc, who);
}

class
scanf_format_elt
{
public:

  enum special_conversion
  {
    whitespace_conversion = 1,
    literal_conversion = 2,
    null = 3
  };

  scanf_format_elt (const char *txt = 0, int w = 0, bool d = false,
                    char typ = '\0', char mod = '\0',
                    const std::string& ch_class = "")
    : 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
scanf_format_list
{
public:

  scanf_format_list (const std::string& fmt = "");

  ~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.

  size_t length (void) const { return fmt_elts.size (); }

  const scanf_format_elt *first (void)
  {
    curr_idx = 0;
    return current ();
  }

  const scanf_format_elt *current (void) const
  {
    return length () > 0 ? fmt_elts[curr_idx] : 0;
  }

  const scanf_format_elt *next (bool cycle = true)
  {
    static scanf_format_elt dummy
      (0, 0, false, scanf_format_elt::null, '\0', "");

    curr_idx++;

    if (curr_idx >= length ())
      {
        if (cycle)
          curr_idx = 0;
        else
          return &dummy;
      }

    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;
  size_t curr_idx;

  // List of format elements.
  std::deque<scanf_format_elt*> fmt_elts;

  // Temporary buffer.
  std::ostringstream buf;

  void add_elt_to_list (int width, bool discard, char type, char modifier,
                        const std::string& char_class = "");

  void process_conversion (const std::string& s, size_t& i, size_t n,
                           int& width, bool& discard, char& type,
                           char& modifier);

  int finish_conversion (const std::string& s, size_t& i, size_t n,
                         int& width, bool discard, char& type,
                         char modifier);
  // No copying!

  scanf_format_list (const scanf_format_list&);

  scanf_format_list& operator = (const scanf_format_list&);
};

scanf_format_list::scanf_format_list (const std::string& s)
  : nconv (0), curr_idx (0), fmt_elts (), buf ()
{
  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 (s[i] == '%')
        {
          // Process percent-escape conversion type.

          process_conversion (s, i, n, width, discard, type, modifier);

          have_more = (buf.tellp () != 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);

          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);

          have_more = false;
        }

      if (nconv < 0)
        {
          have_more = false;
          break;
        }
    }

  if (have_more)
    add_elt_to_list (width, discard, type, modifier);

  buf.clear ();
  buf.str ("");
}

scanf_format_list::~scanf_format_list (void)
{
  size_t n = fmt_elts.size ();

  for (size_t i = 0; i < n; i++)
    {
      scanf_format_elt *elt = fmt_elts[i];
      delete elt;
    }
}

void
scanf_format_list::add_elt_to_list (int width, bool discard, char type,
                                    char modifier,
                                    const std::string& char_class)
{
  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);

      fmt_elts.push_back (elt);
    }

  buf.clear ();
  buf.str ("");
}

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)
{
  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 = 10 * width + c - '0';
              have_width = true;
              buf << c;
              while (i < n && isdigit (s[i]))
                {
                  c = s[i++];
                  width = 10 * width + 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) == 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)
{
  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, char_class);
    }

  return retval;
}

void
scanf_format_list::printme (void) const
{
  size_t n = fmt_elts.size ();

  for (size_t i = 0; i < n; i++)
    {
      scanf_format_elt *elt = fmt_elts[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)
{
  size_t n = fmt_elts.size ();

  if (n > 0)
    {
      for (size_t i = 0; i < n; i++)
        {
          scanf_format_elt *elt = fmt_elts[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)
{
  size_t n = fmt_elts.size ();

  if (n > 0)
    {
      for (size_t i = 0; i < n; i++)
        {
          scanf_format_elt *elt = fmt_elts[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;
}

class
printf_format_elt
{
public:

  printf_format_elt (const char *txt = 0, int n = 0, int w = -1,
                     int p = -1, const std::string& f = "",
                     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
printf_format_list
{
public:

  printf_format_list (const std::string& fmt = "");

  ~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 length () > 0 ? fmt_elts[curr_idx] : 0;
  }

  size_t length (void) const { return fmt_elts.size (); }

  const printf_format_elt *next (bool cycle = true)
  {
    curr_idx++;

    if (curr_idx >= length ())
      {
        if (cycle)
          curr_idx = 0;
        else
          return 0;
      }

    return current ();
  }

  bool last_elt_p (void) { return (curr_idx + 1 == 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;
  size_t curr_idx;

  // List of format elements.
  std::deque<printf_format_elt*> fmt_elts;

  // Temporary buffer.
  std::ostringstream buf;

  void add_elt_to_list (int args, const std::string& flags, int fw,
                        int prec, char type, char modifier);

  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);

  void finish_conversion (const std::string& s, size_t& i, int args,
                          const std::string& flags, int fw, int prec,
                          char modifier, char& type);

  // No copying!

  printf_format_list (const printf_format_list&);

  printf_format_list& operator = (const printf_format_list&);
};

printf_format_list::printf_format_list (const std::string& s)
  : nconv (0), curr_idx (0), fmt_elts (), buf ()
{
  size_t n = s.length ();

  size_t i = 0;

  int args = 0;
  std::string flags;
  int fw = -1;
  int prec = -1;
  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);

      fmt_elts.push_back (elt);
    }
  else
    {
      while (i < n)
        {
          have_more = true;

          empty_buf = (buf.tellp () == 0);

          switch (s[i])
            {
            case '%':
              {
                if (empty_buf)
                  {
                    process_conversion (s, i, n, args, flags, fw, prec,
                                        type, modifier);

                    // If there is nothing in the buffer, then
                    // add_elt_to_list must have just been called, so we
                    // are already done with the current element and we
                    // don't need to call add_elt_to_list if this is our
                    // last trip through the loop.

                    have_more = (buf.tellp () != 0);
                  }
                else
                  add_elt_to_list (args, flags, fw, prec, type, modifier);
              }
              break;

            default:
              {
                args = 0;
                flags = "";
                fw = -1;
                prec = -1;
                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);

      buf.clear ();
      buf.str ("");
    }
}

printf_format_list::~printf_format_list (void)
{
  size_t n = fmt_elts.size ();

  for (size_t i = 0; i < n; i++)
    {
      printf_format_elt *elt = fmt_elts[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)
{
  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);

      fmt_elts.push_back (elt);
    }

  buf.clear ();
  buf.str ("");
}

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)
{
  args = 0;
  flags = "";
  fw = -1;
  prec = -1;
  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 = -2;
          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] == '.')
    {
      // nothing before the . means 0.
      if (fw == -1)
        fw = 0;

      // . followed by nothing is 0.
      prec = 0;

      buf << s[i++];

      if (i < n)
        {
          if (s[i] == '*')
            {
              prec = -2;
              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)
    {
      // Accept and record modifier, but don't place it in the format
      // item text.  All integer conversions are handled as 64-bit
      // integers.

      switch (s[i])
        {
        case 'h': case 'l': case 'L':
          modifier = s[i++];
          break;

        default:
          break;
        }
    }

  if (i < n)
    finish_conversion (s, i, args, flags, fw, prec, modifier, type);
  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)
{
  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);

      break;

    default:
      nconv = -1;
      break;
    }
}

void
printf_format_list::printme (void) const
{
  size_t n = fmt_elts.size ();

  for (size_t i = 0; i < n; i++)
    {
      printf_format_elt *elt = fmt_elts[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";
    }
}

// Calculate x^n.  Used for ...e+nn so that, for example, 1e2 is
// exactly 100 and 5e-1 is 1/2

static double
pown (double x, unsigned int n)
{
  double retval = 1;

  for (unsigned int d = n; d; d >>= 1)
    {
      if (d & 1)
        retval *= x;
      x *= x;
    }

  return retval;
}

static Cell
init_inf_nan (void)
{
  Cell retval (dim_vector (1, 2));

  retval(0) = Cell (octave_value ("inf"));
  retval(1) = Cell (octave_value ("nan"));

  return retval;
}

namespace octave
{
  // Delimited stream, optimized to read strings of characters separated
  // by single-character delimiters.
  //
  // The reason behind this class is that octstream doesn't provide
  // seek/tell, but the opportunity has been taken to optimise for the
  // textscan workload.
  //
  // The function reads chunks into a 4kiB buffer, and marks where the
  // last delimiter occurs.  Reads up to this delimiter can be fast.
  // After that last delimiter, the remaining text is moved to the front
  // of the buffer and the buffer is refilled.  This also allows cheap
  // seek and tell operations within a "fast read" block.

  class
  delimited_stream
  {
  public:

    delimited_stream (std::istream& is, const std::string& delimiters,
                      int longest_lookahead, octave_idx_type bsize = 4096);

    delimited_stream (std::istream& is, const delimited_stream& ds);

    ~delimited_stream (void);

    // Called when optimized sequence of get is finished.  Ensures that
    // there is a remaining delimiter in buf, or loads more data in.
    void field_done (void)
    {
      if (idx >= last)
        refresh_buf ();
    }

    // Load new data into buffer, and set eob, last, idx.
    // Return EOF at end of file, 0 otherwise.
    int refresh_buf (void);

    // Get a character, relying on caller to call field_done if
    // a delimiter has been reached.
    int get (void)
    {
      if (delimited)
        return eof () ? std::istream::traits_type::eof () : *idx++;
      else
        return get_undelim ();
    }

    // Get a character, checking for underrun of the buffer.
    int get_undelim (void);

    // Read character that will be got by the next get.
    int peek (void) { return eof () ? std::istream::traits_type::eof () : *idx; }

    // Read character that will be got by the next get.
    int peek_undelim (void);

    // Undo a 'get' or 'get_undelim'.  It is the caller's responsibility
    // to avoid overflow by calling putbacks only for a character got by
    // get() or get_undelim(), with no intervening
    // get, get_delim, field_done, refresh_buf, getline, read or seekg.
    void putback (char /*ch*/ = 0) { if (! eof ()) --idx; }

    int getline  (std::string& dest, char delim);

    // int skipline (char delim);

    char *read (char *buffer, int size, char* &new_start);

    // Return a position suitable to "seekg", valid only within this
    // block between calls to field_done.
    char *tellg (void) { return idx; }

    void seekg (char *old_idx) { idx = old_idx; }

    bool eof (void)
    {
      return (eob == buf && i_stream.eof ()) || (flags & std::ios_base::eofbit);
    }

    operator const void* (void) { return (! eof () && ! flags) ? this : 0; }

    bool fail (void) { return flags & std::ios_base::failbit; }

    std::ios_base::iostate rdstate (void) { return flags; }

    void setstate (std::ios_base::iostate m) { flags = flags | m; }

    void clear (std::ios_base::iostate m
                = (std::ios_base::eofbit & ~std::ios_base::eofbit))
    {
      flags = flags & m;
    }

    // Report if any characters have been consumed.
    // (get, read, etc. not cancelled by putback or seekg)

    void progress_benchmark (void) { progress_marker = idx; }

    bool no_progress (void) { return progress_marker == idx; }

  private:

    // Number of characters to read from the file at once.
    int bufsize;

    // Stream to read from.
    std::istream& i_stream;

    // Temporary storage for a "chunk" of data.
    char *buf;

    // Current read pointer.
    char *idx;

    // Location of last delimiter in the buffer at buf (undefined if
    // delimited is false).
    char *last;

    // Position after last character in buffer.
    char *eob;

    // True if there is delimiter in the bufer after idx.
    bool delimited;

    // Longest lookahead required.
    int longest;

    // Sequence of single-character delimiters.
    const std::string delims;

    // Position of start of buf in original stream.
    std::streampos buf_in_file;

    // Marker to see if a read consumes any characters.
    char *progress_marker;

    std::ios_base::iostate flags;

    // No copying!

    delimited_stream (const delimited_stream&);

    delimited_stream& operator = (const delimited_stream&);
  };

  // Create a delimited stream, reading from is, with delimiters delims,
  // and allowing reading of up to tellg + longest_lookeahead.  When is
  // is at EOF, lookahead may be padded by ASCII nuls.

  delimited_stream::delimited_stream (std::istream& is,
                                      const std::string& delimiters,
                                      int longest_lookahead,
                                      octave_idx_type bsize)
    : bufsize (bsize), i_stream (is), longest (longest_lookahead),
      delims (delimiters),
      flags (std::ios::failbit & ~std::ios::failbit) // can't cast 0
  {
    buf = new char[bufsize];
    eob = buf + bufsize;
    idx = eob;                    // refresh_buf shouldn't try to copy old data
    progress_marker = idx;
    refresh_buf ();               // load the first batch of data
  }

  // Used to create a stream from a strstream from data read from a dstr.
  // FIXME: Find a more efficient approach.  Perhaps derived dstr
  delimited_stream::delimited_stream (std::istream& is,
                                      const delimited_stream& ds)
    : bufsize (ds.bufsize), i_stream (is), longest (ds.longest),
      delims (ds.delims),
      flags (std::ios::failbit & ~std::ios::failbit) // can't cast 0
  {
    buf = new char[bufsize];
    eob = buf + bufsize;
    idx = eob;                    // refresh_buf shouldn't try to copy old data
    progress_marker = idx;
    refresh_buf ();               // load the first batch of data
  }

  delimited_stream::~delimited_stream (void)
  {
    // Seek to the correct position in i_stream.
    if (! eof ())
      {
        i_stream.clear ();
        i_stream.seekg (buf_in_file);
        i_stream.read (buf, idx - buf);
      }

    delete [] buf;
  }

  // Read a character from the buffer, refilling the buffer from the file
  // if necessary.

  int
  delimited_stream::get_undelim (void)
  {
    int retval;
    if (eof ())
      {
        setstate (std::ios_base::failbit);
        return std::istream::traits_type::eof ();
      }

    if (idx < eob)
      retval = *idx++;
    else
      {
        refresh_buf ();

        if (eof ())
          {
            setstate (std::ios_base::eofbit);
            retval = std::istream::traits_type::eof ();
          }
        else
          retval = *idx++;
      }

    if (idx >= last)
      delimited = false;

    return retval;
  }

  // Return the next character to be read without incrementing the
  // pointer, refilling the buffer from the file if necessary.

  int
  delimited_stream::peek_undelim (void)
  {
    int retval = get_undelim ();
    putback ();

    return retval;
  }

  // Copy remaining unprocessed data to the start of the buffer and load
  // new data to fill it.  Return EOF if the file is at EOF before
  // reading any data and all of the data that has been read has been
  // processed.

  int
  delimited_stream::refresh_buf (void)
  {
    if (eof ())
      return std::istream::traits_type::eof ();

    int retval;

    if (eob < idx)
      idx = eob;

    size_t old_remaining = eob - idx;

    octave_quit ();                       // allow ctrl-C

    if (old_remaining > 0)
      {
        buf_in_file += (idx - buf);
        memmove (buf, idx, old_remaining);
      }

    progress_marker -= idx - buf;         // where original idx would have been
    idx = buf;

    int gcount;   // chars read
    if (! i_stream.eof ())
      {
        buf_in_file = i_stream.tellg ();   // record for destructor
        i_stream.read (buf + old_remaining, bufsize - old_remaining);
        gcount = i_stream.gcount ();
      }
    else
      gcount = 0;

    eob = buf + old_remaining + gcount;
    last = eob;
    if (gcount == 0)
      {
        delimited = false;

        if (eob != buf)              // no more data in file, but still some to go
          retval = 0;
        else
          // file and buffer are both done.
          retval = std::istream::traits_type::eof ();
      }
    else
      {
        delimited = true;

        for (last = eob - longest; last - buf >= 0; last--)
          {
            if (delims.find (*last) != std::string::npos)
              break;
          }

        if (last < buf)
          delimited = false;

        retval = 0;
      }

    // Ensure fast peek doesn't give valid char
    if (retval == std::istream::traits_type::eof ())
      *idx = '\0';    // FIXME: check that no TreatAsEmpty etc starts w. \0?

    return retval;
  }

  // Return a pointer to a block of data of size size, assuming that a
  // sufficiently large buffer is available in buffer, if required.
  // If called when delimited == true, and size is no greater than
  // longest_lookahead then this will not call refresh_buf, so seekg
  // still works.  Otherwise, seekg may be invalidated.

  char *
  delimited_stream::read (char *buffer, int size, char* &prior_tell)
  {
    char *retval;

    if (eob  - idx > size)
      {
        retval = idx;
        idx += size;
        if (idx > last)
          delimited = false;
      }
    else
      {
        // If there was a tellg pointing to an earlier point than the current
        // read position, try to keep it in the active buffer.
        // In the current code, prior_tell==idx for each call,
        // so this is not necessary, just a precaution.

        if (eob - prior_tell + size < bufsize)
          {
            octave_idx_type gap = idx - prior_tell;
            idx = prior_tell;
            refresh_buf ();
            idx += gap;
          }
        else      // can't keep the tellg in range.  May skip some data.
          {
            refresh_buf ();
          }

        prior_tell = buf;

        if (eob - idx > size)
          {
            retval = idx;
            idx += size;
            if (idx > last)
              delimited = false;
          }
        else
          {
            if (size <= bufsize)          // small read, but reached EOF
              {
                retval = idx;
                memset (eob, 0, size + (idx - buf));
                idx += size;
              }
            else  // Reading more than the whole buf; return it in buffer
              {
                retval = buffer;
                // FIXME: read bufsize at a time
                int i;
                for (i = 0; i < size && ! eof (); i++)
                  *buffer++ = get_undelim ();
                if (eof ())
                  memset (buffer, 0, size - i);
              }
          }
      }

    return retval;
  }

  // Return in OUT an entire line, terminated by delim.  On input, OUT
  // must have length at least 1.

  int
  delimited_stream::getline (std::string& out, char delim)
  {
    int len = out.length (), used = 0;
    int ch;
    while ((ch = get_undelim ()) != delim
           && ch != std::istream::traits_type::eof ())
      {
        out[used++] = ch;
        if (used == len)
          {
            len <<= 1;
            out.resize (len);
          }
      }
    out.resize (used);
    field_done ();

    return ch;
  }

  // A single conversion specifier, such as %f or %c.

  class
  textscan_format_elt
  {
  public:

    enum special_conversion
    {
      whitespace_conversion = 1,
      literal_conversion = 2
    };

    textscan_format_elt (const std::string& txt, int w = 0, int p = -1,
                         int bw = 0, bool dis = false, char typ = '\0',
                         const std::string& ch_class = std::string ())
      : text (txt), width (w), prec (p), bitwidth (bw),
        char_class (ch_class), type (typ), discard (dis),
        numeric (typ == 'd' || typ == 'u' || type == 'f' || type == 'n')
    { }

    textscan_format_elt (const textscan_format_elt& e)
      : text (e.text), width (e.width), prec (e.prec),
        bitwidth (e.bitwidth), char_class (e.char_class), type (e.type),
        discard (e.discard), numeric (e.numeric)
    { }

    textscan_format_elt& operator = (const textscan_format_elt& e)
    {
      if (this != &e)
        {
          text = e.text;
          width = e.width;
          prec = e.prec;
          bitwidth = e.bitwidth;
          discard = e.discard;
          type = e.type;
          numeric = e.numeric;
          char_class = e.char_class;
        }

      return *this;
    }

    // The C-style format string.
    std::string text;

    // The maximum field width.
    unsigned int width;

    // The maximum number of digits to read after the decimal in a
    // floating point conversion.
    int prec;

    // The size of the result.  For integers, bitwidth may be 8, 16, 34,
    // or 64.  For floating point values, bitwidth may be 32 or 64.
    int bitwidth;

    // The class of characters in a `[' or `^' format.
    std::string char_class;

    // Type of conversion
    //  -- `d', `u', `f', `n', `s', `q', `c', `%', `C', `D', `[' or `^'.
    char type;

    // TRUE if we are not storing the result of this conversion.
    bool discard;

    // TRUE if the type is 'd', 'u', 'f', 'n'
    bool numeric;
  };

  // The (parsed) sequence of format specifiers.

  class textscan;

  class
  textscan_format_list
  {
  public:

    textscan_format_list (const std::string& fmt = std::string (),
                          const std::string& who = "textscan");

    ~textscan_format_list (void);

    octave_idx_type num_conversions (void) const { 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.

    size_t numel (void) const { return fmt_elts.size (); }

    const textscan_format_elt *first (void)
    {
      curr_idx = 0;
      return current ();
    }

    const textscan_format_elt *current (void) const
    {
      return numel () > 0 ? fmt_elts[curr_idx] : 0;
    }

    const textscan_format_elt *next (bool cycle = true)
    {
      curr_idx++;

      if (curr_idx >= numel ())
        {
          if (cycle)
            curr_idx = 0;
          else
            return 0;
        }

      return current ();
    }

    void printme (void) const;

    bool ok (void) const { return (nconv >= 0); }

    operator const void* (void) const { return ok () ? this : 0; }

    // What function name should be shown when reporting errors.
    std::string who;

    // True if number of %f to be set from data file.
    bool set_from_first;

    // At least one conversion specifier is s,q,c, or [...].
    bool has_string;

    int read_first_row (delimited_stream& is, textscan& ts);

    std::list<octave_value> out_buf (void) const { return (output_container); }

  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;
    size_t curr_idx;

    // List of format elements.
    std::deque<textscan_format_elt*> fmt_elts;

    // list holding column arrays of types specified by conversions
    std::list<octave_value> output_container;

    // Temporary buffer.
    std::ostringstream buf;

    void add_elt_to_list (unsigned int width, int prec, int bitwidth,
                          octave_value val_type, bool discard,
                          char type,
                          const std::string& char_class = std::string ());

    void process_conversion (const std::string& s, size_t& i, size_t n);

    std::string parse_char_class (const std::string& pattern) const;

    int finish_conversion (const std::string& s, size_t& i, size_t n,
                           unsigned int& width, int& prec, int& bitwidth,
                           octave_value& val_type,
                           bool discard, char& type);
    // No copying!

    textscan_format_list (const textscan_format_list&);

    textscan_format_list& operator = (const textscan_format_list&);
  };

  // Main class to implement textscan.  Read data and parse it
  // according to a format.
  //
  // The calling sequence is
  //
  //   textscan scanner ();
  //   scanner.scan (...);

  class
  OCTINTERP_API
  textscan
  {
  public:

    textscan (const std::string& who_arg = "textscan");

    ~textscan (void) { }

    octave_value scan (std::istream& isp, const std::string& fmt,
                       octave_idx_type ntimes,
                       const octave_value_list& options,
                       octave_idx_type& read_count);

  private:

    friend class textscan_format_list;

    // What function name should be shown when reporting errors.
    std::string who;

    std::string buf;

    // Three cases for delim_table and delim_list
    // 1. delim_table empty, delim_list empty:  whitespace delimiters
    // 2. delim_table = look-up table of delim chars, delim_list empty.
    // 3. delim_table non-empty, delim_list = Cell array of delim strings

    std::string whitespace_table;

    // delim_table[i] == '\0' if i is not a delimiter.
    std::string delim_table;

    // String of delimiter characters.
    std::string delims;

    Cell comment_style;

    // How far ahead to look to detect an open comment.
    int comment_len;

    // First character of open comment.
    int comment_char;

    octave_idx_type buffer_size;

    std::string date_locale;

    // 'inf' and 'nan' for formatted_double.
    Cell inf_nan;

    // Array of strings of delimiters.
    Cell delim_list;

    // Longest delimiter.
    int delim_len;

    octave_value empty_value;
    std::string exp_chars;
    int header_lines;
    Cell treat_as_empty;

    // Longest string to treat as "N/A".
    int treat_as_empty_len;

    std::string whitespace;

    short eol1;
    short eol2;
    short return_on_error;

    bool collect_output;
    bool multiple_delims_as_one;
    bool default_exp;
    bool numeric_delim;

    octave_idx_type lines;

    octave_value do_scan (std::istream& isp, textscan_format_list& fmt_list,
                          octave_idx_type ntimes);

    void parse_options (const octave_value_list& args,
                        textscan_format_list& fmt_list);

    int read_format_once (delimited_stream& isp, textscan_format_list& fmt_list,
                          std::list<octave_value>& retval,
                          Array<octave_idx_type> row, int& done_after);

    void scan_one (delimited_stream& is, const textscan_format_elt& fmt,
                   octave_value& ov, Array<octave_idx_type> row);

    // Methods to process a particular conversion specifier.
    double read_double (delimited_stream& is,
                        const textscan_format_elt& fmt) const;

    void scan_complex (delimited_stream& is, const textscan_format_elt& fmt,
                       Complex& val) const;

    int scan_bracket (delimited_stream& is, const std::string& pattern,
                      std::string& val) const;

    int scan_caret (delimited_stream& is, const std::string& pattern,
                    std::string& val) const;

    void scan_string (delimited_stream& is, const textscan_format_elt& fmt,
                      std::string& val) const;

    void scan_cstring (delimited_stream& is, const textscan_format_elt& fmt,
                       std::string& val) const;

    void scan_qstring (delimited_stream& is, const textscan_format_elt& fmt,
                       std::string& val);

    // Helper methods.
    std::string read_until (delimited_stream& is, const Cell& delimiters,
                            const std::string& ends) const;

    int lookahead (delimited_stream& is, const Cell& targets, int max_len,
                   bool case_sensitive = true) const;

    bool match_literal (delimited_stream& isp, const textscan_format_elt& elem);

    int skip_whitespace (delimited_stream& is, bool EOLstop = false);

    int skip_delim (delimited_stream& is);

    bool is_delim (unsigned char ch) const
    {
      return ((delim_table.empty () && (isspace (ch) || ch == eol1 || ch == eol2))
              || delim_table[ch] != '\0');
    }

    bool isspace (unsigned int ch) const { return whitespace_table[ch & 0xff]; }

    // True if the only delimiter is whitespace.
    bool whitespace_delim (void) const { return delim_table.empty (); }

    // No copying!

    textscan (const textscan&);

    textscan& operator = (const textscan&);
  };

  textscan_format_list::textscan_format_list (const std::string& s,
                                              const std::string& who_arg)
    : who (who_arg), set_from_first (false), has_string (false),
      nconv (0), curr_idx (0), fmt_elts (), buf ()
  {
    size_t n = s.length ();

    size_t i = 0;

    unsigned int width = -1;              // Unspecified width = max (except %c)
    int prec = -1;
    int bitwidth = 0;
    bool discard = false;
    char type = '\0';

    bool have_more = true;

    if (s.empty ())
      {
        buf.clear ();
        buf.str ("");

        buf << "%f";

        bitwidth = 64;
        type = 'f';
        add_elt_to_list (width, prec, bitwidth, octave_value (NDArray ()),
                         discard, type);
        have_more = false;
        set_from_first = true;
        nconv = 1;
      }
    else
      {
        set_from_first = false;

        while (i < n)
          {
            have_more = true;

            if (s[i] == '%' && (i+1 == n || s[i+1] != '%'))
              {
                // Process percent-escape conversion type.

                process_conversion (s, i, n);

                // If there is nothing in the buffer, then add_elt_to_list
                // must have just been called, so we are already done with
                // the current element and we don't need to call
                // add_elt_to_list if this is our last trip through the
                // loop.

                have_more = (buf.tellp () != 0);
              }
            else if (isspace (s[i]))
              {
                while (++i < n && isspace (s[i]))
                  /* skip whitespace */;

                have_more = false;
              }
            else
              {
                type = textscan_format_elt::literal_conversion;

                width = 0;
                prec = -1;
                bitwidth = 0;
                discard = true;

                while (i < n && ! isspace (s[i])
                       && (s[i] != '%' || (i+1 < n && s[i+1] == '%')))
                  {
                    if (s[i] == '%')      // if double %, skip one
                      i++;
                    buf << s[i++];
                    width++;
                  }

                add_elt_to_list (width, prec, bitwidth, octave_value (),
                                 discard, type);

                have_more = false;
              }

            if (nconv < 0)
              {
                have_more = false;
                break;
              }
          }
      }

    if (have_more)
      add_elt_to_list (width, prec, bitwidth, octave_value (), discard, type);

    buf.clear ();
    buf.str ("");
  }

  textscan_format_list::~textscan_format_list (void)
  {
    size_t n = numel ();

    for (size_t i = 0; i < n; i++)
      {
        textscan_format_elt *elt = fmt_elts[i];
        delete elt;
      }
  }

  void
  textscan_format_list::add_elt_to_list (unsigned int width, int prec,
                                         int bitwidth, octave_value val_type,
                                         bool discard, char type,
                                         const std::string& char_class)
  {
    std::string text = buf.str ();

    if (! text.empty ())
      {
        textscan_format_elt *elt
          = new textscan_format_elt (text, width, prec, bitwidth, discard, type,
                                     char_class);

        if (! discard)
          output_container.push_back (val_type);

        fmt_elts.push_back (elt);
      }

    buf.clear ();
    buf.str ("");
  }

  void
  textscan_format_list::process_conversion (const std::string& s, size_t& i,
                                            size_t n)
  {
    unsigned width = 0;
    int prec = -1;
    int bitwidth = 0;
    bool discard = false;
    octave_value val_type;
    char 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;
                  }

                if (i < n && s[i] == '.')
                  {
                    buf << s[i++];
                    prec = 0;
                    while (i < n && isdigit (s[i]))
                      {
                        c = s[i++];
                        prec = prec * 10 + c - '0';
                        buf << c;
                      }
                  }
              }
            break;

          case 'd': case 'u':
            {
              bool done = true;
              buf << (type = s[i++]);
              if (i < n)
                {
                  if (s[i] == '8')
                    {
                      bitwidth = 8;
                      if (type == 'd')
                        val_type = octave_value (int8NDArray ());
                      else
                        val_type = octave_value (uint8NDArray ());
                      buf << s[i++];
                    }
                  else if (s[i] == '1' && i+1 < n && s[i+1] == '6')
                    {
                      bitwidth = 16;
                      if (type == 'd')
                        val_type = octave_value (int16NDArray ());
                      else
                        val_type = octave_value (uint16NDArray ());
                      buf << s[i++];
                      buf << s[i++];
                    }
                  else if (s[i] == '3' && i+1 < n && s[i+1] == '2')
                    {
                      done = false;       // use default size below
                      buf << s[i++];
                      buf << s[i++];
                    }
                  else if (s[i] == '6' && i+1 < n && s[i+1] == '4')
                    {
                      bitwidth = 64;
                      if (type == 'd')
                        val_type = octave_value (int64NDArray ());
                      else
                        val_type = octave_value (uint64NDArray ());
                      buf << s[i++];
                      buf << s[i++];
                    }
                  else
                    done = false;
                }
              else
                done = false;

              if (! done)
                {
                  bitwidth = 32;
                  if (type == 'd')
                    val_type = octave_value (int32NDArray ());
                  else
                    val_type = octave_value (uint32NDArray ());
                }
              goto fini;
            }

          case 'f':
            buf << (type = s[i++]);
            bitwidth = 64;
            if (i < n)
              {
                if (s[i] == '3' && i+1 < n && s[i+1] == '2')
                  {
                    bitwidth = 32;
                    val_type = octave_value (FloatNDArray ());
                    buf << s[i++];
                    buf << s[i++];
                  }
                else if (s[i] == '6' && i+1 < n && s[i+1] == '4')
                  {
                    val_type = octave_value (NDArray ());
                    buf << s[i++];
                    buf << s[i++];
                  }
                else
                  val_type = octave_value (NDArray ());
              }
            else
              val_type = octave_value (NDArray ());
            goto fini;

          case 'n':
            buf << (type = s[i++]);
            bitwidth = 64;
            val_type = octave_value (NDArray ());
            goto fini;

          case 's': case 'q': case '[': case 'c':
            if (! discard)
              val_type = octave_value (Cell ());
            buf << (type = s[i++]);
            has_string = true;
            goto fini;

          fini:
            {
              if (! have_width)
                {
                  if (type == 'c')        // %c defaults to one character
                    width = 1;
                  else
                    width = static_cast<unsigned int> (-1); // others: unlimited
                }

              if (finish_conversion (s, i, n, width, prec, bitwidth, val_type,
                                     discard, type) == 0)
                return;
            }
            break;

          default:
            error ("%s: '%%%c' is not a valid format specifier",
                   who.c_str (), s[i]);
          }

        if (nconv < 0)
          break;
      }

    nconv = -1;
  }

  // Parse [...] and [^...]
  //
  // Matlab does not expand expressions like A-Z, but they are useful, and
  // so we parse them "carefully".  We treat '-' as a usual character
  // unless both start and end characters are from the same class (upper
  // case, lower case, numeric), or this is not the first '-' in the
  // pattern.
  //
  // Keep both a running list of characters and a mask of which chars have
  // occurred.  The first is efficient for patterns with few characters.
  // The latter is efficient for [^...] patterns.

  std::string
  textscan_format_list::parse_char_class (const std::string& pattern) const
  {
    int len = pattern.length ();
    if (len == 0)
      return "";

    std::string retval (256, '\0');
    std::string mask   (256, '\0');       // number of times chr has been seen

    int in = 0, out = 0;
    unsigned char ch, prev = 0;
    bool flip = false;

    ch = pattern[in];
    if (ch == '^')
      {
        in++;
        flip = true;
      }
    mask[pattern[in]] = '\1';
    retval[out++] = pattern[in++];        // even copy ']' if it is first

    bool prev_was_range = false;          // disallow "a-m-z" as a pattern
    bool prev_prev_was_range = false;
    for (; in < len; in++)
      {
        bool was_range = false;
        ch = pattern[in];
        if (ch == ']')
          break;

        if (prev == '-' && in > 1 && isalnum (ch) && ! prev_prev_was_range)
          {
            unsigned char start_of_range = pattern[in-2];
            if (start_of_range < ch
                && ((isupper (ch) && isupper (start_of_range))
                    || (islower (ch) && islower (start_of_range))
                    || (isdigit (ch) && isdigit (start_of_range))
                    || mask['-'] > 1))    // not the first '-'
              {
                was_range = true;
                out--;
                mask['-']--;
                for (int i = start_of_range; i <= ch; i++)
                  {
                    if (mask[i] == '\0')
                      {
                        mask[i] = '\1';
                        retval[out++] = i;
                      }
                  }
              }
          }
        if (! was_range)
          {
            if (mask[ch]++ == 0)
              retval[out++] = ch;
            else if (ch != '-')
              warning_with_id ("octave:textscan-pattern",
                               "%s: [...] contains two '%c's",
                               who.c_str (), ch);

            if (prev == '-' && mask['-'] >= 2)
              warning_with_id
                ("octave:textscan-pattern",
                 "%s: [...] contains two '-'s outside range expressions",
                 who.c_str ());
          }
        prev = ch;
        prev_prev_was_range = prev_was_range;
        prev_was_range = was_range;
      }

    if (flip)                             // [^...]
      {
        out = 0;
        for (int i = 0; i < 256; i++)
          if (! mask[i])
            retval[out++] = i;
      }

    retval.resize (out);

    return retval;
  }

  int
  textscan_format_list::finish_conversion (const std::string& s, size_t& i,
                                           size_t n, unsigned int& width,
                                           int& prec, int& bitwidth,
                                           octave_value& val_type, bool discard,
                                           char& type)
  {
    int retval = 0;

    std::string char_class;

    size_t beg_idx = std::string::npos;
    size_t end_idx = std::string::npos;

    if (type != '%')
      {
        nconv++;
        if (type == '[')
          {
            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;
          }
      }

    if (nconv >= 0)
      {
        if (beg_idx != std::string::npos && end_idx != std::string::npos)
          char_class = parse_char_class (s.substr (beg_idx,
                                                   end_idx - beg_idx + 1));

        add_elt_to_list (width, prec, bitwidth, val_type, discard, type,
                         char_class);
      }

    return retval;
  }

  void
  textscan_format_list::printme (void) const
  {
    size_t n = numel ();

    for (size_t i = 0; i < n; i++)
      {
        textscan_format_elt *elt = fmt_elts[i];

        std::cerr
          << "width:      " << elt->width << "\n"
          << "digits      " << elt->prec << "\n"
          << "bitwidth:   " << elt->bitwidth << "\n"
          << "discard:    " << elt->discard << "\n"
          << "type:       ";

        if (elt->type == textscan_format_elt::literal_conversion)
          std::cerr << "literal text\n";
        else if (elt->type == textscan_format_elt::whitespace_conversion)
          std::cerr << "whitespace\n";
        else
          std::cerr << elt->type << "\n";

        std::cerr
          << "char_class: `" << undo_string_escapes (elt->char_class) << "'\n"
          << "text:       `" << undo_string_escapes (elt->text) << "'\n\n";
      }
  }

  // If FORMAT is explicitly "", it is assumed to be "%f" repeated enough
  // times to read the first row of the file.  Set it now.

  int
  textscan_format_list::read_first_row (delimited_stream& is, textscan& ts)
  {
    // Read first line and strip end-of-line, which may be two characters
    std::string first_line (20, ' ');

    is.getline (first_line, static_cast<char> (ts.eol2));

    if (! first_line.empty ()
        && first_line[first_line.length () - 1] == ts.eol1)
      first_line.resize (first_line.length () - 1);

    std::istringstream strstr (first_line);
    delimited_stream ds (strstr, is);

    dim_vector dv (1,1);      // initial size of each output_container
    Complex val;
    octave_value val_type;
    nconv = 0;
    int max_empty = 1000;     // failsafe, if ds fails but not with eof
    int retval = 0;

    // read line, creating output_container as we go
    while (! ds.eof ())
      {
        bool already_skipped_delim = false;
        ts.skip_whitespace (ds);
        ds.progress_benchmark ();
        bool progress = false;
        ts.scan_complex (ds, *fmt_elts[0], val);
        if (ds.fail ())
          {
            ds.clear (ds.rdstate () & ~std::ios::failbit);

            if (ds.eof ())
              break;

            // Unless this was a missing value (i.e., followed by a delimiter),
            // return with an error status.
            ts.skip_delim (ds);
            if (ds.no_progress ())
              {
                retval = 4;
                break;
              }
            already_skipped_delim = true;

            val = ts.empty_value.scalar_value ();

            if (! --max_empty)
              break;
          }

        if (val.imag () == 0)
          val_type = octave_value (NDArray (dv, val.real ()));
        else
          val_type = octave_value (ComplexNDArray (dv, val));

        output_container.push_back (val_type);

        if (! already_skipped_delim)
          ts.skip_delim (ds);

        if (! progress && ds.no_progress ())
          break;

        nconv++;
      }

    output_container.pop_front (); // discard empty element from constructor

    // Create fmt_list now that the size is known
    for (octave_idx_type i = 1; i < nconv; i++)
      fmt_elts.push_back (new textscan_format_elt (*fmt_elts[0]));

    return retval;             // May have returned 4 above.
  }

  textscan::textscan (const std::string& who_arg)
    : who (who_arg), buf (), whitespace_table (), delim_table (),
      delims (), comment_style (), comment_len (0), comment_char (-2),
      buffer_size (0), date_locale (), inf_nan (init_inf_nan ()),
      empty_value (octave::numeric_limits<double>::NaN ()), exp_chars ("edED"),
      header_lines (0), treat_as_empty (), treat_as_empty_len (0),
      whitespace (" \b\t"), eol1 ('\r'), eol2 ('\n'),
      return_on_error (1), collect_output (false),
      multiple_delims_as_one (false), default_exp (true),
      numeric_delim (false), lines (0)
  { }

  octave_value
  textscan::scan (std::istream& isp, const std::string& fmt,
                  octave_idx_type ntimes, const octave_value_list& options,
                  octave_idx_type& count)
  {
    textscan_format_list fmt_list (fmt);

    parse_options (options, fmt_list);

    octave_value result = do_scan (isp, fmt_list, ntimes);

    // FIXME: this is probably not the best way to get count.  The
    // position could easily be larger than octave_idx_type when using
    // 32-bit indexing.

    std::ios::iostate state = isp.rdstate ();
    isp.clear ();
    count = static_cast<octave_idx_type> (isp.tellg ());
    isp.setstate (state);

    return result;
  }

  octave_value
  textscan::do_scan (std::istream& isp, textscan_format_list& fmt_list,
                     octave_idx_type ntimes)
  {
    octave_value retval;

    if (fmt_list.num_conversions () == -1)
      error ("%s: invalid format specified", who.c_str ());

    if (fmt_list.num_conversions () == 0)
      error ("%s: no valid format conversion specifiers", who.c_str ());

    // skip the first header_lines
    std::string dummy;
    for (int i = 0; i < header_lines && isp; i++)
      getline (isp, dummy, static_cast<char> (eol2));

    // Create our own buffered stream, for fast get/putback/tell/seek.

    // First, see how far ahead it should let us look.
    int max_lookahead = std::max (std::max (comment_len, treat_as_empty_len),
                                  std::max (delim_len, 3)); // 3 for NaN and Inf

    // Next, choose a buffer size to avoid reading too much, or too often.
    octave_idx_type buf_size = 4096;
    if (buffer_size)
      buf_size = buffer_size;
    else if (ntimes > 0)
      {
        // Avoid overflow of 80*ntimes...
        buf_size = std::min (buf_size, std::max (ntimes, 80 * ntimes));
        buf_size = std::max (buf_size, ntimes);
      }
    // Finally, create the stream.
    delimited_stream is (isp,
                         (delim_table.empty () ? whitespace + "\r\n" : delims),
                         max_lookahead, buf_size);

    // Grow retval dynamically.  "size" is half the initial size
    // (FIXME: Should we start smaller if ntimes is large?)
    octave_idx_type size = ((ntimes < 8 && ntimes >= 0) ? ntimes : 1);
    Array<octave_idx_type> row_idx (dim_vector (1,2));
    row_idx(1) = 0;

    int err = 0;
    octave_idx_type row = 0;

    if (multiple_delims_as_one)           // bug #44750?
      skip_delim (is);

    int done_after;  // Number of columns read when EOF seen.

    // If FORMAT explicitly "", read first line and see how many "%f" match
    if (fmt_list.set_from_first)
      {
        err = fmt_list.read_first_row (is, *this);
        lines = 1;

        done_after = fmt_list.numel () + 1;
        if (! err)
          row = 1;  // the above puts the first line into fmt_list.out_buf ()
      }
    else
      done_after = fmt_list.out_buf ().size () + 1;

    std::list<octave_value> out = fmt_list.out_buf ();

    // We will later merge adjacent columns of the same type.
    // Check now which columns to merge.
    // Reals may become complex, and so we can't trust types
    // after reading in data.
    // If the format was "", that conversion may already have happened,
    // so force all to be merged (as all are %f).
    bool merge_with_prev[fmt_list.numel ()];
    int conv = 0;
    if (collect_output)
      {
        int prev_type = -1;
        for (std::list<octave_value>::iterator col = out.begin ();
             col != out.end (); col++)
          {
            if (col->type_id () == prev_type
                || (fmt_list.set_from_first && prev_type != -1))
              merge_with_prev [conv++] = true;
            else
              merge_with_prev [conv++] = false;

            prev_type = col->type_id ();
          }
      }

    // This should be caught by earlier code, but this avoids a possible
    // infinite loop below.
    if (fmt_list.num_conversions () == 0)
      error ("%s: No conversions specified", who.c_str ());

    // Read the data.  This is the main loop.
    if (! err)
      {
        for (/* row set ~30 lines above */; row < ntimes || ntimes == -1; row++)
          {
            if (row == 0 || row >= size)
              {
                size += size+1;
                for (std::list<octave_value>::iterator col = out.begin ();
                     col != out.end (); col++)
                  *col = (*col).resize (dim_vector (size, 1), 0);
              }

            row_idx(0) = row;
            err = read_format_once (is, fmt_list, out, row_idx, done_after);

            if ((err & ~1) > 0 || ! is || (lines >= ntimes && ntimes > -1))
              break;
          }
      }

    if ((err & 4) && ! return_on_error)
      error ("%s: Read error in field %d of row %d", who.c_str (),
             done_after + 1, row + 1);

    // If file does not end in EOL, do not pad columns with NaN.
    bool uneven_columns = false;
    if (err & 4)
      uneven_columns = true;
    else if (isp.eof ())
      {
        isp.clear ();
        isp.seekg (-1, std::ios_base::end);
        int last_char = isp.get ();
        isp.setstate (isp.eofbit);
        uneven_columns = (last_char != eol1 && last_char != eol2);
      }

    // convert return value to Cell array
    Array<octave_idx_type> ra_idx (dim_vector (1,2));

    // (err & 1) means "error, and no columns read this row
    // FIXME: This may redundant now that done_after=0 says the same
    if (err & 1)
      done_after = out.size () + 1;

    int valid_rows = (row == ntimes) ? ntimes
                                     : (((err & 1) && (err & 8)) ? row : row+1);
    dim_vector dv (valid_rows, 1);

    ra_idx(0) = 0;
    int i = 0;
    if (! collect_output)
      {
        retval = Cell (dim_vector (1, out.size ()));
        for (std::list<octave_value>::iterator col = out.begin ();
             col != out.end (); col++, i++)
          {
            // trim last columns if that was requested
            if (i == done_after && uneven_columns)
              dv = dim_vector (std::max (valid_rows - 1, 0), 1);

            ra_idx(1) = i;
            retval = do_cat_op (retval, octave_value (Cell (col->resize (dv,0))),
                                ra_idx);
          }
      }
    else  // group adjacent cells of the same type into a single cell
      {
        octave_value cur;                // current cell, accumulating columns
        octave_idx_type group_size = 0;  // columns in this cell
        int prev_type = -1;

        conv = 0;
        retval = Cell ();
        for (std::list<octave_value>::iterator col = out.begin ();
             col != out.end (); col++)
          {
            if (! merge_with_prev [conv++])  // including first time
              {
                if (prev_type != -1)
                  {
                    ra_idx(1) = i++;
                    retval = do_cat_op (retval, octave_value (Cell (cur)),
                                        ra_idx);
                  }
                cur = octave_value (col->resize (dv,0));
                group_size = 1;
                prev_type = col->type_id ();
              }
            else
              {
                ra_idx(1) = group_size++;
                cur = do_cat_op (cur, octave_value (col->resize (dv,0)),
                                 ra_idx);
              }
          }
        ra_idx(1) = i;
        retval = do_cat_op (retval, octave_value (Cell (cur)), ra_idx);
      }

    return retval;
  }

  // Read a double considering the "precision" field of FMT and the
  // EXP_CHARS option of OPTIONS.

  double
  textscan::read_double (delimited_stream& is,
                         const textscan_format_elt& fmt) const
  {
    int sign = 1;
    unsigned int width_left = fmt.width;
    double retval = 0;
    bool valid = false;         // syntactically correct double?

    int ch = is.peek ();

    if (ch == '+')
      {
        is.get ();
        ch = is.peek ();
        if (width_left)
          width_left--;
      }
    else if (ch == '-')
      {
        sign = -1;
        is.get ();
        ch = is.peek ();
        if (width_left)
          width_left--;
      }

    // Read integer part
    if (ch != '.')
      {
        if (ch >= '0' && ch <= '9')       // valid if at least one digit
          valid = true;
        while (width_left-- && is && (ch = is.get ()) >= '0' && ch <= '9')
          retval = retval * 10 + (ch - '0');
        width_left++;
      }

    // Read fractional part, up to specified precision
    if (ch == '.' && width_left)
      {
        double multiplier = 1;
        int precision = fmt.prec;
        int i;

        if (width_left)
          width_left--;                // Consider width of '.'

        if (precision == -1)
          precision = 1<<30;           // FIXME: Should be MAXINT

        if (! valid)                   // if there was nothing before '.'...
          is.get ();                   // ...ch was a "peek", not "get".

        for (i = 0; i < precision; i++)
          {
            if (width_left-- && is && (ch = is.get ()) >= '0' && ch <= '9')
              retval += (ch - '0') * (multiplier *= 0.1);
            else
              {
                width_left++;
                break;
              }
          }

        // round up if we truncated and the next digit is >= 5
        if ((i == precision || ! width_left) && (ch = is.get ()) >= '5'
            && ch <= '9')
          retval += multiplier;

        if (i > 0)
          valid = true;           // valid if at least one digit after '.'

        // skip remainder after '.', to field width, to look for exponent
        if (i == precision)
          while (width_left-- && is && (ch = is.get ()) >= '0' && ch <= '9')
            ;  // discard

        width_left++;
      }

    // look for exponent part in, e.g.,  6.023E+23
    bool used_exp = false;
    if (valid && width_left > 1 && exp_chars.find (ch) != std::string::npos)
      {
        int ch1 = is.peek ();
        if (ch1 == '-' || ch1 == '+' || (ch1 >= '0' && ch1 <= '9'))
          {
            // if 1.0e+$ or some such, this will set failbit, as we want
            width_left--;                         // count "E"
            int exp = 0;
            int exp_sign = 1;
            if (ch1 == '+')
              {
                if (width_left)
                  width_left--;
                is.get ();
              }
            else if (ch1 == '-')
              {
                exp_sign = -1;
                is.get ();
                if (width_left)
                  width_left--;
              }
            valid = false;
            while (width_left-- && is && (ch = is.get ()) >= '0' && ch <= '9')
              {
                exp = exp*10 + ch - '0';
                valid = true;
              }
            width_left++;
            if (ch != std::istream::traits_type::eof () && width_left)
              is.putback (ch);

            double multiplier = pown (10, exp);
            if (exp_sign > 0)
              retval *= multiplier;
            else
              retval /= multiplier;

            used_exp = true;
          }
      }
    is.clear ();
    if (! used_exp && ch != std::istream::traits_type::eof () && width_left)
      is.putback (ch);

    // Check for +/- inf and NaN
    if (! valid && width_left >= 3)
      {
        int i = lookahead (is, inf_nan, 3, false);   // false -> case insensitive
        if (i == 0)
          {
            retval = octave::numeric_limits<double>::Inf ();
            valid = true;
          }
        else if (i == 1)
          {
            retval = octave::numeric_limits<double>::NaN ();
            valid = true;
          }
      }

    // Check for +/- inf and NaN
    if (! valid && width_left >= 3)
      {
        int i = lookahead (is, inf_nan, 3, false);   // false -> case insensitive
        if (i == 0)
          {
            retval = octave::numeric_limits<double>::Inf ();
            valid = true;
          }
        else if (i == 1)
          {
            retval = octave::numeric_limits<double>::NaN ();
            valid = true;
          }
      }

    if (! valid)
      is.setstate (std::ios::failbit);
    else
      is.setstate (is.rdstate () & ~std::ios::failbit);

    return retval * sign;
  }

  // Read a single number: real, complex, inf, NaN, possibly with limited
  // precision.  Calls to this should be preceded by skip_whitespace.
  // Calling that inside scan_complex would violate its const declaration.

  void
  textscan::scan_complex (delimited_stream& is, const textscan_format_elt& fmt,
                          Complex& val) const
  {
    double im = 0;
    double re = 0;
    bool as_empty = false;   // did we fail but match a "treat_as_empty" string?
    bool inf = false;

    int ch = is.peek ();
    if (ch == '+' || ch == '-')   // check for [+-][ij] with no coefficients
      {
        ch = is.get ();
        int ch2 = is.peek ();
        if (ch2 == 'i' || ch2 == 'j')
          {
            double value = 1;
            is.get ();
            // Check not -inf
            if (is.peek () == 'n')
              {
                char *pos = is.tellg ();
                std::ios::iostate state = is.rdstate ();

                is.get ();
                ch2 = is.get ();
                if (ch2 == 'f')
                  {
                    inf = true;
                    re = (ch == '+') ? octave::numeric_limits<double>::Inf ()
                                     : -octave::numeric_limits<double>::Inf ();
                    value = 0;
                  }
                else
                  {
                    is.clear (state);
                    is.seekg (pos);   // reset to position before look-ahead
                  }
              }

            im = (ch == '+') ? value : -value;
          }
        else
          is.putback (ch);
      }

    if (! im && ! inf)        // if not [+-][ij] or [+-]inf, read real normally
      {
        char *pos = is.tellg ();
        std::ios::iostate state = is.rdstate ();
        //re = octave_read_value<double> (is);
        re = read_double (is, fmt);

        // check for "treat as empty" string
        if (treat_as_empty.numel ()
            && (is.fail () || octave::math::is_NaN_or_NA (Complex (re))
                || re == octave::numeric_limits<double>::Inf ()))
          {

            for (int i = 0; i < treat_as_empty.numel (); i++)
              {
                if (ch == treat_as_empty (i).string_value ()[0])
                  {
                    as_empty = true;   // first char matches, so read the lot
                    break;
                  }
              }
            if (as_empty)              // if first char matched...
              {
                as_empty = false;      // ...look for the whole string

                is.clear (state);      // treat_as_empty "-" causes partial read
                is.seekg (pos);        // reset to position before failed read

                // treat_as_empty strings may be different sizes.
                // Read ahead longest, put it all back, then re-read the string
                // that matches.
                std::string look_buf (treat_as_empty_len, '\0');
                char *look = is.read (&look_buf[0], look_buf.size (), pos);

                is.clear (state);
                is.seekg (pos);        // reset to position before look-ahead
                                       // FIXME: is.read could invalidate pos

                for (int i = 0; i < treat_as_empty.numel (); i++)
                  {
                    std::string s = treat_as_empty (i).string_value ();
                    if (! strncmp (s.c_str (), look, s.size ()))
                      {
                        as_empty = true;
                        // read just the right amount
                        is.read (&look_buf[0], s.size (), pos);
                        break;
                      }
                  }
              }
          }

        if (! is.eof () && ! as_empty)
          {
            state = is.rdstate ();        // before tellg, since that fails at EOF
            pos = is.tellg ();
            ch = is.peek ();   // ch == EOF if read failed; no need to chk fail
            if (ch == 'i' || ch == 'j')           // pure imaginary
              {
                is.get ();
                im = re;
                re = 0;
              }
            else if (ch == '+' || ch == '-')      // see if it is real+imag[ij]
              {
                // save stream state in case we have to restore it
                pos   = is.tellg ();
                state = is.rdstate ();

                //im = octave_read_value<double> (is);
                im = read_double (is, fmt);
                if (is.fail ())
                  im = 1;

                if (is.peek () == 'i' || is.peek () == 'j')
                  is.get ();
                else
                  {
                    im = 0;           // no valid imaginary part.  Restore state
                    is.clear (state); // eof shouldn't cause fail.
                    is.seekg (pos);
                  }
              }
            else if (is.eof ())       // we've read enough to be a "valid" read
              is.clear (state);       // failed peek shouldn't cause fail
          }
      }
    if (as_empty)
      val = empty_value.scalar_value ();
    else
      val = Complex (re, im);
  }

  // Return in VAL the run of characters from IS NOT contained in PATTERN.

  int
  textscan::scan_caret (delimited_stream& is, const std::string& pattern,
                        std::string& val) const
  {
    int c1 = std::istream::traits_type::eof ();
    std::ostringstream obuf;              // Is this optimized for growing?

    while (is && ((c1 = (is && ! is.eof ())
                   ? is.get_undelim ()
                   : std::istream::traits_type::eof ())
                  != std::istream::traits_type::eof ())
           && pattern.find (c1) == std::string::npos)
      obuf << static_cast<char> (c1);

    val = obuf.str ();

    if (c1 != std::istream::traits_type::eof ())
      is.putback (c1);

    return c1;
  }

  // Read until one of the strings in DELIMITERS is found.  For
  // efficiency, ENDS is a list of the last character of each delimiter.

  std::string
  textscan::read_until (delimited_stream& is, const Cell& delimiters,
                        const std::string& ends) const
  {
    std::string retval ("");
    bool done = false;
    do
      {
        // find sequence ending with an ending char
        std::string next;
        scan_caret (is, ends.c_str (), next);
        retval = retval + next;   // FIXME: could use repeated doubling of size

        int last = (! is.eof ()
                    ? is.get_undelim () : std::istream::traits_type::eof ());

        if (last != std::istream::traits_type::eof ())
          {
            retval = retval + static_cast<char> (last);
            for (int i = 0; i < delimiters.numel (); i++)
              {
                std::string delim = delimiters(i).string_value ();
                size_t start = (retval.length () > delim.length ()
                                ? retval.length () - delim.length ()
                                : 0);
                std::string may_match = retval.substr (start);
                if (may_match == delim)
                  {
                    done = true;
                    retval = retval.substr (0, start);
                    break;
                  }
              }
          }
      }
    while (! done && is && ! is.eof ());

    return retval;
  }

  // Read stream until either fmt.width chars have been read, or
  // options.delimiter has been found.  Does *not* rely on fmt being 's'.
  // Used by formats like %6f to limit to 6.

  void
  textscan::scan_string (delimited_stream& is, const textscan_format_elt& fmt,
                         std::string& val) const
  {
    if (delim_list.is_empty ())
      {
        unsigned int i = 0;
        unsigned int width = fmt.width;

        for (i = 0; i < width; i++)
          {
            if (i+1 > val.length ())
              val = val + val + ' ';      // grow even if empty
            int ch = is.get ();
            if (is_delim (ch) || ch == std::istream::traits_type::eof ())
              {
                is.putback (ch);
                break;
              }
            else
              val[i] = ch;
          }
        val = val.substr (0, i);          // trim pre-allocation
      }
    else  // Cell array of multi-character delimiters
      {
        std::string ends ("");
        for (int i = 0; i < delim_list.numel (); i++)
          {
            std::string tmp = delim_list(i).string_value ();
            ends += tmp.substr (tmp.length () - 1);
          }
        val = textscan::read_until (is, delim_list, ends);
      }
  }

  // Return in VAL the run of characters from IS contained in PATTERN.

  int
  textscan::scan_bracket (delimited_stream& is, const std::string& pattern,
                          std::string& val) const
  {
    int c1 = std::istream::traits_type::eof ();
    std::ostringstream obuf;              // Is this optimized for growing?

    while (is && pattern.find (c1 = is.get_undelim ()) != std::string::npos)
      obuf << static_cast<char> (c1);

    val = obuf.str ();
    if (c1 != std::istream::traits_type::eof ())
      is.putback (c1);
    return c1;
  }

  // Return in VAL a string, either delimited by whitespace/delimiters, or
  // enclosed in a pair of double quotes ("...").  Enclosing quotes are
  // removed.  A consecutive pair "" is inserted into VAL as a single ".

  void
  textscan::scan_qstring (delimited_stream& is, const textscan_format_elt& fmt,
                          std::string& val)
  {
    skip_whitespace (is);

    if (is.peek () != '\"')
      scan_string (is, fmt, val);
    else
      {
        is.get ();
        scan_caret (is, "\"", val);       // read everything until "
        is.get ();                        // swallow "

        while (is && is.peek () == '\"')  // if double ", insert one in stream,
          {                               // and keep looking for single "
            is.get ();
            std::string val1;
            scan_caret (is, "\"", val1);
            val = val + "\"" + val1;
            is.get_undelim ();
          }
      }
  }

  // Read from IS into VAL a string of the next fmt.width characters,
  // including any whitespace or delimiters.

  void
  textscan::scan_cstring (delimited_stream& is, const textscan_format_elt& fmt,
                          std::string& val) const
  {
    val.resize (fmt.width);

    for (unsigned int i = 0; is && i < fmt.width; i++)
      {
        int ch = is.get_undelim ();
        if (ch != std::istream::traits_type::eof ())
          val[i] = ch;
        else
          {
            val.resize (i);
            break;
          }
      }
  }

  //  Read a single '%...' conversion and place it in position ROW of OV.

  void
  textscan::scan_one (delimited_stream& is, const textscan_format_elt& fmt,
                      octave_value& ov, Array<octave_idx_type> row)
  {
    skip_whitespace (is);

    is.clear ();

    octave_value val;
    if (fmt.numeric)
      {
        if (fmt.type == 'f' || fmt.type == 'n')
          {
            Complex v;
            skip_whitespace (is);
            scan_complex (is, fmt, v);

            if (! fmt.discard && ! is.fail ())
              {
                if (fmt.bitwidth == 64)
                  {
                    if (ov.is_real_type () && v.imag () == 0)
                      ov.internal_rep ()->fast_elem_insert (row(0), v.real ());
                    else
                      {
                        if (ov.is_real_type ())  // cat does type conversion
                          ov = do_cat_op (ov, octave_value (v), row);
                        else
                          ov.internal_rep ()->fast_elem_insert (row(0), v);
                      }
                  }
                else
                  {
                    if (ov.is_real_type () && v.imag () == 0)
                      ov.internal_rep ()->fast_elem_insert (row(0),
                                                            float (v.real ()));
                    else
                      {
                        if (ov.is_real_type ())  // cat does type conversion
                          ov = do_cat_op (ov, octave_value (v), row);
                        else
                          ov.internal_rep ()->fast_elem_insert (row(0),
                                                                FloatComplex (v));
                      }
                  }
              }
          }
        else
          {
            double v;    // Matlab docs say 1e30 etc should be valid for %d and
                         // 1000 as a %d8 should be 127, so read as double.
                         // Some loss of precision for d64 and u64.
            skip_whitespace (is);
            v = read_double (is, fmt);
            if (! fmt.discard && ! is.fail ())
              switch (fmt.bitwidth)
                {
                case 64:
                  switch (fmt.type)
                    {
                    case 'd':
                      {
                        octave_int64 vv = v;
                        ov.internal_rep ()->fast_elem_insert (row(0), vv);
                      }
                      break;

                    case 'u':
                      {
                        octave_uint64 vv = v;
                        ov.internal_rep ()->fast_elem_insert (row(0), vv);
                      }
                      break;
                    }
                  break;

                case 32:
                  switch (fmt.type)
                    {
                    case 'd':
                      {
                        octave_int32 vv = v;
                        ov.internal_rep ()->fast_elem_insert (row(0), vv);
                      }
                      break;

                    case 'u':
                      {
                        octave_uint32 vv = v;
                        ov.internal_rep ()->fast_elem_insert (row(0), vv);
                      }
                      break;
                    }
                  break;

                case 16:
                  if (fmt.type == 'd')
                    {
                      octave_int16 vv = v;
                      ov.internal_rep ()->fast_elem_insert (row(0), vv);
                    }
                  else
                    {
                      octave_uint16 vv = v;
                      ov.internal_rep ()->fast_elem_insert (row(0), vv);
                    }
                  break;

                case 8:
                  if (fmt.type == 'd')
                    {
                      octave_int8 vv = v;
                      ov.internal_rep ()->fast_elem_insert (row(0), vv);
                    }
                  else
                    {
                      octave_uint8 vv = v;
                      ov.internal_rep ()->fast_elem_insert (row(0), vv);
                    }
                  break;
                }
          }

        if (is.fail () & ! fmt.discard)
          ov = do_cat_op (ov, empty_value, row);
      }
    else
      {
        std::string vv ("        ");      // initial buffer.  Grows as needed
        switch (fmt.type)
          {
          case 's':
            scan_string (is, fmt, vv);
            break;

          case 'q':
            scan_qstring (is, fmt, vv);
            break;

          case 'c':
            scan_cstring (is, fmt, vv);
            break;

          case '[':
            scan_bracket (is, fmt.char_class.c_str (), vv);
            break;

          case '^':
            scan_caret   (is, fmt.char_class.c_str (), vv);
            break;
          }

        if (! fmt.discard)
          ov.internal_rep ()->fast_elem_insert (row (0),
                                                Cell (octave_value (vv)));

        // FIXME: why does failbit get set at EOF, instead of eofbit?
        if (! vv.empty ())
          is.clear (is.rdstate () & ~std::ios_base::failbit);
      }

    is.field_done ();
  }

  // Read data corresponding to the entire format string once, placing the
  // values in row ROW of retval.

  int
  textscan::read_format_once (delimited_stream& is,
                              textscan_format_list& fmt_list,
                              std::list<octave_value>& retval,
                              Array<octave_idx_type> row, int& done_after)
  {
    const textscan_format_elt *elem = fmt_list.first ();
    std::list<octave_value>::iterator out = retval.begin ();
    bool no_conversions = true;
    bool done = false;
    bool conversion_failed = false;       // Record for ReturnOnError
    bool nothing_worked = true;

    octave_quit ();

    for (size_t i = 0; i < fmt_list.numel (); i++)
      {
        bool this_conversion_failed = false;

        // Clear fail of previous numeric conversions.
        is.clear ();

        switch (elem->type)
          {
          case 'C':
          case 'D':
            warning ("%s: conversion %c not yet implemented",
                     who.c_str (), elem->type);
            break;

          case 'u':
          case 'd':
          case 'f':
          case 'n':
          case 's':
          case '[':
          case '^':
          case 'q':
          case 'c':
            scan_one (is, *elem, *out, row);
            break;

          case textscan_format_elt::literal_conversion :
            match_literal (is, *elem);
            break;

          default:
            error ("Unknown format element '%c'", elem->type);
          }

        if (! is.fail ())
          {
            if (! elem->discard)
              no_conversions = false;
          }
        else
          {
            is.clear (is.rdstate () & ~std::ios::failbit);

            if (! is.eof () && ~is_delim (is.peek ()))
              this_conversion_failed = true;
          }

        if (! elem->discard)
          out++;

        elem = fmt_list.next ();
        char *pos = is.tellg ();

        // FIXME: these conversions "ignore delimiters".  Should they include
        // delimiters at the start of the conversion, or can those be skipped?
        if (elem->type != textscan_format_elt::literal_conversion
            // && elem->type != '[' && elem->type != '^' && elem->type != 'c'
           )
          skip_delim (is);

        if (is.eof ())
          {
            if (! done)
              done_after = i+1;

            // note EOF, but process others to get empty_val.
            done = true;
          }

        if (this_conversion_failed)
          {
            if (is.tellg () == pos && ! conversion_failed)
              {
                // done_after = first failure
                done_after = i; // note fail, but parse others to get empty_val
                conversion_failed = true;
              }
            else
              this_conversion_failed = false;
          }
        else if (! done && ! conversion_failed)
          nothing_worked = false;
      }

    if (done)
      is.setstate (std::ios::eofbit);

    return no_conversions
           + (is.eof () ? 2 : 0)
           + (conversion_failed ? 4 : 0)
           + (nothing_worked ? 8 : 0);

  }

  void
  textscan::parse_options (const octave_value_list& args,
                           textscan_format_list& fmt_list)
  {
    int last = args.length ();
    int n = last;

    if (n & 1)
      error ("%s: %d parameters given, but only %d values",
             who.c_str (), n-n/2, n/2);

    delim_len = 1;
    bool have_delims = false;
    for (int i = 0; i < last; i += 2)
      {
        std::string param = args(i).xstring_value ("%s: Invalid parameter type <%s> for parameter %d",
                                                   who.c_str (),
                                                   args(i).type_name ().c_str (),
                                                   i/2 + 1);
        std::transform (param.begin (), param.end (), param.begin (), ::tolower);

        if (param == "delimiter")
          {
            bool invalid = true;
            if (args(i+1).is_string ())
              {
                invalid = false;
                have_delims = true;
                delims = args(i+1).string_value ();
                if (args(i+1).is_sq_string ())
                  delims = do_string_escapes (delims);
              }
            else if (args(i+1).is_cell ())
              {
                invalid = false;
                delim_list = args(i+1).cell_value ();
                delim_table = " "; // non-empty, to flag non-default delim

                // Check that all elements are strings, and find max length
                for (int j = 0; j < delim_list.numel (); j++)
                  {
                    if (! delim_list(j).is_string ())
                      invalid = true;
                    else
                      {
                        if (delim_list(j).is_sq_string ())
                          delim_list(j) = do_string_escapes (delim_list(j)
                                                             .string_value ());
                        octave_idx_type len = delim_list(j).string_value ()
                          .length ();
                        delim_len = std::max (static_cast<int> (len), delim_len);
                      }
                  }
              }
            if (invalid)
              error ("%s: Delimiters must be either a string or cell array of strings",
                     who.c_str ());
          }
        else if (param == "commentstyle")
          {
            if (args(i+1).is_string ())
              {
                // check here for names like "C++", "C", "shell", ...?
                comment_style = Cell (args(i+1));
              }
            else if (args(i+1).is_cell ())
              {
                comment_style = args(i+1).cell_value ();
                int len = comment_style.numel ();
                if ((len >= 1 && ! comment_style (0).is_string ())
                    || (len >= 2 && ! comment_style (1).is_string ())
                    || (len >= 3))
                  error ("%s: CommentStyle must be either a string or cell array of one or two strings",
                         who.c_str ());
              }
            else
              error ("%s: CommentStyle must be either a string or cell array of one or two strings",
                     who.c_str ());

            // How far ahead do we need to look to detect an open comment
            // and which character do we look for?
            if (comment_style.numel () >= 1)
              {
                comment_len  = comment_style (0).string_value ().size ();
                comment_char = comment_style (0).string_value ()[0];
              }
          }
        else if (param == "treatasempty")
          {
            bool invalid = false;
            if (args(i+1).is_string ())
              {
                treat_as_empty = Cell (args(i+1));
                treat_as_empty_len = args(i+1).string_value ().size ();
              }
            else if (args(i+1).is_cell ())
              {
                treat_as_empty = args(i+1).cell_value ();
                for (int j = 0; j < treat_as_empty.numel (); j++)
                  if (! treat_as_empty (j).is_string ())
                    invalid = true;
                  else
                    {
                      int k = treat_as_empty (j).string_value ().size ();
                      if (k > treat_as_empty_len)
                        treat_as_empty_len = k;
                    }
              }
            if (invalid)
              error ("%s: TreatAsEmpty must be either a string or cell array of one or two strings",
                     who.c_str ());

            // FIXME: Ensure none is a prefix of a later one.  Sort by length?
          }
        else if (param == "collectoutput")
          {
            collect_output = args(i+1).xbool_value ("%s: CollectOutput must be logical or numeric", who.c_str ());
          }
        else if (param == "emptyvalue")
          {
            empty_value = args(i+1).xscalar_value ("%s: EmptyValue must be numeric", who.c_str ());
          }
        else if (param == "headerlines")
          {
            header_lines = args(i+1).xscalar_value ("%s: HeaderLines must be numeric", who.c_str ());
          }
        else if (param == "bufsize")
          {
            buffer_size = args(i+1).xscalar_value ("%s: BufSize must be numeric", who.c_str ());
          }
        else if (param == "multipledelimsasone")
          {
            multiple_delims_as_one = args(i+1).xbool_value ("%s: MultipleDelimsAsOne must be logical or numeric", who.c_str ());
          }
        else if (param == "returnonerror")
          {
            return_on_error = args(i+1).xbool_value ("%s: ReturnOnError must be logical or numeric", who.c_str ());
          }
        else if (param == "whitespace")
          {
            whitespace = args(i+1).xstring_value ("%s: Whitespace must be a character string", who.c_str ());
          }
        else if (param == "expchars")
          {
            exp_chars = args(i+1).xstring_value ("%s: ExpChars must be a character string", who.c_str ());
            default_exp = false;
          }
        else if (param == "endofline")
          {
            bool valid = true;
            std::string s = args(i+1).xstring_value ("%s: EndOfLine must be at most one character or '\\r\\n'", who.c_str ());
            if (args(i+1).is_sq_string ())
              s = do_string_escapes (s);
            int l = s.length ();
            if (l == 0)
              eol1 = eol2 = -2;
            else if (l == 1)
              eol1 = eol2 = s.c_str ()[0];
            else if (l == 2)
              {
                eol1 = s.c_str ()[0];
                eol2 = s.c_str ()[1];
                if (eol1 != '\r' || eol2 != '\n')    // Why limit it?
                  valid = false;
              }
            else
              valid = false;

            if (! valid)
              error ("%s: EndOfLine must be at most one character or '\\r\\n'",
                     who.c_str ());
          }
        else
          error ("%s: unrecognized option '%s'", who.c_str (), param.c_str ());
      }

    whitespace_table = std::string (256, '\0');
    for (unsigned int i = 0; i < whitespace.length (); i++)
      whitespace_table[whitespace[i]] = '1';

    // For Matlab compatibility, add 0x20 to whitespace, unless
    // whitespace is explicitly ignored.
    if (! (whitespace.empty () && fmt_list.has_string))
      whitespace_table[' '] = '1';

    // Create look-up table of delimiters, based on 'delimiter'
    delim_table = std::string (256, '\0');
    if (eol1 >= 0 && eol1 < 256)
      delim_table[eol1] = '1';        // EOL is always a delimiter
    if (eol2 >= 0 && eol2 < 256)
      delim_table[eol2] = '1';        // EOL is always a delimiter
    if (! have_delims)
      for (unsigned int i = 0; i < 256; i++)
        {
          if (isspace (i))
            delim_table[i] = '1';
        }
    else
      for (unsigned int i = 0; i < delims.length (); i++)
        delim_table[delims[i]] = '1';
  }

  // Skip comments, and characters specified by the "Whitespace" option.
  // If EOLstop == true, don't skip end of line.

  int
  textscan::skip_whitespace (delimited_stream& is, bool EOLstop)
  {
    int c1 = std::istream::traits_type::eof ();
    bool found_comment = false;

    do
      {
        found_comment = false;
        int prev = -1;
        while (is && (c1 = is.get_undelim ()) != std::istream::traits_type::eof ()
               && ( ( (c1 == eol1 || c1 == eol2) && ++lines && ! EOLstop)
                    || isspace (c1)))
          {
            if (prev == eol1 && eol1 != eol2 && c1 == eol2)
              lines--;
            prev = c1;
          }

        if (c1 == comment_char)           // see if we match an open comment
          {
            // save stream state in case we have to restore it
            char *pos = is.tellg ();
            std::ios::iostate state = is.rdstate ();

            std::string tmp (comment_len, '\0');
            char *look = is.read (&tmp[0], comment_len-1, pos); // already read first char
            if (is && ! strncmp (comment_style(0).string_value ().substr (1)
                                 .c_str (), look, comment_len-1))
              {
                found_comment = true;

                std::string dummy;
                if (comment_style.numel () == 1)  // skip to end of line
                  {
                    std::string eol (3, '\0');
                    eol[0] = eol1;
                    eol[1] = eol2;

                    scan_caret (is, eol, dummy);
                    c1 = is.get_undelim ();
                    if (c1 == eol1 && eol1 != eol2 && is.peek_undelim () == eol2)
                      is.get_undelim ();
                    lines++;
                  }
                else      // matching pair
                  {
                    std::string end_c = comment_style(1).string_value ();
                    // last char of end-comment sequence
                    std::string last = end_c.substr (end_c.size () - 1);
                    std::string may_match ("");
                    do
                      {
                        // find sequence ending with last char
                        scan_caret (is, last, dummy);
                        is.get_undelim ();        // (read LAST itself)

                        may_match = may_match + dummy + last;
                        if (may_match.length () > end_c.length ())
                          {
                            size_t start = may_match.length () - end_c.length ();
                            may_match = may_match.substr (start);
                          }
                      }
                    while (may_match != end_c && is && ! is.eof ());
                  }
              }
            else  // wasn't really a comment; restore state
              {
                is.clear (state);
                is.seekg (pos);
              }
          }
      }
    while (found_comment);

    if (c1 != std::istream::traits_type::eof ())
      is.putback (c1);
    return c1;
  }

  // See if the next few characters match one of the strings in target.
  // For efficiency, MAX_LEN is the cached longest length of any target.
  // Return -1 if none is found, or the index of the match.

  int
  textscan::lookahead (delimited_stream& is, const Cell& targets, int max_len,
                       bool case_sensitive) const
  {
    // target strings may be different sizes.
    // Read ahead longest, put it all back, then re-read the string
    // that matches.

    char *pos = is.tellg ();

    std::string tmp (max_len, '\0');
    char *look = is.read (&tmp[0], tmp.size (), pos);

    is.clear ();
    is.seekg (pos);              // reset to position before look-ahead
                                 // FIXME: pos may be corrupted by is.read

    int i;
    int (*compare)(const char *, const char *, size_t);
    compare = case_sensitive ? strncmp : strncasecmp;

    for (i = 0; i < targets.numel (); i++)
      {
        std::string s = targets (i).string_value ();
        if (! (*compare) (s.c_str (), look, s.size ()))
          {
            is.read (&tmp[0], s.size (), pos); // read just the right amount
            break;
          }
      }

    if (i == targets.numel ())
      i = -1;

    return i;
  }

  // Skip delimiters -- multiple if MultipleDelimsAsOne specified.
  int
  textscan::skip_delim (delimited_stream& is)
  {
    int c1 = skip_whitespace (is, true);  // 'true': stop once EOL is read
    if (delim_list.numel () == 0)         // single character delimiter
      {
        if (is_delim (c1) || c1 == eol1 || c1 == eol2)
          {
            is.get ();
            if (c1 == eol1 && is.peek_undelim () == eol2)
              is.get_undelim ();          // if \r\n, skip the \n too.

            if (multiple_delims_as_one)
              {
                int prev = -1;
                // skip multiple delims.
                // Increment lines for each end-of-line seen; for \r\n, decrement
                while (is && ((c1 = is.get_undelim ())
                              != std::istream::traits_type::eof ())
                       && (((c1 == eol1 || c1 == eol2) && ++lines)
                           || isspace (c1) || is_delim (c1)))
                  {
                    if (prev == eol1 && eol1 != eol2 && c1 == eol2)
                      lines--;
                    prev = c1;
                  }
                if (c1 != std::istream::traits_type::eof ())
                  is.putback (c1);
              }
          }
      }
    else                                  // multi-character delimiter
      {
        int first_match;

        if (c1 == eol1 || c1 == eol2
            || (-1 != (first_match = lookahead (is, delim_list, delim_len))))
          {
            if (c1 == eol1)
              {
                is.get_undelim ();
                if (is.peek_undelim () == eol2)
                  is.get_undelim ();
              }
            else if (c1 == eol2)
              {
                is.get_undelim ();
              }

            if (multiple_delims_as_one)
              {
                int prev = -1;
                // skip multiple delims.
                // Increment lines for each end-of-line seen; for \r\n, decrement
                while (is && ((c1 = skip_whitespace (is, true))
                              != std::istream::traits_type::eof ())
                       && (((c1 == eol1 || c1 == eol2) && ++lines)
                           || -1 != lookahead (is, delim_list, delim_len)))
                  {
                    if (prev == eol1 && eol1 != eol2 && c1 == eol2)
                      lines--;
                    prev = c1;
                  }
              }
          }
      }

    return c1;
  }

  // Read in as much of the input as coincides with the literal in the
  // format string.  Return "true" if the entire literal is matched, else
  // false (and set failbit).

  bool
  textscan::match_literal (delimited_stream& is, const textscan_format_elt& fmt)
  {
    // "false" -> treat EOL as normal space
    // since a delimiter at the start of a line is a mismatch, not empty field
    skip_whitespace (is, false);

    for (unsigned int i = 0; i < fmt.width; i++)
      {
        int ch = is.get_undelim ();
        if (ch != fmt.text[i])
          {
            if (ch != std::istream::traits_type::eof ())
              is.putback (ch);
            is.setstate (std::ios::failbit);
            return false;
          }
      }
    return true;
  }
}

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)
{
  if (octave::application::interactive () && file_number () == 0)
    ::error ("%s: unable to read from stdin while running interactively",
             who.c_str ());

  std::string retval;

  err = false;

  std::istream *isp = input_stream ();

  if (! isp)
    {
      err = true;
      invalid_operation (who, "reading");
    }
  else
    {
      std::istream& is = *isp;

      std::ostringstream buf;

      int c = 0;
      int char_count = 0;

      if (max_len != 0)
        {
          while (is && (c = is.get ()) != std::istream::traits_type::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 != std::istream::traits_type::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");
        }
    }

  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);
}

off_t
octave_base_stream::skipl (off_t num, bool& err, const std::string& who)
{
  if (octave::application::interactive () && file_number () == 0)
    ::error ("%s: unable to read from stdin while running interactively",
             who.c_str ());

  off_t cnt = -1;

  err = false;

  std::istream *isp = input_stream ();

  if (! isp)
    {
      err = true;
      invalid_operation (who, "reading");
    }
  else
    {
      std::istream& is = *isp;

      int c = 0;
      int lastc = -1;
      cnt = 0;

      while (is && (c = is.get ()) != std::istream::traits_type::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;
    }

  return cnt;
}

template <typename T>
std::istream&
octave_scan_1 (std::istream& is, const scanf_format_elt& fmt, T* valptr)
{
  T value = T ();

  switch (fmt.type)
    {
    case 'o':
      is >> std::oct >> value >> std::dec;
      break;

    case 'x':
      is >> std::hex >> value >> std::dec;
      break;

    case 'i':
      {
        int c1 = std::istream::traits_type::eof ();

        while (is && (c1 = is.get ()) != std::istream::traits_type::eof ()
               && isspace (c1))
          ; // skip whitespace

        if (c1 != std::istream::traits_type::eof ())
          {
            if (c1 == '0')
              {
                int c2 = is.peek ();

                if (c2 == 'x' || c2 == 'X')
                  {
                    is.ignore ();
                    if (std::isxdigit (is.peek ()))
                      is >> std::hex >> value >> std::dec;
                    else
                      value = 0;
                  }
                else
                  {
                    if (c2 == '0' || c2 == '1' || c2 == '2'
                        || c2 == '3' || c2 == '4' || c2 == '5'
                        || c2 == '6' || c2 == '7')
                      is >> std::oct >> value >> std::dec;
                    else if (c2 == '8' || c2 == '9')
                      {
                        // FIXME: Would like to set error state on octave
                        // stream.  See bug #46493.  But only std::istream is
                        // input to fcn.
                        // error ("internal failure to match octal format");
                        value = 0;
                      }
                    else
                      value = 0;
                  }
              }
            else
              {
                is.putback (c1);

                is >> value;
              }
          }
      }
      break;

    default:
      is >> value;
      break;
    }

  // If conversion produces an integer that overflows, failbit is set but
  // value is non-zero.  We want to treat this case as success, so clear
  // failbit from the stream state to keep going.
  // FIXME: Maybe set error state on octave stream as above? Matlab does
  // *not* indicate an error message on overflow.
  if ((is.rdstate () & std::ios::failbit) && value != T ())
    is.clear (is.rdstate () & ~std::ios::failbit);

  // Only copy the converted value if the stream is in a state where we
  // want to continue reading.
  if (! (is.rdstate () & std::ios::failbit))
    *valptr = value;

  return is;
}

template <typename 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& is, const scanf_format_elt& fmt, double* valptr)
{
  double& ref = *valptr;

  switch (fmt.type)
    {
    case 'e':
    case 'f':
    case 'g':
      {
        int c1 = std::istream::traits_type::eof ();

        while (is && (c1 = is.get ()) != std::istream::traits_type::eof ()
               && isspace (c1))
          ; // skip whitespace

        if (c1 != std::istream::traits_type::eof ())
          {
            is.putback (c1);

            ref = octave_read_value<double> (is);
          }
      }
      break;

    default:
      panic_impossible ();
      break;
    }

  return is;
}

template <typename 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)
    return;

  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&, double*,
               Matrix&, double*, octave_idx_type&, octave_idx_type&,
               octave_idx_type, octave_idx_type, bool);

#define DO_WHITESPACE_CONVERSION()                                      \
  do                                                                    \
    {                                                                   \
      int c = std::istream::traits_type::eof ();                        \
                                                                        \
      while (is && (c = is.get ()) != std::istream::traits_type::eof () \
             && isspace (c))                                            \
        { /* skip whitespace */ }                                       \
                                                                        \
      if (c != std::istream::traits_type::eof ())                       \
        is.putback (c);                                                 \
    }                                                                   \
  while (0)

#define DO_LITERAL_CONVERSION()                                         \
  do                                                                    \
    {                                                                   \
     int c = std::istream::traits_type::eof ();                         \
                                                                        \
     int n = strlen (fmt);                                              \
     int i = 0;                                                         \
                                                                        \
     while (i < n && is && (c = is.get ()) != std::istream::traits_type::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 != std::istream::traits_type::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 = std::istream::traits_type::eof ();                            \
  int n = 0;                                                            \
                                                                        \
  while (is && n < width                                                \
         && (c = is.get ()) != std::istream::traits_type::eof ())       \
    tmp[n++] = static_cast<char> (c);                                   \
                                                                        \
  if (n > 0 && c == std::istream::traits_type::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 = std::istream::traits_type::eof ();                    \
                                                                        \
          int n = 0;                                                    \
                                                                        \
          while (is && (c = is.get ()) != std::istream::traits_type::eof ()) \
            {                                                           \
              if (! isspace (c))                                        \
                {                                                       \
                  tmp[n++] = static_cast<char> (c);                     \
                  break;                                                \
                }                                                       \
            }                                                           \
                                                                        \
          while (is && n < width                                        \
                 && (c = is.get ()) != std::istream::traits_type::eof ()) \
            {                                                           \
              if (isspace (c))                                          \
                {                                                       \
                  is.putback (c);                                       \
                  break;                                                \
                }                                                       \
              else                                                      \
                tmp[n++] = static_cast<char> (c);                       \
            }                                                           \
                                                                        \
          if (n > 0 && c == std::istream::traits_type::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 = std::numeric_limits<int>::max ();                        \
                                                                        \
     std::ostringstream buf;                                            \
                                                                        \
     std::string char_class = elt->char_class;                          \
                                                                        \
     int c = std::istream::traits_type::eof ();                         \
                                                                        \
     if (elt->type == '[')                                              \
       {                                                                \
        int chars_read = 0;                                             \
        while (is && chars_read++ < width                               \
               && (c = is.get ()) != std::istream::traits_type::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 ()) != std::istream::traits_type::eof () \
                && char_class.find (c) == std::string::npos)            \
           buf << static_cast<char> (c);                                \
       }                                                                \
                                                                        \
     if (width == std::numeric_limits<int>::max ()                      \
         && c != std::istream::traits_type::eof ())                     \
       is.putback (c);                                                  \
                                                                        \
     tmp = buf.str ();                                                  \
                                                                        \
     if (tmp.empty ())                                                  \
       is.setstate (std::ios::failbit);                                 \
     else if (c == std::istream::traits_type::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)
{
  if (octave::application::interactive () && file_number () == 0)
    ::error ("%s: unable to read from stdin while running interactively",
             who.c_str ());

  octave_value retval = Matrix ();

  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::null
                  || (! (elt->type == scanf_format_elt::whitespace_conversion
                         || elt->type == scanf_format_elt::literal_conversion
                         || elt->type == '%')
                      && max_conv > 0 && conversion_count == max_conv))
                {
                  // We are done, either because we have reached the end of the
                  // format string and are not cycling through the format again
                  // or because we've converted all the values that have been
                  // requested and the next format element is a conversion.
                  // Determine final array size and exit.
                  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':
                        {
                          int16_t tmp;
                          do_scanf_conv (is, *elt, &tmp, mval, data,
                                         data_index, conversion_count,
                                         nr, max_size, discard);
                        }
                        break;

                      case 'l':
                        {
                          int64_t tmp;
                          do_scanf_conv (is, *elt, &tmp, mval, data,
                                         data_index, conversion_count,
                                         nr, max_size, discard);
                        }
                        break;

                      default:
                        {
                          int32_t 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':
                        {
                          uint16_t tmp;
                          do_scanf_conv (is, *elt, &tmp, mval, data,
                                         data_index, conversion_count,
                                         nr, max_size, discard);
                        }
                        break;

                      case 'l':
                        {
                          uint64_t tmp;
                          do_scanf_conv (is, *elt, &tmp, mval, data,
                                         data_index, conversion_count,
                                         nr, max_size, discard);
                        }
                        break;

                      default:
                        {
                          uint32_t 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 (octave::application::interactive ()
                      && ! octave::application::forced_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
            {
              // Cycle through the format list more than once if we have some
              // conversions to make and we haven't reached the limit on the
              // number of values to convert (possibly because there is no
              // specified limit).
              elt = fmt_list.next (nconv > 0
                                   && (max_conv == 0
                                       || conversion_count < max_conv));
            }
        }
    }

  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)
    invalid_operation (who, "reading");
  else
    {
      scanf_format_list fmt_list (fmt);

      if (fmt_list.num_conversions () == -1)
        ::error ("%s: invalid format specified", who.c_str ());

      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);

      retval = do_scanf (fmt_list, nr, nc, one_elt_size_spec,
                         conversion_count, who);
    }

  return retval;
}

bool
octave_base_stream::do_oscanf (const scanf_format_elt *elt,
                               octave_value& retval, const std::string& who)
{
  std::istream *isp = input_stream ();

  if (! isp)
    return false;

  bool quit = false;

  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 (octave::application::interactive ()
          && ! octave::application::forced_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)
    invalid_operation (who, "reading");
  else
    {
      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 ());

      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);
            }
        }
    }

  return retval;
}

octave_value
octave_base_stream::do_textscan (const std::string& fmt,
                                 octave_idx_type ntimes,
                                 const octave_value_list& options,
                                 const std::string& who,
                                 octave_idx_type& read_count)
{
  if (octave::application::interactive () && file_number () == 0)
    ::error ("%s: unable to read from stdin while running interactively",
             who.c_str ());

  octave_value retval = Cell (dim_vector (1, 1), Matrix (0, 1));

  std::istream *isp = input_stream ();

  if (! isp)
    invalid_operation (who, "reading");
  else
    {
      octave::textscan scanner (who);

      retval = scanner.scan (*isp, fmt, ntimes, options, read_count);
    }

  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)
    invalid_operation ("fflush", "writing");
  else
    {
      os->flush ();

      if (os->good ())
        retval = 0;
    }

  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), have_data (false),
      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 ())
          err_wrong_type_arg (who, val);
      }
  }

  ~printf_value_cache (void) { }

  // Get the current value as a double and advance the internal pointer.
  octave_value get_next_value (char type = 0);

  // Get the current value as an int and advance the internal pointer.
  int int_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;
  bool have_data;
  octave_value 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&);
};

octave_value
printf_value_cache::get_next_value (char type)
{
  octave_value retval;

  if (exhausted ())
    curr_state = conversion_error;

  while (! exhausted ())
    {
      if (! have_data)
        {
          curr_val = values (val_idx);

          elt_idx = 0;
          n_elts = curr_val.numel ();
          have_data = true;
        }

      if (elt_idx < n_elts)
        {
          if (type == 's')
            {
              if (curr_val.is_string ())
                {
                  dim_vector dv (1, curr_val.numel ());
                  octave_value tmp = curr_val.reshape (dv);

                  std::string sval = tmp.string_value ();

                  retval = sval.substr (elt_idx);

                  // We've consumed the rest of the value.
                  elt_idx = n_elts;
                }
              else
                {
                  // Convert to character string while values are
                  // integers in the range [0 : char max]
                  const NDArray val = curr_val.array_value ();

                  octave_idx_type idx = elt_idx;

                  for (; idx < n_elts; idx++)
                    {
                      double dval = val(idx);

                      if (octave::math::x_nint (dval) != dval || dval < 0 || dval > 255)
                        break;
                    }

                  octave_idx_type n = idx - elt_idx;

                  if (n > 0)
                    {
                      std::string sval (n, '\0');

                      for (octave_idx_type i = 0; i < n; i++)
                        sval[i] = val(elt_idx++);

                      retval = sval;
                    }
                  else
                    retval = curr_val.fast_elem_extract (elt_idx++);
                }
            }
          else
            {
              retval = curr_val.fast_elem_extract (elt_idx++);

              if (type == 'c' && ! retval.is_string ())
                {
                  double dval = retval.double_value ();

                  if (octave::math::x_nint (dval) == dval && dval >= 0 && dval < 256)
                    retval = static_cast<char> (dval);
                }
            }

          if (elt_idx >= n_elts)
            {
              elt_idx = 0;
              val_idx++;
              have_data = false;
            }

          break;
        }
      else
        {
          val_idx++;
          have_data = false;

          if (n_elts == 0)
            {
              if (elt_idx == 0 && (type == 's' || type == 'c'))
                {
                  retval = "";
                  break;
                }

              if (exhausted ())
                curr_state = conversion_error;
            }
        }
    }

  return retval;
}

int
printf_value_cache::int_value (void)
{
  int retval = 0;

  octave_value val = get_next_value ();

  double dval = val.double_value (true);

  if (octave::math::x_nint (dval) == dval)
    retval = octave::math::nint (dval);
  else
    curr_state = conversion_error;

  return retval;
}

// Ugh again and again.

template <typename 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;
}

static size_t
do_printf_string (std::ostream& os, const printf_format_elt *elt,
                  int nsa, int sa_1, int sa_2, const std::string& arg,
                  const std::string& who)
{
  if (nsa > 2)
    ::error ("%s: internal error handling format", who.c_str ());

  std::string flags = elt->flags;

  bool left = flags.find ('-') != std::string::npos;

  size_t len = arg.length ();

  size_t fw = nsa > 0 ? sa_1 : (elt->fw == -1 ? len : elt->fw);
  size_t prec = nsa > 1 ? sa_2 : (elt->prec == -1 ? len : elt->prec);

  os << std::setw (fw)
     << (left ? std::left : std::right)
     << (prec < len ? arg.substr (0, prec) : arg);

  return len > fw ? len : fw;
}

static bool
is_nan_or_inf (const octave_value& val)
{
  octave_value ov_isnan = val.isnan ();
  octave_value ov_isinf = val.isinf ();

  return (ov_isnan.is_true () || ov_isinf.is_true ());
}

static bool
ok_for_signed_int_conv (const octave_value& val)
{
  uint64_t limit = std::numeric_limits<int64_t>::max ();

  if (val.is_string ())
    return true;
  else if (val.is_integer_type ())
    {
      if (val.is_uint64_type ())
        {
          octave_uint64 ival = val.uint64_scalar_value ();

          if (ival.value () <= limit)
            return true;
        }
      else
        return true;
    }
  else
    {
      double dval = val.double_value (true);

      if (dval == octave::math::round (dval) && dval <= limit)
        return true;
    }

  return false;
}

static bool
ok_for_unsigned_int_conv (const octave_value& val)
{
  if (val.is_string ())
    return true;
  else if (val.is_integer_type ())
    {
      // Easier than dispatching here...

      octave_value ov_is_ge_zero
        = do_binary_op (octave_value::op_ge, val, octave_value (0.0));

      return ov_is_ge_zero.is_true ();
    }
  else
    {
      double dval = val.double_value (true);

      uint64_t limit = std::numeric_limits<uint64_t>::max ();

      if (dval == octave::math::round (dval) && dval >= 0 && dval <= limit)
        return true;
    }

  return false;
}

static std::string
switch_to_g_format (const printf_format_elt *elt)
{
  std::string tfmt = elt->text;

  tfmt.replace (tfmt.rfind (elt->type), 1, "g");

  return tfmt;
}

int
octave_base_stream::do_numeric_printf_conv (std::ostream& os,
                                            const printf_format_elt *elt,
                                            int nsa, int sa_1, int sa_2,
                                            const octave_value& val,
                                            const std::string& who)
{
  int retval = 0;

  const char *fmt = elt->text;

  if (is_nan_or_inf (val))
    {
      double dval = val.double_value ();

      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 == -2)
            nsa--;
        }

      const char *tval;
      if (lo_ieee_isinf (dval))
        {
          if (elt->flags.find ('+') != std::string::npos)
            tval = (dval < 0 ? "-Inf" : "+Inf");
          else
            tval = (dval < 0 ? "-Inf" : "Inf");
        }
      else
        {
          if (elt->flags.find ('+') != std::string::npos)
            tval = (lo_ieee_is_NA (dval) ? "+NA" : "+NaN");
          else
            tval = (lo_ieee_is_NA (dval) ? "NA" : "NaN");
        }

      retval += do_printf_conv (os, tfmt.c_str (), nsa, sa_1, sa_2, tval, who);
    }
  else
    {
      static std::string llmod
        = sizeof (long) == sizeof (int64_t) ? "l" : "ll";

      char type = elt->type;

      switch (type)
        {
        case 'd': case 'i': case 'c':
          if (ok_for_signed_int_conv (val))
            {
              octave_int64 tval = val.int64_scalar_value ();

              // Insert "long" modifier.
              std::string tfmt = fmt;
              tfmt.replace (tfmt.rfind (type), 1, llmod + type);

              retval += do_printf_conv (os, tfmt.c_str (), nsa, sa_1, sa_2,
                                        tval.value (), who);
            }
          else
            {
              std::string tfmt = switch_to_g_format (elt);

              double dval = val.double_value (true);

              retval += do_printf_conv (os, tfmt.c_str (), nsa,
                                        sa_1, sa_2, dval, who);
            }
          break;

        case 'o': case 'x': case 'X': case 'u':
          if (ok_for_unsigned_int_conv (val))
            {
              octave_uint64 tval = val.uint64_scalar_value ();

              // Insert "long" modifier.
              std::string tfmt = fmt;
              tfmt.replace (tfmt.rfind (type), 1, llmod + type);

              retval += do_printf_conv (os, tfmt.c_str (), nsa, sa_1, sa_2,
                                        tval.value (), who);
            }
          else
            {
              std::string tfmt = switch_to_g_format (elt);

              double dval = val.double_value (true);

              retval += do_printf_conv (os, tfmt.c_str (), nsa,
                                        sa_1, sa_2, dval, who);
            }
          break;

        case 'f': case 'e': case 'E':
        case 'g': case 'G':
          {
            double dval = val.double_value (true);

            retval += do_printf_conv (os, fmt, nsa, sa_1, sa_2, dval, who);
          }
          break;

        default:
          // Note: error is member fcn from octave_base_stream, not ::error.
          // This error does not halt execution so "return ..." must exist.
          error ("%s: invalid format specifier", who.c_str ());
          return -1;
          break;
        }
    }

  return retval;
}

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)
    invalid_operation (who, "writing");
  else
    {
      std::ostream& os = *osp;

      const printf_format_elt *elt = fmt_list.first ();

      printf_value_cache val_cache (args, who);

      for (;;)
        {
          octave_quit ();

          if (! elt)
            ::error ("%s: internal error handling format", who.c_str ());

          // NSA is the number of 'star' args to convert.
          int nsa = (elt->fw == -2) + (elt->prec == -2);

          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;
                    }
                }
            }

          if (elt->type == '%')
            {
              os << "%";
              retval++;
            }
          else if (elt->args == 0 && elt->text)
            {
              os << elt->text;
              retval += strlen (elt->text);
            }
          else if (elt->type == 's' || elt->type == 'c')
            {
              octave_value val = val_cache.get_next_value (elt->type);

              if (val_cache)
                {
                  if (val.is_string ())
                    {
                      std::string sval = val.string_value ();

                      retval += do_printf_string (os, elt, nsa, sa_1,
                                                  sa_2, sval, who);
                    }
                  else
                    retval += do_numeric_printf_conv (os, elt, nsa, sa_1,
                                                      sa_2, val, who);
                }
              else
                break;
            }
          else
            {
              octave_value val = val_cache.get_next_value ();

              if (val_cache)
                retval += do_numeric_printf_conv (os, elt, nsa, sa_1,
                                                  sa_2, val, who);
              else
                break;
            }

          if (! os)
            {
              error ("%s: write error", who.c_str ());
              break;
            }

          elt = fmt_list.next (nconv > 0 && ! val_cache.exhausted ());

          if (! elt || (val_cache.exhausted () && elt->args > 0))
            break;
        }
    }

  return retval;
}

int
octave_base_stream::printf (const std::string& fmt,
                            const octave_value_list& args,
                            const std::string& who)
{
  printf_format_list fmt_list (fmt);

  if (fmt_list.num_conversions () == -1)
    ::error ("%s: invalid format specified", who.c_str ());

  return do_printf (fmt_list, args, who);
}

int
octave_base_stream::puts (const std::string& s, const std::string& who)
{
  int retval = -1;

  std::ostream *osp = output_stream ();

  if (! osp)
    invalid_operation (who, "writing");
  else
    {
      std::ostream& os = *osp;

      os << s;

      if (! os)
        error ("%s: write error", who.c_str ());
      else
        {
          // 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 ());
        }
    }

  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: This calls the member fcn error, not ::error from error.h.
  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)
{
  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 ());
        }
    }

  return getl (max_len, err, who);
}

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)
{
  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 ());
        }
    }

  return gets (max_len, err, who);
}

off_t
octave_stream::skipl (off_t count, bool& err, const std::string& who)
{
  off_t retval = -1;

  if (stream_ok ())
    retval = rep->skipl (count, err, who);

  return retval;
}

off_t
octave_stream::skipl (const octave_value& tc_count, bool& err,
                      const std::string& who)
{
  err = false;

  int conv_err = 0;

  int count = 1;

  if (tc_count.is_defined ())
    {
      if (tc_count.is_scalar_type ()
          && octave::math::isinf (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 ());
            }
        }
    }

  return skipl (count, err, who);
}

int
octave_stream::seek (off_t offset, int origin)
{
  int status = -1;

  if (stream_ok ())
    {
      clearerr ();

      // Find current position so we can return to it if needed.
      off_t 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)
        {
          off_t 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?
              off_t 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;

  // FIXME: should we have octave_value methods that handle off_t explicitly?
  octave_int64 val = tc_offset.xint64_scalar_value ("fseek: invalid value for offset");
  off_t xoffset = val.value ();

  int conv_err = 0;

  int origin = SEEK_SET;

  if (tc_origin.is_string ())
    {
      std::string xorigin = tc_origin.string_value ("fseek: invalid value for origin");

      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)
    ::error ("fseek: invalid value for origin");

  retval = seek (xoffset, origin);

  if (retval != 0)
    // Note: error is member fcn from octave_stream, not ::error.
    error ("fseek: failed to seek to requested position");

  return retval;
}

off_t
octave_stream::tell (void)
{
  off_t 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 ();
}

// FIXME: maybe these should be defined in lo-ieee.h?

template <typename T>
static inline bool
is_old_NA (T)
{
  return false;
}

template <>
inline bool
is_old_NA<double> (double val)
{
  return __lo_ieee_is_old_NA (val);
}

template <typename T>
static inline T
replace_old_NA (T val)
{
  return val;
}

template <>
inline double
replace_old_NA<double> (double val)
{
  return __lo_ieee_replace_old_NA (val);
}

template <typename SRC_T, typename DST_T>
static octave_value
convert_and_copy (std::list<void *>& input_buf_list,
                  octave_idx_type input_buf_elts,
                  octave_idx_type elts_read,
                  octave_idx_type nr, octave_idx_type nc, bool swap,
                  bool do_float_fmt_conv, bool do_NA_conv,
                  octave::mach_info::float_format from_flt_fmt)
{
  typedef typename DST_T::element_type dst_elt_type;

  DST_T conv (dim_vector (nr, nc));

  dst_elt_type *conv_data = conv.fortran_vec ();

  octave_idx_type j = 0;

  for (std::list<void *>::const_iterator it = input_buf_list.begin ();
       it != input_buf_list.end (); it++)
    {
      SRC_T *data = static_cast<SRC_T *> (*it);

      if (swap || do_float_fmt_conv)
        {
          if (do_NA_conv)
            {
              for (octave_idx_type i = 0; i < input_buf_elts && j < elts_read;
                   i++, j++)
                {
                  if (swap)
                    swap_bytes<sizeof (SRC_T)> (&data[i]);
                  else if (do_float_fmt_conv)
                    do_float_format_conversion (&data[i], sizeof (SRC_T),
                                                1, from_flt_fmt,
                                                octave::mach_info::native_float_format ());

                  dst_elt_type tmp (data[i]);

                  if (is_old_NA (tmp))
                    tmp = replace_old_NA (tmp);

                  conv_data[j] = tmp;
                }
            }
          else
            {
              for (octave_idx_type i = 0; i < input_buf_elts && j < elts_read;
                   i++, j++)
                {
                  if (swap)
                    swap_bytes<sizeof (SRC_T)> (&data[i]);
                  else if (do_float_fmt_conv)
                    do_float_format_conversion (&data[i], sizeof (SRC_T),
                                                1, from_flt_fmt,
                                                octave::mach_info::native_float_format ());

                  conv_data[j] = data[i];
                }
            }
        }
      else
        {
          if (do_NA_conv)
            {
              for (octave_idx_type i = 0; i < input_buf_elts && j < elts_read;
                   i++, j++)
                {
                  dst_elt_type tmp (data[i]);

                  if (is_old_NA (tmp))
                    tmp = replace_old_NA (tmp);

                  conv_data[j] = tmp;
                }
            }
          else
            {
              for (octave_idx_type i = 0; i < input_buf_elts && j < elts_read;
                   i++, j++)
                conv_data[j] = data[i];
            }
        }

      delete [] data;
    }

  input_buf_list.clear ();

  for (octave_idx_type i = elts_read; i < nr * nc; i++)
    conv_data[i] = dst_elt_type (0);

  return conv;
}

typedef octave_value (*conv_fptr)
  (std::list<void *>& input_buf_list, octave_idx_type input_buf_elts,
   octave_idx_type elts_read, octave_idx_type nr, octave_idx_type nc,
   bool swap, bool do_float_fmt_conv, bool do_NA_conv,
   octave::mach_info::float_format from_flt_fmt);

#define TABLE_ELT(T, U, V, W)                                           \
  conv_fptr_table[oct_data_conv::T][oct_data_conv::U] = convert_and_copy<V, W>

#define FILL_TABLE_ROW(T, V)                    \
  TABLE_ELT (T, dt_int8, V, int8NDArray);       \
  TABLE_ELT (T, dt_uint8, V, uint8NDArray);     \
  TABLE_ELT (T, dt_int16, V, int16NDArray);     \
  TABLE_ELT (T, dt_uint16, V, uint16NDArray);   \
  TABLE_ELT (T, dt_int32, V, int32NDArray);     \
  TABLE_ELT (T, dt_uint32, V, uint32NDArray);   \
  TABLE_ELT (T, dt_int64, V, int64NDArray);     \
  TABLE_ELT (T, dt_uint64, V, uint64NDArray);   \
  TABLE_ELT (T, dt_single, V, FloatNDArray);    \
  TABLE_ELT (T, dt_double, V, NDArray);         \
  TABLE_ELT (T, dt_char, V, charNDArray);       \
  TABLE_ELT (T, dt_schar, V, charNDArray);      \
  TABLE_ELT (T, dt_uchar, V, charNDArray);      \
  TABLE_ELT (T, dt_logical, V, boolNDArray);

octave_value
octave_stream::finalize_read (std::list<void *>& input_buf_list,
                              octave_idx_type input_buf_elts,
                              octave_idx_type elts_read,
                              octave_idx_type nr, octave_idx_type nc,
                              oct_data_conv::data_type input_type,
                              oct_data_conv::data_type output_type,
                              octave::mach_info::float_format ffmt)
{
  octave_value retval;

  static bool initialized = false;

  // Table function pointers for return types x read types.

  static conv_fptr conv_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++)
          conv_fptr_table[i][j] = 0;

      FILL_TABLE_ROW (dt_int8, int8_t);
      FILL_TABLE_ROW (dt_uint8, uint8_t);
      FILL_TABLE_ROW (dt_int16, int16_t);
      FILL_TABLE_ROW (dt_uint16, uint16_t);
      FILL_TABLE_ROW (dt_int32, int32_t);
      FILL_TABLE_ROW (dt_uint32, uint32_t);
      FILL_TABLE_ROW (dt_int64, int64_t);
      FILL_TABLE_ROW (dt_uint64, uint64_t);
      FILL_TABLE_ROW (dt_single, float);
      FILL_TABLE_ROW (dt_double, double);
      FILL_TABLE_ROW (dt_char, char);
      FILL_TABLE_ROW (dt_schar, signed char);
      FILL_TABLE_ROW (dt_uchar, unsigned char);
      FILL_TABLE_ROW (dt_logical, bool);

      initialized = true;
    }

  bool swap = false;

  if (ffmt == octave::mach_info::flt_fmt_unknown)
    ffmt = float_format ();

  if (octave::mach_info::words_big_endian ())
    swap = (ffmt == octave::mach_info::flt_fmt_ieee_little_endian);
  else
    swap = (ffmt == octave::mach_info::flt_fmt_ieee_big_endian);

  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);

  switch (output_type)
    {
    case oct_data_conv::dt_int8:
    case oct_data_conv::dt_uint8:
    case oct_data_conv::dt_int16:
    case oct_data_conv::dt_uint16:
    case oct_data_conv::dt_int32:
    case oct_data_conv::dt_uint32:
    case oct_data_conv::dt_int64:
    case oct_data_conv::dt_uint64:
    case oct_data_conv::dt_single:
    case oct_data_conv::dt_double:
    case oct_data_conv::dt_char:
    case oct_data_conv::dt_schar:
    case oct_data_conv::dt_uchar:
    case oct_data_conv::dt_logical:
      {
        conv_fptr fptr = conv_fptr_table[input_type][output_type];

        retval = fptr (input_buf_list, input_buf_elts, elts_read,
                       nr, nc, swap, do_float_fmt_conv, do_NA_conv, ffmt);
      }
      break;

    default:
      ::error ("read: invalid type specification");
    }

  return retval;
}

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, octave::mach_info::float_format ffmt,
                     octave_idx_type& count)
{
  octave_value retval;

  octave_idx_type nr = -1;
  octave_idx_type nc = -1;

  bool one_elt_size_spec = false;

  if (! stream_ok ())
    return retval;

  // 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.

  // Expose this in a future version?
  octave_idx_type char_count = 0;

  count = 0;

  try
    {
      get_size (size, nr, nc, one_elt_size_spec, "fread");
    }
  catch (const octave::execution_exception&)
    {
      invalid_operation ("fread", "reading");
    }

  octave_idx_type elts_to_read;

  if (one_elt_size_spec)
    {
      // If NR == 0, Matlab returns [](0x0).

      // If NR > 0, the result will be a column vector with the given
      // number of rows.

      // If NR < 0, then we have Inf and the result will be a column
      // vector but we have to wait to see how big NR will be.

      if (nr == 0)
        nr = nc = 0;
      else
        nc = 1;
    }
  else
    {
      // Matlab returns [] even if there are two elements in the size
      // specification and one is nonzero.

      // If NC < 0 we have [NR, Inf] and we'll wait to decide how big NC
      // should be.

      if (nr == 0 || nc == 0)
        nr = nc = 0;
    }

  // FIXME: Ensure that this does not overflow.
  //        Maybe try comparing nr * nc computed in double with
  //        std::numeric_limits<octave_idx_type>::max ();
  elts_to_read = nr * nc;

  bool read_to_eof = elts_to_read < 0;

  octave_idx_type input_buf_elts = -1;

  if (skip == 0)
    {
      if (read_to_eof)
        input_buf_elts = 1024 * 1024;
      else
        input_buf_elts = elts_to_read;
    }
  else
    input_buf_elts = block_size;

  octave_idx_type input_elt_size
    = oct_data_conv::data_type_size (input_type);

  octave_idx_type input_buf_size = input_buf_elts * input_elt_size;

  assert (input_buf_size >= 0);

  // Must also work and return correct type object
  // for 0 elements to read.
  std::istream *isp = input_stream ();

  if (! isp)
    error ("fread: invalid input stream");
  else
    {
      std::istream& is = *isp;

      std::list <void *> input_buf_list;

      while (is && ! is.eof ()
             && (read_to_eof || count < elts_to_read))
        {
          if (! read_to_eof)
            {
              octave_idx_type remaining_elts = elts_to_read - count;

              if (remaining_elts < input_buf_elts)
                input_buf_size = remaining_elts * input_elt_size;
            }

          char *input_buf = new char [input_buf_size];

          is.read (input_buf, input_buf_size);

          size_t gcount = is.gcount ();

          char_count += gcount;

          octave_idx_type nel = gcount / input_elt_size;

          count += nel;

          input_buf_list.push_back (input_buf);

          if (is && skip != 0 && nel == block_size)
            {
              // Seek to skip.
              // If skip would move past EOF, position at EOF.

              off_t orig_pos = tell ();

              seek (0, SEEK_END);

              off_t eof_pos = tell ();

              // Is it possible for this to fail to return us to
              // the original position?
              seek (orig_pos, SEEK_SET);

              off_t remaining = eof_pos - orig_pos;

              if (remaining < skip)
                seek (0, SEEK_END);
              else
                seek (skip, SEEK_CUR);

              if (! is)
                break;
            }
        }

      if (read_to_eof)
        {
          if (nc < 0)
            {
              nc = count / nr;

              if (count % nr != 0)
                nc++;
            }
          else
            nr = count;
        }
      else if (count == 0)
        {
          nr = 0;
          nc = 0;
        }
      else if (count != nr * nc)
        {
          if (count % nr != 0)
            nc = count / nr + 1;
          else
            nc = count / nr;

          if (count < nr)
            nr = count;
        }

      retval = finalize_read (input_buf_list, input_buf_elts, count,
                              nr, nc, input_type, output_type, ffmt);
    }

  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, octave::mach_info::float_format flt_fmt)
{
  octave_idx_type retval = -1;

  if (! stream_ok ())
    invalid_operation ("fwrite", "writing");
  else
    {
      if (flt_fmt == octave::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;
    }

  return retval;
}

template <typename T, typename V>
static void
convert_chars (const void *data, void *conv_data, octave_idx_type n_elts)
{
  const T *tt_data = static_cast<const T *> (data);

  V *vt_data = static_cast<V *> (conv_data);

  for (octave_idx_type i = 0; i < n_elts; i++)
    vt_data[i] = tt_data[i];
}

template <typename T, typename V>
static void
convert_ints (const T *data, void *conv_data, octave_idx_type n_elts,
              bool swap)
{
  typedef typename V::val_type val_type;

  val_type *vt_data = static_cast<val_type *> (conv_data);

  for (octave_idx_type i = 0; i < n_elts; i++)
    {
      // Yes, we want saturation semantics when converting to an integer type.
      V val (data[i]);

      vt_data[i] = val.value ();

      if (swap)
        swap_bytes<sizeof (val_type)> (&vt_data[i]);
    }
}

template <typename T>
class ultimate_element_type
{
public:
  typedef T type;
};

template <typename T>
class ultimate_element_type<octave_int<T> >
{
public:
  typedef T type;
};

template <typename T>
static bool
convert_data (const T *data, void *conv_data, octave_idx_type n_elts,
              oct_data_conv::data_type output_type,
              octave::mach_info::float_format flt_fmt)
{
  bool retval = true;

  bool swap = false;

  if (octave::mach_info::words_big_endian ())
    swap = (flt_fmt == octave::mach_info::flt_fmt_ieee_little_endian);
  else
    swap = (flt_fmt == octave::mach_info::flt_fmt_ieee_big_endian);

  bool do_float_conversion = flt_fmt != octave::mach_info::float_format ();

  typedef typename ultimate_element_type<T>::type ult_elt_type;

  switch (output_type)
    {
    case oct_data_conv::dt_char:
      convert_chars<ult_elt_type, char> (data, conv_data, n_elts);
      break;

    case oct_data_conv::dt_schar:
      convert_chars<ult_elt_type, signed char> (data, conv_data, n_elts);
      break;

    case oct_data_conv::dt_uchar:
      convert_chars<ult_elt_type, unsigned char> (data, conv_data, n_elts);
      break;

    case oct_data_conv::dt_int8:
      convert_ints<T, octave_int8> (data, conv_data, n_elts, swap);
      break;

    case oct_data_conv::dt_uint8:
      convert_ints<T, octave_uint8> (data, conv_data, n_elts, swap);
      break;

    case oct_data_conv::dt_int16:
      convert_ints<T, octave_int16> (data, conv_data, n_elts, swap);
      break;

    case oct_data_conv::dt_uint16:
      convert_ints<T, octave_uint16> (data, conv_data, n_elts, swap);
      break;

    case oct_data_conv::dt_int32:
      convert_ints<T, octave_int32> (data, conv_data, n_elts, swap);
      break;

    case oct_data_conv::dt_uint32:
      convert_ints<T, octave_uint32> (data, conv_data, n_elts, swap);
      break;

    case oct_data_conv::dt_int64:
      convert_ints<T, octave_int64> (data, conv_data, n_elts, swap);
      break;

    case oct_data_conv::dt_uint64:
      convert_ints<T, octave_uint64> (data, conv_data, n_elts, swap);
      break;

    case oct_data_conv::dt_single:
      {
        float *vt_data = static_cast<float *> (conv_data);

        for (octave_idx_type i = 0; i < n_elts; i++)
          {
            vt_data[i] = data[i];

            if (do_float_conversion)
              do_float_format_conversion (&vt_data[i], 1, flt_fmt);
          }
      }
      break;

    case oct_data_conv::dt_double:
      {
        double *vt_data = static_cast<double *> (conv_data);

        for (octave_idx_type i = 0; i < n_elts; i++)
          {
            vt_data[i] = data[i];

            if (do_float_conversion)
              do_double_format_conversion (&vt_data[i], 1, flt_fmt);
          }
      }
      break;

    default:
      ::error ("write: invalid type specification");
    }

  return retval;
}

bool
octave_stream::write_bytes (const void *data, size_t nbytes)
{
  bool status = false;

  std::ostream *osp = output_stream ();

  if (osp)
    {
      std::ostream& os = *osp;

      if (os)
        {
          os.write (static_cast<const char *> (data), nbytes);

          if (os)
            status = true;
        }
    }

  return status;
}

bool
octave_stream::skip_bytes (size_t skip)
{
  bool status = false;

  std::ostream *osp = output_stream ();

  if (! osp)
    return false;

  std::ostream& os = *osp;

  // Seek to skip when inside bounds of existing file.
  // Otherwise, write NUL to skip.
  off_t orig_pos = tell ();

  seek (0, SEEK_END);

  off_t eof_pos = tell ();

  // Is it possible for this to fail to return us to the original position?
  seek (orig_pos, SEEK_SET);

  size_t 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 (size_t j = 0; j < skip - remaining; j++)
        os.write (reinterpret_cast<const char *> (&zero), 1);
    }
  else
    seek (skip, SEEK_CUR);

  if (os)
    status = true;

  return status;
}

template <typename 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,
                      octave::mach_info::float_format flt_fmt)
{
  bool swap = false;

  if (octave::mach_info::words_big_endian ())
    swap = (flt_fmt == octave::mach_info::flt_fmt_ieee_little_endian);
  else
    swap = (flt_fmt == octave::mach_info::flt_fmt_ieee_big_endian);

  bool do_data_conversion = (swap || ! is_equivalent_type<T> (output_type)
                             || flt_fmt != octave::mach_info::float_format ());

  octave_idx_type nel = data.numel ();

  octave_idx_type chunk_size;

  if (skip != 0)
    chunk_size = block_size;
  else if (do_data_conversion)
    chunk_size = 1024 * 1024;
  else
    chunk_size = nel;

  octave_idx_type i = 0;

  const T *pdata = data.data ();

  while (i < nel)
    {
      if (skip != 0)
        {
          if (! skip_bytes (skip))
            return -1;
        }

      octave_idx_type remaining_nel = nel - i;

      if (chunk_size > remaining_nel)
        chunk_size = remaining_nel;

      bool status = false;

      if (do_data_conversion)
        {
          size_t output_size
            = chunk_size * oct_data_conv::data_type_size (output_type);

          OCTAVE_LOCAL_BUFFER (unsigned char, conv_data, output_size);

          status = convert_data (&pdata[i], conv_data, chunk_size,
                                 output_type, flt_fmt);

          if (status)
            status = write_bytes (conv_data, output_size);
        }
      else
        status = write_bytes (pdata, sizeof (T) * chunk_size);

      if (! status)
        return -1;

      i += chunk_size;
    }

  return nel;
}

#define INSTANTIATE_WRITE(T)                                            \
  template                                                              \
  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,                           \
                        octave::mach_info::float_format flt_fmt)

INSTANTIATE_WRITE (octave_int8);
INSTANTIATE_WRITE (octave_uint8);
INSTANTIATE_WRITE (octave_int16);
INSTANTIATE_WRITE (octave_uint16);
INSTANTIATE_WRITE (octave_int32);
INSTANTIATE_WRITE (octave_uint32);
INSTANTIATE_WRITE (octave_int64);
INSTANTIATE_WRITE (octave_uint64);
INSTANTIATE_WRITE (int8_t);
INSTANTIATE_WRITE (uint8_t);
INSTANTIATE_WRITE (int16_t);
INSTANTIATE_WRITE (uint16_t);
INSTANTIATE_WRITE (int32_t);
INSTANTIATE_WRITE (uint32_t);
INSTANTIATE_WRITE (int64_t);
INSTANTIATE_WRITE (uint64_t);
INSTANTIATE_WRITE (bool);
#if defined (OCTAVE_HAVE_OVERLOAD_CHAR_INT8_TYPES)
INSTANTIATE_WRITE (char);
#endif
INSTANTIATE_WRITE (float);
INSTANTIATE_WRITE (double);

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: error is member fcn from octave_stream, 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: error is member fcn from octave_stream, not ::error.
      error (who + ": format must be a string");
    }

  return retval;
}

octave_value
octave_stream::textscan (const std::string& fmt, octave_idx_type ntimes,
                         const octave_value_list& options,
                         const std::string& who, octave_idx_type& count)
{
  return (stream_ok ()
          ? rep->do_textscan (fmt, ntimes, options, who, count)
          : octave_value ());
}

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: error is member fcn from octave_stream, 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: error is member fcn from octave_stream, 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;
}

octave::mach_info::float_format
octave_stream::float_format (void) const
{
  octave::mach_info::float_format retval = octave::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!");

  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 () : "";
}

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 = os.file_number ();

  if (stream_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 ())
    ::error ("could not create file id");

  list[stream_number] = os;

  return stream_number;
}

OCTAVE_NORETURN static
void
err_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)
    err_invalid_file_id (fid, who);

  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 ())
        err_invalid_file_id (fid, who);

      retval = iter->second;
      lookup_cache = iter;
    }

  return retval;
}

octave_stream
octave_stream_list::do_lookup (const octave_value& fid,
                               const std::string& who) const
{
  int i = get_file_number (fid);

  return do_lookup (i, who);
}

int
octave_stream_list::do_remove (int fid, const std::string& who)
{
  // Can't remove stdin (std::cin), stdout (std::cout), or stderr (std::cerr).
  if (fid < 3)
    err_invalid_file_id (fid, who);

  ostrl_map::iterator iter = list.find (fid);

  if (iter == list.end ())
    err_invalid_file_id (fid, who);

  octave_stream os = iter->second;
  list.erase (iter);
  lookup_cache = list.end ();

  // FIXME: is this check redundant?
  if (! os.is_valid ())
    err_invalid_file_id (fid, who);

  os.close ();

  return 0;
}

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);

      retval = do_remove (i, who);
    }

  return retval;
}

void
octave_stream_list::do_clear (bool flush)
{
  if (flush)
    {
      // Flush stdout and stderr.
      list[1].flush ();
      list[2].flush ();
    }

  for (ostrl_map::iterator iter = list.begin (); iter != list.end (); )
    {
      int fid = iter->first;
      if (fid < 3)  // Don't delete stdin, stdout, stderr
        {
          iter++;
          continue;
        }

      octave_stream os = iter->second;

      std::string name = os.name ();
      std::transform (name.begin (), name.end (), name.begin (), tolower);

      // FIXME: This test for gnuplot is hardly foolproof.
      if (name.find ("gnuplot") != std::string::npos)
        {
          // Don't close down pipes to gnuplot
          iter++;
          continue;
        }

      // Normal file handle.  Close and delete from list.
      if (os.is_valid ())
        os.close ();

      list.erase (iter++);
    }

  lookup_cache = list.end ();
}

string_vector
octave_stream_list::do_get_info (int fid) const
{
  octave_stream os = do_lookup (fid);

  if (! os.is_valid ())
    ::error ("invalid file id = %d", fid);

  string_vector retval (3);

  retval(0) = os.name ();
  retval(1) = octave_stream::mode_as_string (os.mode ());
  retval(2) = octave::mach_info::float_format_as_string (os.float_format ());

  return retval;
}

string_vector
octave_stream_list::do_get_info (const octave_value& fid) const
{
  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 or integer value");

  return do_get_info (int_fid);
}

std::string
octave_stream_list::do_list_open_files (void) const
{
  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 << "     "
          // reset necessary in addition to setiosflags since this is one stmt.
          << std::resetiosflags (std::ios::adjustfield)
          << std::setiosflags (std::ios::left)
          << std::setw (3)
          << octave_stream::mode_as_string (os.mode ())
          << "  "
          << std::setw (9)
          << octave::mach_info::float_format_as_string (os.float_format ())
          << "  "
          << os.name () << "\n";
    }

  buf << "\n";

  return buf.str ();
}

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, stdout, and stderr 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");

      retval = int_fid;
    }

  return retval;
}